Django Login using Access & Refresh Tokens

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Seems easier just to use ldap3, no?

👍︎︎ 1 👤︎︎ u/gbdavidx 📅︎︎ Feb 19 2022 🗫︎ replies
Captions
in this video we will log in using access and refresh tokens as you can see the response returns an access token and also we will get a refresh token in the cookies we will use the access token to get the authenticated user and we will add it in the headers like this i will copy this access token i'll add it to the bearer headers and i will get the authenticated user and if this expires so this will expire in 30 seconds we will post to the refresh endpoint to generate a new access token which if you if we use it it will work the same before we start building the app i would like to remind you that this video can be combined with other videos so if you want to use django with any of these front-end frameworks i provided some links in the description of this video so after you finish this video make sure to pick one of these front ends now let's build the app we will start with a pre-built jungle app that contains the main files in the app directory and also another app core which will contains our models and serializers in our app directory in the settings file we need to add to the installed apps the rest framework course headers and core which is this app course headers is really important because we will use multiple front ends to consume this jungle apis and we need to install this package otherwise we will have course problems to install this package run pip install jungle course headers and when we install this package we need to add also this course middleware here and in the end we need to add course origin allow all and course allow credentials to true this is required because our front ends will have a different port than our backends and we will have course problem unless we add this line and the second line is needed because we will send the cookies to the front end and if we don't add this we won't be able to send cookies to the front end and that's it for this package next is the database connection which i will connect to mysql currently this is an empty database here this is a way to connect with mysql but you may connect with a different database it is the same and what is the left we need also this house user model here which is our core user so if we go to the models we will see that we have a user model here that contains a name an email and a password the email should be unique and i set these values to none because these are added automatically by django and i don't want to add them in the database also this change here is when we log into django admin we will use the email and not the username like this and that should be it so with this we can run a python manage that pi make migrations so we created the migration here the initial migration and now just migrate so i'll run migrate so this will create tables in our database if we see here we will create 10 tables and this is our core user table with the name email and password which we need also these values will be added to the serializer here so if you don't know serializers this may be confusing for you so you may check my other video on django jwt authentication there i will explain how serializers work so here simply i define the model which is this user model i define all the fields that we need to return in the response and to override them the password won't be returned in the response because it is only write only so only when we create the user we use this field and when we create the user we want to use the built-in jungle function set password to hash our password because if we don't add this function the password will be stored as it is in the database and we don't want that we want to hash the password and the way to do it is by extracting the password from the inputs creating the user here and then from the user we will use the built-in function and saving the user and that should be it now let's create our endpoints so in our urls here i added this path which starts with api and then it will include core urls so it is this file here which we don't have any urls so let's add one first we need to create a view and i will create the api view here register api view will extend from api view i will import this from rest framework views import api view and this will have a post request so dev post and i'll pass in the end so this is a basic skeleton for a simple post request that does nothing in the urls now i will add the path register and this will be from views we need to import register api view and i will add it here register api view as a view so we added our first endpoint which does nothing currently so this endpoint will create a user let's do it this request will contain all the information that we need so we need to use the serializers now i'll create a serializer is equal to user serializer i will import it so from serializers import user serializer i'll pass there request that data so i'll pass whatever we send in the request next i will check if this is valid if it's not we will raise an exception to true and then in the end we will return response which i will import it from there is a lot of imports here i think is the rest framework response and inside we need serializer that data i forgot to save it so serializer save here and that should be it so it is this simple now what is left is to test this endpoint first we need to run the server so run python manage that by run server it will run our server on port 8000 and now let's test this endpoint and to test it we need to use a tool like postman go to postman.com and make sure you download that software i will open the software now and now we need to send a post request to http localhost port 8000 slash api slash register i'll select the body row json here and we'll send a name of a email of ata.com and the password of a also make sure to change this to data is equal to requested data because uh before i forgot to add this now let's send this request and indeed we returned a user so we have also the id of one if we check the database we'll see that we have a record now that contains a name email and a password which is hashed and also the password wasn't returned in the response so this is what this user serializer does now let's use this user that we just created to login so i'll create another class here login api view will extend from api view this will be also a post request and i'll pass for the moment and i'll go to the urls i'll duplicate this i'll import login api view here and this will be login and this is login api view so what do we want to do here we already created a user and now we need to get that user so we will send in the request an email in the password first we'll get the user which is equal so let's import it here from user from models import user and user will be equal to user objects filter where the email is equal request the data email like this and we will get the first value if the user is not set so if not user then we will raise an exception so exceptions i need here rest framework exceptions i will import api exception so api exception with a message invalid credentials so if the user is not set if we go here it means that we found the user with that email and we have to check the password so if not again user check password with the request that data password here so this will return true if the password is correct and false if the password is incorrect if we add not here it means that it will erase an exception if the password is incorrect and i'll raise the same exception and if we go here it means that the response is successful i will get the user serializer here so serializer is equal to user serializer with the user and i'll return response of serializer that data so let's check this login i'll copy this url paste it here this will be a post request and we will send an email which is aet.com and the password which is a so i'll put the wrong password first the wrong email sorry it seems i forgot to change this to login and let's send it again and we get invalid credentials if i put the wrong password i get again invalid credentials and if i put the correct email and password we get the user so everything is correct right now now we want to return an access in the refresh token so to do that we have to create gwts so json web tokens which basically are this kind of tokens that when they can be decoded we'll have some extra information to use those we have to install this package pi jwt so i will install it right now now that we installed the package i will create in the core project a python file authentication and here we want to create an access and the in the refresh token so i'll paste it immediately and let's import what we need so first from we need to import jwt here we need to import also date time and that should be it so to create an access token we need the id of the user and we will use jwt encode here and this is the information that we want to encode as i said before it will create this token and inside the payload will have the user id that we want this is the expiry time so this token expires in 30 seconds and this is the creation time which is now we need a secret so i will call it access secret and we need also an algorithm the same will be for the refresh token so i'll rename this to refresh i'll store the same user id and the expiry time will be days seven so this will expire in seven days and this is refresh secret when we create an access in the refresh token the access token should be short-lived so i put it 30 seconds here and the refresh token should stay longer so we created these functions and now in the views i will remove this serializer now we don't need it we need to create an access token which is equal to create access token with the user dot id inside so if i import this i will get the from authentication import create access token the same will be for the refresh token i will import it here also create refresh token and we will have these two tokens now returning them will be different so the access token will be returned in the response like the serializer here and the refresh token will be returned as a cookie how do we do that so first i'll get a response here which is equal to response and i will set response that set cookie i'll call it refresh token and the value will be the value refresh token and we need also to be http only to true so http only means that the backend can only get this cookie the front end will get this cookie but it won't be able to access it so the only purpose of this cookie is to be sent in the backend so i forgot here the key is refresh token and the value is this value and now we want to set the access token so the access token will be set in the response that data is equal to token the access token and that's it so we will return a response in the end so let's test this endpoint now so before it returned the user now if we send a request we will get the access token in the body and we will get also cookie here which is the refresh token which is also http only so that's it the front end will get both of these values and now we want to get the authenticated user so for that i'll create a class user api view will extend from api view and this is a get request this request here let's pass for the moment and let's add it to the urls so this is user user api view so let's import it here user api view user api view so i added this endpoint and now what do we want to return here so first we will get the access token from the headers and the way to do that is like this so i will import this get authorization header from rest framework auto authentication so we will get the [Music] header authorization we will split it so the first parameter will be the better and the second will be the actual token and here we will make the condition if we have a value and the length of that value is 2 which means that we have a bearer and the token the token will be the second value and we have to decode it to utf-8 so this will be the access token now that we got the access token we need to decode it and for that i'll go again to the authentication.pi file and here i will add the function to decode it i will paste it directly and i will import here the jungle exceptions where is it rest framework exceptions and in this decode function we simply pass through the token also the second parameter is the secret and also the algorithm in the end i want to return just the user id i don't need the other information if this fails for some reason we return unauthenticated so that should be it so while i am at it i will add also the decode refresh token and this will accept the refresh secret so it is the same now i'll go back to the views and i will get the id of the user which is equal to decode i will get it here decode access token and also decode the refresh token the id will be equal to decode access token and i'll pass the token so if this is successful then we can get the user so the user is equal to user objects filter where the primary key is equal to this id and we will get the first value and that is the authenticated user so i will return it as a response as a user serializer here so i will remove these hints i'll pass here the user and i want the data so i did this in one line the long way is like this but i did it in one line if we have some kind of error in the end here i will erase an exception so i'll copy this line i'll go back and i will erase authentication failed exception and that should be it so this is how we get the authenticated user so what is the problem here i get the api exception and i need here so my bad authentication failed let's test this endpoint now i'll copy the url here paste it here and this is user also when we switch tabs on postman if we have a cookie here the cookie will be preserved also in this endpoint so we get the cookie we get unauthenticated because we need to add the header the authorization header as a bearer the second value will be this token i will paste it here send a request and i still get unauthenticated why is that the reason because the token will last only for 30 seconds and this has probably expired so i will log in again get a new token and i'll paste it here immediately and now i get the authenticated user so it is working fine but this user will last only for 30 seconds because we need to refresh that access token if it expires so let's add now another endpoint to refresh that access token so i'll call it refresh api view api view here and this will be a post request request i'll pass it for the moment let's add it to the urls refresh let's get it here so this is refresh api view refresh api view so what do we want to do here so i have an error so in this refresh api view we want to get the refresh token we have to validate that token and then we need to generate a new access token so this will be the really simple so we have to get the refresh token is equal to request cookies like this get refresh token so we will get to the refresh token from the cookies and now we have to decode it so this will return the id so decode refresh token and i will pass this refresh token if something fails here we will return also unauthenticated if it doesn't fail we'll get the id of the user which we will get a new access token which is equal to encode or create access token with the id and in the end we will return that token return response with the token access token like this so it is this simple we just get the refresh token from the cookies we decode it we generate a new access token and that should be it so let's test it now uh this user probably has expired right now and we returned unauthenticated but we have the refresh token cookie so i will open a new tab now and this is refresh and this will be a post request we don't want to send anything in the body just send this request and we will get a new token which i will copy and i'll paste it here and it works so that's it so now this looks really annoying uh if we refresh all the time get a new token and then we have to paste it here but this will be done very easily on the front end so this is not the job of the back end to replace the tokens we added the refresh api view and what is left now is to add the last function which is a logout api view as an api view this will be a post request and this i'll pass it for the moment let's add it to the urls let's add here logout api view and this will be logout and this is logout api view and this function will be very simple we will simply remove the refresh token to remove the cookie we have to get the response is equal to response response delete cookie with the key refresh token and response we need the body so the data of the body will be message success and we return the response and that's it it is this simple we probably don't need the request so i'll put an underscore here this means that it won't be used and let's test it now i'll copy this paste it here and this is logout this is a post request let's send the request and we get success and we removed the cookie this means now that when we get the authenticated user we get unauthenticated but even if we refresh the end point we still get unauthenticated so that's it we completed what we need in order to use access and refresh tokens so i have only one small last problem which this is only on my case on your case it you will probably be okay with this information the status that i return or jungle returns is 403 4 billion and forbidden i combine multiple frontends with backends and all the backends should return 401 only in jungle i have this kind of problem and the way that i want to fix this problem is like this i will create another python file here i'll call it exceptions and i'll paste this function so you also import here from rest framework views import exception handler and what does this function do so we will get a response and we will check here that if the response is known and it has a status code of 403 which is now in our case is this i want to change the response code to 401 so this is just a simple bug fix that uh i want to all the front ends and the back ends i want to synchronize them in your application you don't have to do this so i just did it for the sake of the combinations and now i added this function i'll go to settings and i'll paste it here this i will add the rest exception handler for the rest framework which is located in core exceptions status called handler and this i will save it now i will get the same response and this time is unauthorized 401 so all the front-ends now will be based on this 401 error and that's it we completed the authentication with access and refresh tokens in the backend in the jungle part now to complete this app you need to build one front end also if you want a more complex project i provided in the links of the description of this video the ultimate authentication course with django and react but you can pick any frontend that you want in this course you will learn more complex uh stuff like login with a two-factor authentication with your google authenticator and social authentication using your google account so you can get this course here on scalable scripts on udemy or you can get all my jungle courses for just 8 dollars a month if you are not in europe and if you are in europe for 9.52 per month so is up to you thank you for watching this video don't forget to like share and subscribe thank you
Info
Channel: Scalable Scripts
Views: 10,543
Rating: undefined out of 5
Keywords: coding, programming, full stack development, scalable scripts, programming tutorials, developer, coder, software, laravel, react, vue, angular, django, python, nestjs, nextjs, nuxtjs, golang, denojs, nodejs, microservices, docker, kubernetes, rabbitmq, kafka, event driven architecture, event driven design, containers, mircorservices architecture, api, spa, single page application, c#, java, kotlin, .net core, java spring boot
Id: l6Pfu4L_y_k
Channel Id: undefined
Length: 31min 37sec (1897 seconds)
Published: Thu Feb 17 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.