JWT Authentication (Create Access And Refresh Tokens) - FastAPI Beyond CRUD (Part 9)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's up everyone welcome back now in this video we're going to be looking at JWT authentication in the previous video we built a user authentication model and an API endpoint for helping us create those user accounts in this video we going to build on top of that to allow users identify themselves so that they can gain access to any part of our application that is protected we're going to be carrying out JWT authentication JWT authentication is basically a client side form of authentication where users are going to identify themselves by using jwt's now JWT stand for Json web tokens and this is a standard for transmitting claims or information among two parties for our case is going to be our client and then our server JWT is are credentials or information that is going to be about anything so in our case is going to be majorly about the users who are authenticated this information is going to be inced in a Json format making it readable and then we're going to make this secure by using cryptographic algorithms to digitally say this ensuring authenticity and integrity a JWT is going to contain three parts the header or the information about the token the P which is the information that we want to store within that token and then the signature with the details about how the token was signed and in order these are going to be separated by a period character or what we call a full stop character if you go to this diagram right here we have a simple JWT and then on the right hand we have the various parts or the three parts of that JWT in the red right here we have the JT header which is going to have basically two things the algorithm which is hs256 as well as the type of the token in our case is going to be the JT the second part which is in purle is going to be the payload the claims of this token now in our case we see that we have three claims and this is going to be the sub or the subject of our token that's going to be some random user ID then we also going to have the name now our name in this case is going to be J and then we can also have the I and this is going to stand for the issue that time so you can now notice that we have some claims that we may provide but we can even leave them out so they are not that compulsory so we have the subject and we also have the issue that time now the third part right here is going to be the verify signature and this is basically details about how we're going to verify whether our token is it whether its signature is valid or not so basically these are the details about how we're going to go about that then this is the flow of normal JWT authentication at first the user will log in with their details such as the email or their password and once they logged in then the server is going to verify whether those credentials they have provided match what the server has kept on our database side upon a successful login the server is going to provide a JWT or an access token containing the user claim so this is going to have the information about the currently logged in user for any future requests the client is going to always send this JWT in its HTTP header so that they can be authorized to access this specific protected inps once the server gets that token it's going to verify the token signature and the pillow to ensure that that token is valid and is of that specific user and once the token is valid and the server is going to process the request otherwise it's going to reject the request depending on whether this token is valid or not so using JWT comes with some benefits and these are some of them so the first one is they are Compact and therefore we can send them via any way so we can send them via our URL through path and query parameters we can also use request body or we can send them via post request using our request body we can also provide this as headers to our requests just like we're going to be using in this video they are self-contained meaning that you can keep all information that we want to keep Within These tokens allowing us to not query the database very often so for example when we provideing user information when the user has logged in we can make use of that token and store all the information about the current logged in user so that we don't have to fetch them from that database and this is important they are secure in a way that we use cryptographic algorithms and these crypto algorithms are going to allow us to ensure that this are going to be confidential and only access by the parties that will be in need of them then we're also going to look at another Advantage which is they can be used across different domains so if you have a micros service type of application you can ensure that your authentication is shared across very many other services without having to implement authentication for all those services so I hope you've understood what jts are and let's get right into the video so the first thing we're going to do is to head over to our code I'm going to go within our vs code and I'm going to open up new terminal inside new terminal I'm going to install P JWT with Pip install P JWT and this will go ahead and install P JWT once P JWT has been installed we're going to head over to ours. P file that we created in the previous video and then we're going to create two functions so the the first function is going to be one to help us encode our token so shall just simply create access token so this is one for creating our access tokens and this will take in whatever user data that we're going to require to create the token so this is going to be a dictionary and then we're also going to pass in the expiry or the tokens so this is going to be a time Delta object and therefore we shall have to import time Delta so I'll go operate here and all I have to say is from date time we are going to go ahead and import our time Delta class and then we shall also import our dat time class once you've imported that then we simply going to go ahead and create our tokens so for us to create our tokens we should have to import pwt I'll come right here at the top and then I say import JWT once we've imported JWT then we are simply going to create our tokens token is going to be equal to JWT do encode and inside here is where we shall provide the arguments that are needed to create an access token now the first one is going to be our payload and the payload is going to be the data that we want to encode as a Json object within our token now I'll create this as an empty dictionary for now so I'll say pad is going to be an empty dictionary and once you've been able to do do that then we shall just pass in our payload another thing we shall need is going to be the key so the key is going to be the secret key that pwt will use to sign our token so we're going to set this up within our environment variables so I'll search for myv and inside that is where I'm going to add the JWT separate key so this is going to be uh something that's going to be secret something you don't want to expose so to generate a random string I'm just simply going to be using the python Secrets module as it's going to allow me to create something that cannot be easily memorized so I'll just come right here and say Python 3 and inside here I'll say import secrets and I'll call a specific method or fun that's going to be the token hex function to create a random heximal string of a certain number of B now this is going to be rjt secr I'll copy it and then I'll paste it right here my EnV thing we shall need is the JWT algorithm so just going to set this with JWT algorithm and this is going to be the default which is HS 256 I'm going to save and when I save that then the next thing is going to be for us to make use of these two environment variables shall go back within .p and inside there is where I'm to provide to secret key but before I do that I'll have to set this to be read within our settings class so I'll go to our config file right here and inside our config what I'm going to go ahead and do is to add this true so I just come and add the JT secret so this will be a string and then I'll also add our JWT algorithm and this will also be a string all right now once I'm able to get this VR config object I'll just go ahead and include them here so I'll come in the to create here and import our config object so I'll say from source. config we shall go ahead and import our config and once that has been imported then let's go ahead and make use of our secret environment variables with config so in this case I'll just call a config object and Dot the environment variable this case it's going to be a JT secret another thing we I have to provide is going to be the algorithm so I'll just come right here and say algorithm and in this case it will be config JWT algorithm so once this has been called then what we shall have is going to be our access token or our JWT now let's go ahead and return this I'll say return and in that case we shall return our JT so thing is going to be to encode data or claims within our token so the first thing we have here is going to be our user data and we just simply going to provide it as a key so shall say payload user is going to be equal to the user data another thing we shall set is going to be the expir so we shall say payload and this is going to be the EXP claim and this shall be the expired date but in this case we need to add this to the time that is now so we shall make use of dat time do now and we shall go and ahead and add our our specific expiry so in this case it's going to be our expiry but we shall provide a default for this in case we do not have the expired set so we can simply go ahead and say the expired date has a default value of n so if we do not provide a default a default time then we shall go ahead and make use of of our default time or default expir of token so I'm just going to come at the top right here and I'll create a constant and this constant is going to be the access token expir so this is going to be amount of time in seconds so I'm going set it to the amount of time of sequence in an hour and that is going to be uh 3,600 so what I'll do is to just Cate here and then say the I expir is going to be day time now plus the expiry if our expir is not n so I'll just set this to be if expiry is not n else so in this case this will be else and we shall set it to R time Delta and in this case we shall have seconds being equal to the access token expir so I'll just put this in Brackets just Lael it as one statement and what this will do is to provide a default expiry just in case we do not provide the expiry within the create access token function another thing we shall do is to provide a unique ID to each of the tokens that you shall create and we going to achieve that is by using the U ID module so I'll go ahead and import it I'll say import U ID and once I've imported you ID then I'll come bottom right here and say payload in this case I'll set the optional jti claim and this is going to be uu ID do uid 4 so remember that this creates a uu ID object and we need to go ahead and serialize this in a Json serializable format so we have to convert this to a string by saying string U ID do id4 once that is done then we are also going to go ahead and set what else should we set so this is going to be the user data the expir of this token and whether it's a refresh token but then what you can do is to go ahead and simply say that we shall need an optional refresh token parameter so I'll just come right here and add it so shall say refresh and this is going to be a Boolean and in this case we shall have false because this function is going to create both access and refresh tokens now refresh tokens are going to be more long lived compared to our access tokens and our access tokens are going to have a short lifespan while the refresh tokens will be used to get more tokens in case our access tokens are expanded so what you're going to do is to go ahead and set that up so you shall say pad and in this case shall specify refresh and in this case our refresh claim is going to be equal to the value of refresh and this is going to be just enough for us to create our tokens now the next thing we're going to do is write the function that's going to be necessary for the coding these tokens so for us to do that shall just come right here and shall Define a function so this is going to be our uh this is going to be a decod token function and this function shall take in a token which is going to be a string and this will return the data contained within the token as a dictionary now for us to decode that token all we have to do is to just simply create a variable let's call this our token data and our token data in this case is going to be a result of calling JWT do decode and this is going to take in almost the same things but instead of the payload it will take in the JWT which shall be the token and then we shall need our secret key so in this case shall provide that key which shall be our config Dot JWT secret another thing we shall provide is algorithms so algorithms is going to be a list of algorithms that shall use to decode the token and this case we shall have our config JWT algorithm so this will be the only algorithm that shall use to decode our token now there are very many chances that you're going to land in erors when we decode the token so we may catch things like the token being expired or the signature verification failing link and that's where we need a try cash so in this case shall say try except because this is python so we using try and accept so I'll say try then shall decode the token and then return the token so in this case we are returning the token data and in case we fail to decode the token then we going to accept any error but in this case what we want to do is to accept p W specific errors to do that what we're going to do is to come right in here and then we shall do something like except JWT do PI JWT error so in this case I'll just say Pi JWT error so that's going to be the best class for all these exceptions that P jw2 is going to raise so shall access P jw2 wonder why I'm writing this wrong so this going to be appt error and then in case we are interested in doing anything with that we can simply say as e so what I'll do is to go ahead and raise an exception or what we can do is to Simply go ahead and log it so I import logging and once I've imported logging then what you shall do in this case is simply go ahead and log that exception so I'll say loging to exception and in this case shall log our error once we've been able to log the exception the next thing is going to be for us to Simply return none in case our token has not been decoded and that's it for creating the functions for encoding and decoding our tokens now the next thing we're going to do is to make use of this function so that we can be able to log in a user and provide for them both access and refresh token so to do that we're going to go to our routes and shall Begin by importing those two functions so we're going to go ahead and say from doils we're going to go ahead and import our create access token function and then we shall import our decode token function so once we've been able to import this then the next thing we're going to do is to go ahead and create the route or the path that's going to be necessary for us to log in so to log in what you shall do is to get user details check if these user details mat what we have in the database and then provide the access and the refresh token and in case we do not match those then we shall throw an exception showing the user that they have invalid credentials so let's go ahead and do that shall Begin by saying at AU router dopost since we're going to be making a post request and our path in this case is going to be our SL login so once we've done that we're going to Define our Handler for this as login users and and this is going to take in the user login data so we shall pass this for now so we're going to go ahead and create a schema for the information that shall be needed when the user is logging in so you're going to go to schemas py inside our o and there is where we're going to go ahead and create our model app identic model for logging in a user so we shall say user login model and this is also going to be a pantic based model so I've written this badly so I have to go ahead and Define the fils that we need so going to need both our email as well as our passwords so I'll go ahead and provide them right here once this is done then we going to go ahead and import this so I'll just come in the top right here where imported our user create model as well as our user model and that I'll do is to go ahead and import our user log model for us to make use of that user log class shall have to inject it within our Handler as a parameter so in this case this is going to be the can call it the login data or the user login data whatever you prefer and this shall be of type user login model once this is done then we're simply going to go ahead and access those details so shall say email and our email is going to be the login data. email and we shall also have our password so our password in this case is going to be the password from our login data so shall just access that as login data. password and the first thing we shall do is to make use of our user service object we created to check if that user exists so to do that we shall just come right here and say user is going to be equal to await user service dot in this case we shall call a get user by email function so this will take in the email of that user as well as the session so we shall provide our email right here but we need to get the session object so we have to go ahead and use dependence injection just like we did for the previous video I'll come right here and inject it within this path Handler and once we've been able to do that then we're going to Simply go ahead and provide our session right here and once our session has been provided now we can have access to our user object so the first thing going to do to check if this user exist so we shall say if user is not none then in this case we shall go ahead and check if their password or the password they have provided matches the hash that we have within our database so we created a function within our utilities and that is going to be our verify password so this verify password function uh takes in the provided password and then checks whether it matches the one password has that we have in our database and returns true or false depending on whether it matches or not so in this case what shall do is to create a Broan so we shall create a bran called password valid and in this case we are going to go ahead and call that function so we shall say verify password and this will take in our password so it will also take in the hash of the user from the database so shall say user do password hash and once that has been done then we're going to use that as what to check if the user actually exist and their password is correct so we shall say if password valid then we shall create both the access and the refresh token for this user so to create the access token we shall say that our access token is going to be equal to a call to the create access token function and in this case we shall create our user data so I'm just simply going to go ahead and say that our user data is going to be equal to a dictionary containing the user data and insight here we shall just have the email and this is going to be the email of that specific user so shall say user do email and then we shall also pass in the user U ID so this user U ID is going to be the ID of the user so this is going to be user do uid but remember this user uid is being stored as a uid and therefore we have to stringify it so I'll say string and in this case I provide our user ID so once this is done then let's go ahead and provide our so we shall not actually provide an expiry and refresh this will be kept to the default Valu so in case we did not provide one uh this utils function is going to go ahead and provide the access token life LIF span or the time Delta which shall be our expiry which we set to 300 3,600 seconds which is an hour so I'll go back to our out right here and then we're going to create the refresh token so I'll say that our refresh token so it's going to be our refresh token and the refresh token shall also be the same but in this case what we're going to have is something with the expiry and that expir will also be longer than what we have for the access token so it's going to have the same details but in this case we shall go ahead and provide refresh as true so shall say refresh is going to be true and then we shall also provide our expiry so our expiry shall be something longer so in this case we can provide this as a Time Delta so I'll go at toate and import the time Delta class so I'll save from date time we shall import time Delta and once you imported time Delta now what you're going to provide here is going to be time Delta and in this case provide days being equal to two so you can also go ahead and set that up or we can actually just come right here and say refresh so this can be a refresh token expiry and this will be equal to two and then you can go ahead and set this up to be today so I'll just Cate and say refresh token expir so once these have been done then what you're going to do is to return a Json response showing the user that they've successfully logged in and we're going to do that is by making use of the response Json response class from first so we're going to go ahead and import it by saying from P API do responses or sorry for this this going to be responses uh we're going to go ahead and import the Json response so we shall just come right here and then say return our Json response and then this is going to to contain the content so our content is going to be dictionary and this dictionary shall have a message so this message shall be uh login successful and then and then we shall also provide the token pair so in this case we shall have our access token so our access token is going to be the access token and then we shall have our refresh token being the refresh token so in this case I say refresh token so once this have been provided then we can also maybe provide some little details about the user who has logged in so we shall say user and this shall be a dictionary containing the user email so the user email is going to be user do email and then we can also have the user username or let's say the user's email and then let's say the user ID so I'll say uid and then we shall provide the user ID so I'll say user do uid so this shall also be a string because this is going to be adjon response so I'll make it a string by simply calling string and then wrapping it in there so this will be enough for us to Grant access to a user now in case these two functions do not pass or these two if statements do not pass then we are simply going to go ahead and raise an exception so I'll do that with race and in our case we shall raise the HTTP exception and this shall have our status code being equal to status do HTTP 400 or this is actually going to be HTTP 43 forbidden and then our detail is going to be invalid email or password so we're going to go ahead and save and once we save then we shall go ahead and test this in our rest Fox so I'm going to head over to rest Fox and I'm going to create a new request within this folder we created for our authentication routes so I'm going to go in here and say uh login users so I'll simply call it create token pair so once I've created this then shall go ahead and say that this is going to be a post request and it's going to be one to that specific login endpoint so shall just come right here and say SL login when you send this without the body we're going to need to provide it so I'll come and provide ad Json and this is going to have our username so our username in this case is going to be John door actually in this case we're logging in the email and password I don't know why I'm forgetting this so I'll just have to change this key to email which is joho and this is going to be at company.com just like we saw in the previous video and then we shall have a password being our simple password of test 1 2 3 so once I provide this details and I press okay so we have an error let's go ahead and see what that is um this error is saying that we module U ID has no attribute U ID for so I made that mistake I think I made it in utils.py I'll just simply go ahead and call id4 so I head over that way and save now we shall see that our response is being returned with both an access and a refresh token so these are what we use to basically give a user a session I hope you've enjoyed this video and I'll see you in the next video we're going to go ahead and build on top of this to allow access to endpoints only when users provide their access token
Info
Channel: Ssali Jonathan
Views: 482
Rating: undefined out of 5
Keywords: fastapi, jwt auth, jwt, pyjwt, python3, fastapi jwt auth, jwt toiken auth
Id: NJu0tmwb3n0
Channel Id: undefined
Length: 31min 21sec (1881 seconds)
Published: Tue Jun 18 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.