Authenticating a Flask API Using JSON Web Tokens

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey everyone in this video I'll be showing you how to authenticate a flask API using JSON web tokens so if you've watched my previous two videos you would have seen that I covered how to use HTTP basic authentication in flask and also an introduction to JSON web tokens and the reason why I come for those in the last two videos is because for this video I need to use both those things and combine them in such a way for the authentication to work so in this video I'll cover the basics of doing it and then in the next video I'll create a more realistic example of how to use this in an actual API so this video will be fairly basic but it will have all the pieces that are necessary to do it so even if you didn't watch the next video you should be able to figure out how to do everything from this one so before I get started writing the code I just want to remind you that I have courses up on prettyprint calm so if you're interested in taking any longer flask courses that are more organized you can check out pretty printer comm and see the courses there I have a combination of free courses and premium courses so the first thing that we need to do for my API is set up a couple of routes one route will be for logging in another route will be a protected route so this route can only be seen if you are authenticated and a final route will be a route where anybody can see it so I'm going to do everything in the browser in this example but in the next video I'll use it I'll do everything to postman so it makes more sense but the browser should suffice for this example so the three routes I'll create are unprotected so this route will not be protected at all so any user of your API can call it and I'll show that in later and then I'll have a route called protected and this route will be only for people who are authenticated so if you don't pass in the correct token then you won't be able to view this route so I'll fill in the return later and then finally I'll have a route for logging in this route will be used to get the token that will be used to view the protected route so logging in you have to supply a username and password first then you'll get a token in return and then you can use that token for the protected route so call this login and I'll return the token later so what I want to import is justanna fie request and make response so just on off' I will be to return JSON objects instead of HTML request will be to get the incoming request data so in this example I'll get the login information and the token depending on the situation and they make response will be used to tell the browser or the API that HTTP basic authentication is required for login so to start I'll work on the login route and I'll ignore these two for now and with the login to route what I want to do is first I need to get the authentication or authorization information so if you saw the video on doing this then this will be very familiar but I'll explain briefly what's going on again so I've created a variable called auth it's going to be set to request that authorization so this will give me the username and password that is sent along with a request to this login route so then I want to check if this information actually actually exists so there is a username and password passed along with it and if it does exist in this case I only want to check the password because this is a simple example in the next video I'll make a more realistic example but for this one I'll just say off the password is equal to password so I don't care about the username um but in a realistic example you obviously will care about the username but in this case I only want the password and if the password is equal to password and I'll say that they are logged in correctly so I'll briefly skip what happens if the password is correct and I'll just simply add what happens if the password is incorrect or if they don't even supply your username and password so what I'm going to do is I'll make a response and I will say could not verify and I'll pass back a 401 ere telling them that they need to login and then finally I'll pass the headers saying that this is the HTTP basic login so wwl sense to Kate then to Kate so I spell that right then to Kate okay and then see basic realm and then I'll say login required okay so if the login information is incorrect or there is if the login information is incorrect or there is no login information then it's going to return nothing and if it is correct then or if it isn't correct and it's going to return I could not verify so that should say could not so let me just test that out really quick my app should be running no it crashed so I'll run it again okay so there's no route on the index I'll go to login and I see the Box pops up so if I put anthony's username and then password is the password that should log me in and nothing gets returned because i have nothing there so now what i want to do is if they are logged in correctly i want to return a token so how the api will work is they will log in once and after they log in they'll get a token in return they can then use that token on a subsequent request and then my server will automatically verify that that token is valid and that token will have information about who the user is so i know what data to send back in the response if anything is relevant to the particular user so i need to import a couple of things before I can use the token I need to import JWT for JSON web tokens so you need to have pi JWT installed so pip install pi JWT so import JWT and then I'm also going to import eight-time because i'm going to make sure the token expires after a while so now I'll go back down here to the return statement and I will generate a token so I'll create a variable called token and then I'll call JWT in code and in the payload for this token I want a couple of things I want the actual user who has logged in so I'll call it user here and off.not username so that's where the username comes into play it's not used to verify the authentication but it is used to identify who the user is and like I said this is a contrived example that's very basic it's just to show you the the basics of it and in the next example I'll show you a more realistic one and then I also have an expiration so this expiration is actually reserved a part of the payload in JSON web tokens and it basically tells you when the JSON web token will expire and to determine when it will expire first I'll get the current date at a time that the token is being generated so daytime daytime die UTC now so the expiration value needs to be a UNIX tile UTC date which is just like an integer and then I'm going to add an interval and that interval is going to be let's see date time dot time Delta and let's say minutes thirty minutes so what I'm doing is I'm setting this token to expire thirty minutes after it gets created so the idea is when someone logs in you give them a token you don't want that token to be valid forever you want that token to expire after some time so they will be forced to log in again it's just basic security obviously you don't want the tokens expire after 30 seconds otherwise they'd have to log in constantly and if you have the token expire after like a year then it's pretty much useless to have an expiration on there in the first place so thirty minutes is nice maybe 24 hours is more standard that depends on your case I'll just use thirty minutes here but this obviously can be changed at any value that you so after you have the payload information you have to supply a secret key so I'll just create the secret key in my app configuration so app config secret key and I'll say this is the secret key which is obviously a pretty bad secret key but that's the one I'll use here and I simply need to pass that into JWT in code so it's the next argument after the payload itself so config and then secret key and I'm going to use the default encoding algorithm so I won't add any value there so now I have the token here in this variable and what I want to do is I want to return this token to the user now return it in adjacent objects so return just on a Phi and up has it through the key token and I'll pass token there and since I'm using Python 3 this token is actually generated and bytes so I need to decode this token to be a regular string so decode and I'll do utf-8 if you're using Python 2 you may not have to do that so just check what you're looking for is BiBi ' before the actual token so now that I have all that I can test my login route again so I'll go back to login and since the information is still there from my browser I can see the token so here's the token and what I'll do is I'll actually take this token and I'll go to JWT i/o and I'll put it in their little debugger and on the right hand side you'll see the data that is in the payload so you see the user is Anthony and the expiration is that there which is a UNIX timestamp and the signature is invalid because the secret key is wrong but if I take the secret key that I have here and paste it in here it should come back clarified which it does so we can see that the token is doing what it's supposed to do so now that I can generate the token the next thing I want to do is I want to make it to where I can easily protect multiple routes that require the token to be available so what I'll do is I'll create a decorator that basically says check and see if the token is along in the request if it is get it and make sure the token is valid if it's valid then unless the user continued on to the actual view function for that route and if it's invalid and return a message saying that the token is invalid so pretty basic authentication thing so I'll create the decorator here which will be applied to my protected route and I'll just say token required is going to be the name so I need to pass in the function there and I need to import wraps from func tools so from func tools import wraps then what I'll do is wraps the same function which is the view function then I'll create the inner decorated function which takes the arbitrary arguments okay so now what I want to do is I want to get the token there are multiple ways to get the token from the requests so there are different ways that you can tell the consumers of your API to YouTube you can tell the consumers of your API how to pass along the the information for the token but in this case I'll do it in a simplest way possible and we pass through the query string so to get the token out of the query string I'll create a variable called token and I'll use the request dark skit token which is just giving the token other query strings so as an example it will look something like this HTTP and then local host for five thousand routes and then token would be blah blah blah all this right there so that's what I mean by query strings but in the next video and the more realistic example you an alternative way and probably a better way of having the users of your API pass the token to you so now what I want to do is I want to verify that this token is valid so I'm going to try because the following function on jwc decode will raise an exception if the token is invalid so I'm not going to catch the specific error in this case but in the next video a more realistic example I'll do that so I'm going to decode the token so the token is passed in through the query string and I need to supply the secret key again so app config secret key and if the token is able to be decoded then I will return the actual function the view function so keyword arguments there and if the token is invalid so the exception block gets activated I'm going to return a JSON object saying something like um message token is missing or invalid and actually I'll say the token is in valley in this case and what I'll say is if not token meaning there is nothing for the token I'll return - sana Phi token is missing so we can see both cases and I'll pass back a 403 here and now let's do 403 I'm not completely sure on the difference differences between 401 and 403 but they're pretty similar so anyway a 403 gets passed back and there's a missing and invalid one for this so this is actually pretty simple so now I'll just fill in the two routes I'll say for unprotected return to sana Phi say message anyone can view this and then I'll say for the protector route this is only available for people with valid tokens okay so the final thing I need to do here is at the decorator the token required decorator so the protected route is treated differently than the uh protector out so now if I go back to my browser and I go to unprotect it obviously did a crash yes let's see um on line 30 I have an error so where is line 30 so app routes unprotected token required so let's see I don't think I've ever seen this particular error before so I'll work with it with you token are required it's saying that token required is an issue oh and I think it's because I didn't return decorate it so return decorate it because I have to return this inner function so this outer function knows what to do so I think that's the air and that was the air so now I can go to unprotected and I see the message anyone can view this which is exactly what I want if I go to protect it I see the token is missing so now what I'll do is I'll input an invalid token so remember I'm using the query string so token and then I think it's still there well how about this this is the secret key that's obviously not the token so if I call that again it tells me that the token is invalid so what I need to do then is go to login which will give me the actual token so I'll copy and paste this then I'll go back to protect it touken and then I'll add the token and then it tells me this is only available for people with a valid token so that means I was able to get to the protected route so in the previous two when I tried it you saw that it ended in here in the decorator and it didn't even let me get to the view function but once I supplied a valid token then it worked correctly so now what I'll do is I'll set the token to expire in like 15 seconds so you can see what happens over time so I'll go back to the login route and I'll change the password too so it forces me to log in again let's say pastor is now secret so I'll go to the login route telling me to log in so my username will be Anthony again doesn't really matter in this case and the password will be secret don't save so it gives me a new token so let me quickly take that and go to protect it token and it tells me that this is only available for people with valid tokens so I'll keep refreshing and it's still valid and then all of a sudden it's invalid and that's because my token was set to expire after 15 seconds so as you can see the expiration works and if I want a new token then of course I'd have to go to login again get that new token and then supply it in each one as a subsequent request to any of the protected routes so that's pretty much it that shows you the basics of using the tokens for authentication so as you can see you don't have to pass in a username and password each time you want to authenticate yourself you simply pass the token along with the request and then that will allow the server to know who is requesting the information and if the person is allowed to access that data or not so like I said in the next video I'll create a more complete example so you out so you can see how it works in a real-life example how we'll work in the real world and that's complete everything on this topic so if you have any questions about this video like always just leave a comment down below and I'll get to it if you like this video please give me a thumbs up if you haven't subscribed to my channel already please subscribe I'll have a link to the code and the other videos in the description below so if you want to get that you can and finally check out pretty pretty calm for courses and Python and flask and that's it so thank you for watching this video and I will talk to you next time
Info
Channel: Pretty Printed
Views: 169,744
Rating: undefined out of 5
Keywords: flask api, flask api authentication, flask api jwt, flask api json web tokens, json web tokens, jwt, json web tokens authentication, python, pyjwt, flask
Id: J5bIPtEbS0Q
Channel Id: undefined
Length: 20min 33sec (1233 seconds)
Published: Mon Jun 19 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.