Authentication & Refreshing Tokens Implementation

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey what's going on everybody so in this video i want to show you how you can use json web tokens with django and react to add an authentication into your project now with this i also want to put a special emphasis on refresh tokens so i have a lot of questions about this and i don't see that many videos implementing this so what i want to do is cover things like how we can use a refresh token to update an access token how we can rotate refresh tokens and also how we can blacklist refresh tokens so with that we're also going to start from scratch where we'll set up our django project and we'll add in the django res framework and a package called simple jwt so simple jwt is going to allow us to change our authentication system in django so we're going to use the json web tokens for that now in the front end we're also going to use react so we're actually going to create these as two separate projects and we're going to make requests to the back end to get that token and then we'll store that token somewhere in the browser and that's how we know which user is logged in so before we get started i'm going to assume you already know a little bit about django react and refresh tokens because i'm not going to be focusing on the core concepts here we're just going to focus on how we can implement this and focus on that actual authentication flow here so let's go ahead and take a look at this project before we get started so this is a simple two-page project we can see that this is react on the front end and it's calling django in the back end to connect to things so here we have a simple login page if i try to go to the home page what's happening here is immediately it's hitting a private route and it knows that i'm not logged in so it redirects me back to the login page so that's actually something we'll build into this project so we're going to know how to build in those private routes and now if i log in i can actually see this user's information along with any database tables that are going to connect to that user so in this case later on in the project i'm going to create like a notes table and we'll be able to get that specific user's notes here so what's happening here is in this entire process there's different ways in how we can actually refresh that token so if i open up my inspect element here and go into application we're actually storing this token inside of local storage here so right here we see an axis and a refresh token and it's kind of this long character here or it's a really long character here so it's kind of hard to see all of it but what's happening here is every five minutes i'm gonna make a request to the back end and we're gonna use this refresh token to update this access token so if you understand how access and refresh tokens work typically you have an access token that stores all the information about a user and a refresh token that has a longer life span is meant to simply get a new access token so we have a short life span on that access token typically 5 to 15 minutes depending on how long you want to set that for and then a refresh token would change depend on how or depending on how secure you want your application or maybe how sensitive that information is in this case we can set that to a day we can set that to 30 days or even a year and always just make sure that a user can be logged in whenever they go to this website as long as they they were authenticated at one point so we're gonna build all this in here and that's how we're storing that so there's different ways of doing this i know some people like to use axios and axios has this let's see i forgot what that was called here it's called an interceptor and axios actually has this thing where whenever you make a request if that request fails this interceptor catches it it generates a new token and then it proceeds with that original request again that's one way to do that we can also do that with fetch i'm actually probably gonna make a video with axios and fetch after this to show you how to do that but in this case because those require a little bit more configuration we're just going to use the method of updating it every single five minutes so as we're working through this application we'll make that request we'll update that access token and we'll also generate a new refresh token and then update our local state along with the local storage so that's going to be the entire application here so let's just go ahead and actually start building this in so i'm going to close out this demo and i'm going to turn off the servers for that demo just get everything closed out here and let's start a new project here so i'm actually just going to go ahead and open up my command prompt i'm going to use windows here and let's just go ahead and get this started so i'm going to store my project on my desktop and for this i'm going to create a virtual environment so i'm going to use virtual env to create one and i'm not going over all the basics so if you don't know how this setup works i'd highly recommend you try to understand how to install virtual env and django and how to get that configured so i'm going to create a virtual environment called env we'll get that set up and then i'm going to add that virtual environment into my django project so we'll just activate that we'll just do env scripts and then activate and we'll just go ahead and do pip install django so that'll give me the latest version of django we'll get that set up here and once that's ready we're just going to go ahead and open up the text editor so that's going to take a second here okay so now we have django installed so i can go ahead and run django dash admin start project and we're going to call this project backend so the django side will just be called back end the react side we'll just call front end so i just want to make sure that's simple to follow and we just have two different sides of things so we'll go ahead and start configuring the back end right now so what i like to do is actually take this virtual environment and bring that into my django project so that's what that command did it just set up the boilerplate files you should be familiar with that already so let's go ahead and open up our text editor and for this i'm going to use vs code here so we'll go ahead and find this project so i'm going to use this terminal now we'll go into open folder and i just need to find this in the desktop here that's where i have the project and we're just going to open up the backend folder that we just created so i'm going to open up this terminal right now and the first thing i want to do is make sure the virtual environment is on so it's already activated if not just go ahead and activate that and you should be familiar with this all we need to do now is just run python manage dot py start app and we're gonna call this base so we're just gonna create an app for our django project so if you know django you know that django is comprised of multiple apps so we wanna run this command from the django project so make sure you're seated into the django project okay so let's quickly configure this app here we'll go into settings.py we'll go in here install the apps right here we'll just go into base dot apps so we're going into the apps folder inside of base and we're going to configure this to the base config class here so we just configured this and i'm going to go ahead and just run these installs it's asking me for this highlighting for python here so we're just going to go ahead and hit yes we'll make sure all of this is complete if you see that question just go ahead and decide on what settings you want i'm just going to confirm it and that'll run that installation okay so i just wanted you to see that so now that we have our app configured let's go ahead and set up our api here so we configure the app in here and some people like to create their api as an app what i like to do is typically keep my api separate from the app because the app has anything like the or files like the models file for the database any other kind of logic so i like to keep things separate so instead of actually creating another app for our api what i'm going to do is actually create the api folder inside of the base app here so we're going to create a new folder inside of base if you called it that and we're just going to call this api so because we only have one app that's why i'm going to do things this way and inside of api i'm going to create a new file called double underscore init double underscore dot py and the api will actually have its own views file so we won't use the views from base and it's also going to have its own urls so we'll just do urls.py and we are also going to want some serializers so let's do serializers dot py and those are going to come later but i just want to make sure the api folder is complete so views urls serializers and init so let's go ahead and actually make sure the views and urls are configured here so we'll go ahead and close out init and we'll start with the views so before we install the django rest framework i just want to make sure that the views are working so from django.http import json response and we'll create a view that's going to show us all the endpoints in our application so this will be kind of like some documentation for our app so you can go here and see all the routes that you can actually visit so we're going to call this get routes and we'll pass in request here again if you know all of this you can zoom right through this we're just setting up the api and then we're going to install the json web tokens so we'll do a return and we'll just do json response we're going to return routes that's going to be a list that we're going to create in a second and safe can be false and safe just basically means that we can render out any anything more than just a python dictionary so it's going to basically serialize that information for us so we'll create the list here and at this point we're going to prefix everything with the route of api forward slash and then what endpoint that we want to use so we're going to set that to token that's going to be the first endpoint this is where you can actually submit a username and password and you will get back a access and a refresh token now the next route is going to be api for slash token forward slash refresh and this will give you a new token based on a refresh token that you sent to the backend so these are our two routes here and now we want to create some urls for this so we're going to do from django.urls import path so we need a path method we also need access to our views so we're going to do from dot and then we're going to import views so we'll get the views imported and let's create the url pattern so we'll just do url patterns we'll create that and that's going to be using the path method the first route is going to be an empty string this is going to show our routes here and we'll just go into views dot get routes okay so we have a url that points to this view right here and those are all inside of the api folder not inside of base so we have two different views files and now we just need to configure these urls to our main application so let's go ahead and configure that so we'll go into the backend folder we'll go into the root directories urls file let's just go ahead and get rid of all these comments i just want to clean this up a little bit and in here we're going to need to add in the include method and we'll create a new path here so this path is going to send the user to the api folder so we're going to set the route we're going to prefix everything in this urls file with api so we're just going to do api forward slash and when a user goes to this route we're going to send them to base dot api dot url so we're just sending the user to this urls file and this file right here will take care of all the url routing so in here this is why we don't need to add an api because it's already prefixed right here so let's go ahead and test this so we want to turn on our server we'll just do python manage dot py run server get that going and we see unapplied migrations we're not worried about that right now and let's just go ahead and open up poor 8000 so it tells me my project is active on port 8000 what i like to do is actually go ahead and add that as a tab here but i could just paste that in like this and we should see this so if you see this that's fine we're seeing this error because we only have the route for the admin panel which we can't use because we have it ran on migrations and we have this api route so we'll go to that route and here we go we see these two routes inside of this array or i guess python list so the api folder is configured so let's just go ahead and open up django rest framework so let's go ahead and install this and make sure that we're actually using this instead of just that json response so the first thing i want to do is run this install so pip install django res framework as one word we'll get this installed so i'll just go ahead and open up a new terminal so my server is still on and we'll just clear this i'll do python dash m and then i'll just paste that in so pip install django rest framework that'll get that installed and in the documentation it also tells me to add it to installed apps so we'll take this value right here and we'll bring that in so we'll take this and add it to installed apps we'll minimize this or close that out it will leave our server on and let's go into settings and paste that in okay so rest underscore framework so that's it so to configure the rest api or the django rest framework that's all we need to do and now we just want to update our urls so we're not the urls but the views so i'm going to leave json response because maybe i can use that later but for now i'm just going to go into from rest underscore framework this is all in the documentation and we're just going to go ahead and get response so rest framework response we're going to import the response object so it's kind of like json response but it has a lot more to it so we're going to use this and the cool thing about response is we don't need to use the safe method right here and it gives us like a decorated response to our endpoint now we're going to use function based views not class based views so for this we're going to need a decorator so we're going into from rest underscore framework.decorators and we're going to import the api underscore view decorator so we'll bring this in and in order to use response you need the api decorator or the api view so we'll go ahead and add that to the top of the view and this just takes a list of http methods that we can send to this view so at this point we're only going to allow a get request you can also set put delete post etc so as long as you have the decorator imported and added right here you can use the response method and if i save it if i go to that same endpoint and refresh it we should now get a different interface but it looks like i have an error so what i need to do is just go ahead and run some migrations so let's actually just go ahead and turn off our server and we'll just do python manage dot py migrate and we'll just run the initial migrations i didn't realize that was going to cause an error so let's turn the server back on and let's check this out so if i go back here refresh it here we go so the same response but now i got i get this interface so i'm not going to go into why this is so cool and what it does basically but it's the django rest framework you should be familiar with this part of things so we see our same response but we have extra information so we know everything's connected and let's go ahead and actually start using simple jwt to actually work with the authentication and or the access and refresh tokens so if we go into the django rest framework documentation there should be a part that talks about authentication so we'll go into authentication and there's many different ways we can handle authentication but what i want to use is the json web token so let's see if i could scroll around here i should find it somewhere right here so json web tokens so json web tokens there's different ways we can do things there's hawk http authentication there's the signature authentication we're just going to use this json web token authentication and we're going to click on this link and that's going to take us to simple jwt so it's just a package that allows us to work with this so let's go ahead and actually check out the official documentation so down here from that link this should be the documentation to simple jwt so we also need to install this so we're going to go ahead and run this pip install so pip install django rest framework as one word dash simple jwt so we need to install it and then change our django application to handle or to use this for authentication so i'll open up a new terminal and clear that and i'll just do python dash m and i'm going to paste in pip install django rest framework dash simple jwt so i have that installed here and i also need to configure it so we need to let django know that we're trying to use this instead of whatever is set up there by default so we're just going to override this method right here or this variable inside of settings.py so it's all in the documentation here it's telling me to do this in settings.py so let's copy that we'll close this out we'll go into settings and i'm just going to add this under installed apps here so we'll paste this in and i'm just going to get rid of these three dots right here to get rid of that right there and now it's telling django use simple jwt for authentication so there's a lot of different configuration we can do here but we're going to leave it like that now in order to actually work with this we're going to start customizing this in a second but we want to use these built-in views to get the token the access and refresh token and also create the endpoint to refresh a token so let's go ahead and actually copy this right here too so we'll bring this into urls.py and i'm just going to paste this in right here so this is inside of that api folder so we're going to bring this in and it gives us two different views we can work with so we'll go back here and let's just take these two paths right here so we'll copy that and if you don't have the documentation you can just follow this and type it in just look at what i'm doing here so i want to make sure you can see this so we just pasted this in and we don't need to prefix it with api because we already have that so i can get rid of this but now we have two different endpoints one for token and that uses the token obtained pair view class here and then you have to use as view because it's a class based view and then it gives it a name now for this view it's token refresh that's what i put into those routes into that view here so let's go ahead and save this and it's going to use these right here so we'll save this and let's just go ahead and open this up and test this so we'll go to our api let's refresh it make sure it's all working and let's go to token okay so the first thing it's telling me is that this method is not allowed here so this is already built in all i had to do was use that class simple jwt does this for me now what i need to do is create a user and log this user in i don't have a user right now i just migrated my database so what i need to do is quickly create a user because if i try to submit this post request which i'll just hide my face here if i try to submit this post request it's not going to do anything so if i submit it it's going to say there are there is no user with these credentials we don't know who you're looking for so it's going to try to make that request it won't find anyone so we need to go ahead and create a user so let's go ahead and go back to the terminal we'll do python manage dot py create super user as one word you should already know all of this let's create a user i'm just gonna call my user dennis dennis at email.com we're gonna use a fake email and i'll add in a password it's gonna ask me to confirm the password and now that user is created so my server is still on so let's go ahead and actually try this again so we'll submit this request and the password should be pre-filled already so i'll just go ahead and refresh this and i use the same password that i always use for testing so we'll just go ahead and submit the post request and this is what the view does for me so we get back a refresh token and we get back an access tokens so this access token is actually going to store information about my user so i didn't want to get too much into how json web tokens work but there is a website that you can use it's called jwt.io and i just want to show you what this access token contains so this is the token that we need in the front end i'll try to zoom in a little bit this is the token that we need in the front end in order to store in that inside of our local storage and inside of our state in the front end to make sure that a user is authenticated so we're going to go ahead and take this token let's just copy the entire access token and if i go to jwt.io and scroll down here i can see this area to add in an encoded token so basically this is like user information encoded and we can actually paste this in here and it will decode it so django already knows how to decode it but it's all encrypted right now so if i paste this in right here it decodes this token and we can see this token right here and information about it so it knows our username so that's a user in the database it tells us when it's expired and more information about it and it also tells us the algorithm used to encrypt this token and basically all sorts of information about the user and the token so that's what it does for us now if i take this refresh token i can actually take this refresh token let's go go ahead and get the one on top here let's go ahead and go to the endpoint of refresh so we'll just do token forward slash refresh now this endpoint simply takes in this refresh value here so we need to take this refresh token and we just need to paste it in here so you can use the raw data right here this is actually how you would send it from the front end as long as it has the value of refresh we send this value with a post request we submit that and it gives us back a new access token so we get back a new token and we now have a new life span so let's talk about this token configuration so if we go back to this documentation we can go to customizing token claims so i'm gonna bring my face down here and i'll just minimize it because i don't wanna i wanna make sure it doesn't block anything here so if we go to customizing token claims we can see all this information about how we can work with this so let's see we want to go back here and i think it's in settings so in settings right here so we need to configure or we can configure our token inside of settings.py with all this information so this is actually the default configuration for a token so let's take all of this right here so it's inside of that url so make sure you follow that if you want to look this up let's take this entire configuration right here and let's paste this into settings.py so we'll bring this in here and we'll go into settings.py and let's add this just underneath rest underscore framework so we'll bring this in right here and what i want to do here first of all is remove the three dots here i want to take this time value this date time value and i want to paste that up here by baster so we'll bring that in and i also want to just go ahead and remove the signing key so if i remove it it's still going to be there it's just basically allowing us to override the default settings so here's where we can actually really customize a lot of information about our tokens so the first thing is the axis token lifetime and refresh token lifetime so the access token has a shorter life span and this is what we need to update so we use the refresh token to update the access token so five minutes is actually pretty good i can always change this i can set it to a couple days i can set this to 15 minutes or whatever i'm gonna leave it at five minutes so i want my token to expire after five minutes but the refresh token i want to make sure that last let's say 90 days so a refresh token should last a little bit longer because if a user logs into their application let's say you logged into facebook.com or twitter you don't want to have to log in every single day if you're using it you want to be able to open up your app or go to the website and still be logged in so that's what the refresh token does for us as long as the refresh token is active then we just use that token to update this shorter token so we always want to make sure that we're storing both of these tokens and that the refresh token has a longer life span but if this was like a bank website you might want to maybe make this lifespan shorter so it really depends on what you're trying to do with your application now rotating refresh tokens this is also something that's really cool here so when we rotate a refresh token let's say we use this refresh token so we'll go back to our website let's get a new token here so we'll go to api forward slash token so we'll go here we'll log in so we'll submit our username and password and let's get this refresh token so i just want to explain this concept here so if i go to refresh and if i paste in the refresh token all it's going to do is give me a new access token and that's it now if the 90 days expire here let's say the user's been logged in for 90 days what's going to happen is that refresh token will now expire and that's it so we want to change that so if a user is logged in let's say the refresh token lasts 90 days but if a user persists in the website there's they stay logged in we want to create like a rolling window and always generate a new refresh token for that user so after 90 days they don't have to log in as long as they've been active on the website now if they haven't used it for 90 days that means no refresh token has been generated and the user should be logged out but as long as they continue using it the user does not have to continuously log in so to update this all we do is go to rotate refresh token and we set that to true so at this point what i'm going to do is go ahead and use this refresh token and now when i submit it we don't just give back an access token let me try to zoom in here we also get a new refresh token so the refresh token will be updated we want to get this new token store this somewhere inside of our application and now a user is logged in from the point of when that refresh token was updated so it's always going to be rotating and that date that it expires will always keep rolling or moving away because the user is still logged in now there is one issue in here let's say i want to get this new token so i'm going to copy this new token right here and we're just going to send this again so we got this token inside of our browser and we want to paste that in that's going to go ahead and generate a new access token and a new refresh token for the user now this can create kind of an issue because i can actually take that refresh token that i just used and i can use it again so it generates a new axis and a refresh token and it can be used as much as possible so i can continuously use the old refresh tokens now this is really dangerous if somebody gets a hold of these refresh tokens because now they can generate their own access tokens and if we lost this information we want this to expire or just i guess have a minimal or allow it to be displayed or used as little as possible so we basically what we wanted was my horrible explanation of that but basically what happens is once the token is used we want to blacklist it so it doesn't exist anymore and only the most recent refresh token can be used so if i take this token and use it let's say i paste this in i should not be able to use that token again i should need this new refresh token because it's really dangerous if somebody gets that token so we want to blacklist this token now so what i can do here is actually go into simple jwt and i can say blacklist blacklist after rotation so after the token rotates do i want to blacklist this so i can go ahead and set that to true and now this will allow my token to be blacklisted but i need to actually add in some configuration for this so let me just check my notes here so inside of installed apps here let's go ahead and actually look this up here so it should be somewhere here so rotate refresh token blacklist refresh token so once we set that to true all i need to do is add in rest underscore framework underscore simple jwt token dot blacklist so we want to take this value and we want to add this into installed apps so that's going to add an app to our application now once we do this we need to run a migration because what it's going to do is create a database table and every single time a token is rotated it's going to take that that old refresh token and it's going to add it to that database table and these will be a list of blacklisted tokens so if somebody tries to use that again it won't allow it because it's going to check the database and it's going to say hey this token has been blacklisted don't allow this user so that's what's happening here is we add that in here and we also add in blacklist after rotation and we set that to true so we need to run a migration now it says we have 10 unapplied migrations so we'll open up a new terminal here we'll clear that and we'll just do python manage.py migrate and it will add that database table so my server is still on so let's check this out so we'll go back to the front end and let's go ahead and take this refresh token right here so we're going to copy this and we're going to paste this into refresh so if i post that it's going to give me back a new access and a new refresh token but if i try to use that original token again it's been blacklisted now so if i try to paste that in let's say someone steals this information and they want to use this again if i submit that now it tells me token has been blacklisted token is not valid that's the status code and the token is blacklisted so it blocks the user from being able to reuse that after it's been used once so that makes our application much more secure now before we move on to the front end because we're almost ready to start using this we first want to customize what the user response looks like and then we want to be able to modify or set up the course configuration so one second here let me bring this in or let's remove this and let's go back to token so let me explain what's going on here so when i log a user in we're going to get back access token so we're actually going to decode this token in the front end and we want to get some user information from this so let's take this access token let's bring this into jwt.io if i paste this in at this point we only get the token type the user id and basic information about this user so we want to be able to customize this so we actually get back a username so we can actually customize token claims so right here if we go into the documentation in simple jwt we can go to customize token claims and it tells us how we can do this so what i'm going to do is quickly just grab these two imports right here and i'm going to bring this into my views so basically what we're going to do is actually override this view and we're going to use our customized version of that view so we'll bring this into our views we'll paste this in so we have a serializer that it works with and a token obtain pair view which is also being used right here so let's go back to the documentation so we made those two imports and what we want to do is take these two classes right here so let's take these two values and i'll make sure you can see that in frame if you want to code that out yourself and i actually need to go back to our views here and let's bring this in above right here so we have the token obtained pair serializer which inherits from this value that we imported you can go into the github documentation or the source code and actually see how this is configured but basically what it's telling us here is we can go ahead and customize the token claim right here so we can take this token and we can add any value we want in here so in this case i want to also encrypt the user's name so we have the user object right here and we're going into user dot user name so that's going to be encrypted into the token we're going to take this serializer and we're also going to add that as the serializer class so we extend the serializer with all the other values that it has we add in this value so token is basically just a dictionary right here that's encrypted we add in the username from the user object that value is derived from the actual token we encrypt this value and then we return it and we add that as a serializer class so what i can actually do is take this value now so remember it's token obtain pair view and we just added the word my so it just basically means that this is our customized version of this so if we go back to urls here we can see token obtained pair view so we're no longer using this we're going to use our own custom value so we're going to paste in my token obtain pair view so what i'm going to do here is actually just import that manually so we're going to do from dot views and then we'll import my token obtain pair view so we want to import that so we can use that right here okay so now if we get the response we're not going to see much of our difference until we decode this and this is something that we're actually going to decode in the front end so if i refresh this let's go ahead and make sure we get back everything again let's go ahead and submit our username and password we'll submit the post request so i'll just move my face up here we'll submit that request and now we get a refresh token and an access token so it all looks the same here so we're just going to take this access token right here copy that and we'll go into jwt dot io so we're actually going to do all of this in the front end i'm just using this to show you so at this point we see the token type expiration user id and so on so if i paste in the new token now we see user name right there so we encrypted that username value inside of the token so in the front end this is how we're able to get that username right away now you could leave it with the id take this id and make another request for the user information but it doesn't hurt us to add this in directly in here so we can access it immediately now other user information you can store in a different way but i want to get that user information right here directly so this is how we did it we just simply customized the serializer that works with that we got that from the documentation created the new view by inheriting from the original view and then we used the custom view inside of the urls right here now the token refresh view well we're going to leave that because there's not much we want to customize there okay so we have most of our application done here we're almost ready to use our api and we have one final step before we can build out the front end and actually make requests to this so at this point what we need to do is work on course configuration so core stands for cross origin resource sharing i think i have that right but basically what's going to happen here is we're going to have our react project as a completely different folder and that's going to be running from port 3000 django right now is running on port 8000 so basically what's going to happen is the origin from where that request is being made from the front end it's going to be on a different url or the endpoint is going to be different so django is going to look at this request and say i don't know who you are i don't trust you so it's going to block that request so we need to configure it to where we can either allow any kind of request to this backend we can give it a specific list of urls to actually allow there's different ways we can do it but basically we need to make sure that the api is available from this endpoint now i just want to quickly look this up real quick so we'll just do cores error and if you see this this is what the issue is so i just want to pull up this image because in the url you'll see something like this if you try to make a request now you might not notice it right away because it's going to be in the network call but if you're trying to make these requests and you're wondering why the api is breaking or why that request isn't working probably because of this if you haven't configured this yet so let's go ahead and quickly just run through this and i'm going to move my face down here actually i guess that's probably a good size right there and i'll just zoom in so it looks something like this well i guess there's a bunch of documentation on it but this air is seen by a lot of people a lot of people run into this so there is actually a package that we can use it's called django cores headers so let's go ahead and open this up and let's follow the instructions here so this is the github repo it tells us how to use it so we're going to want to quickly just run this install so it's pip install django dash cores dash headers we're going to install it and then we need to add that to installed apps so there's about three different steps that we need to run through here so we'll open up our terminal we'll open up a new terminal i'll just clear this paste that in so python dash m pip install django course header so you can just get that from the documentation and we'll just clear this so that's installed now and i just need to add this to installed apps we'll bring that in we'll go ahead and minimize that we'll go here under rest framework we'll add in a comma just to make sure that's there and we'll add in course headers so one final step here all we need to do or two i guess we first need to add this to our middleware so we'll bring this in we'll go back to settings.py we'll bring this in right here so let's just put this under our security middleware and i'll create some space so we can see what we added and what was originally there now this is that step that i was telling you about when we can configure how we want to set this up so there's course allow origins or cores allowed origins and this is basically a list of urls that we want to allow to our api now we can also use regex or rejects that's going to basically allow us to configure things in a different way so here's the allow origins it's basically saying these are the urls that are allowed to make requests to our api now we can use regex for this we can set up a certain a certain path here or we could just allow all origins so cores allow all origins this is going to say go ahead and just allow anybody to hit this endpoint right here so i'm just going to configure this at the bottom of settings.py cores allow all origins and we're going to set that to true i'm not worried about the details of configuration it's just locally we're just trying to use this project right now so we'll set that up and that should be it for the backend at this point so i'll just go ahead and minimize a few things here i guess i can leave these open it doesn't really affect anything and let's just go ahead and create our react application now so i'll close all this out we're going to leave port 8000 on that server will be running and i'm just going to use my terminal for this or at this point and i'm going to cd into my desktop so that's where i'm going to store this project and you do need to make sure you have node.js installed and we're going to use npx here to execute a command so we're going to use npx create dash react dash app you should be familiar with this and we're going to call this front end like that so that's going to create the boilerplate files for our react project so i told you that we're going to create the back end and the front end completely separate so it's going to take a minute or two to run through this we can see the front end folder right here and the back end folder so what i'll do is just let this run through i might just pause it if it takes a minute and we'll just cut at this point okay so the react project just finished setting up here so we'll just go ahead and close out that command prompt and i'm going to open up another vs code terminal here to access that part of things so we'll open up a new window so i'm just gonna i guess work on them from from two different uh vs code projects we're not gonna put it into one folder just yet so we'll go into the desktop and i'm gonna open up front end so i have a folder for the back end and front end so i have both of these opened up so make sure your server on the back end the django server is not off make sure it's running because we are going to need to access this so we'll go ahead and open up the front end now and we're just going to work on them separately so before we get started the first thing i want to do is clear this up a little bit so in source because we're not going to need app.test and report vitals and setup tests we're just going to delete some stuff here just to keep things clean it doesn't mean these things aren't important we're just going to get rid of what we don't need right now so i'm just going to select all of those and we'll just hit delete and all we should have at this point is app.css app.js and index.js now before we can actually turn on our server here let's go ahead and clear this out because web vitals is there that's going to cause an issue we also don't want to import it because we don't have it we don't have index.css and i can save that so we'll go into app.js let's actually go to app.css we'll select all of this we'll delete all the styling i'm not sure if we'll add any styling i don't think we will but we'll clear that we'll go to app.js and let's just get rid of everything inside of header and we'll just say home so we'll just do here is our website or something like that here is our react website okay so i just want to make sure everything's running we'll just do npm start we'll get that react server on so npm start we'll turn that on that should open this up automatically on port 3000 in a second here so now we have our back end and we have the front end and if everything went successfully we should see this nope i guess i'm not so it looks like i didn't remove a certain import so i deleted that logo so i don't need that there anymore so just go ahead and refresh that and here we go so here is our react website so what i'm going to do at this point is just go ahead and get some basic configurations set up so we're going to create a home page a login page and then we'll go ahead and build out a header so the header will store the two links there and that's where we can create our navigation from so we'll get that set up really quick we just want to get some boilerplate get get some boilerplate going and then we'll use the context api to actually handle state management so in source i'm gonna create a folder for pages we're also going to create a folder for components and let's see so we're going to create a folder for context so when we're using the context api we want to so con text couldn't spell that when we're using it we want to be able to create context or state i guess for different parts of our application so that will be in its own folder and we'll create a folder for utilities so utils and that's going to create just any other functions that we want to store separately so let's start with our pages so we'll go into pages and create a new file and this is going to be called homepage.js so i have a shortcut here and this is called r or let's see it was es7 i believe es7 code snippets so this is really convenient because i can install this if you have vs code where you can install it and i'm able to type in these short codes and i'm able to generate imports and also create react components so you're going to see me use imd so let's find this real quick so imd is a destructured import and then imp is just a standard import and i can also type in things like react functional component and that'll just generate these components for me so if you see me using these shortcuts it's going to happen really quickly this is why it's happening and then i also have something called auto rename tag so auto rename tag and this basically means that i can rename an opening tag or a closing tag and it will automatically rename the other tags so it's just going to make things a little bit quicker kind of works like this in this demo here so i'm not sure if you can see that but yeah so i'm using those so that's what's going to happen here so i can actually do react arrow function component exported and that's going to generate a component when i hit enter and the component will be named based off of the file name so that's what's happening here so let's just go ahead and add in a p tag here and we'll just say you are logged in to the home page okay so we're just sending some kind of message to the user so we have the home component or the home page we'll create a new page and we'll just say login page dot js and we'll just do r f c e react actually that's a r a of c because we're using arrow functions and you can use whatever you want here and this will be the login page so for this we're going to create a form and we'll just fill out some information so we'll create an input value so we'll do input type is going to be text here for the username we also want to give it a name because we need to access it by this name here and we'll just say user name and we'll just close this out really quick and then the placeholder will just say enter username so if you already know this just go ahead and finish up this boilerplate we're creating a form with the type of text or a field of the type of text a name of username and some placeholder information we're going to create another input value for the password so this is that login form type will be password if you're using an email for this part you can do email make sure the name is password here and then we'll just say enter password okay so we have a basic form we also need a submit button so we'll paste that in right there so i just copy this type will be submit and for this we don't need a name or a placeholder so we're going to keep our form pretty simple here we're just prompting the user for their username and password and let's go into app.js now so in app.js this is where we're going to store that main component we're going to need to use react router for this so before we use react router for our page navigation let's go ahead and import it so imp that's going to give us a shortcut it's going to prep a module import and we can just go into pages and we're going to get the home page and if i hit tab here it'll send me over here and we can just do home page like that so we're going to import that we'll also import the login page so that's going to give me a destructured import i need to do imp with that shortcut we'll go into the pages folder and we'll just do forward slash login page and we'll get login page okay so we have those two imports and i'm just going to open up my terminal here and let's just go ahead and open up a new one and we'll just do npm install react dash router dash dom so that's all one word it looks kind of funny here because of the space that i have because i'm so zoomed in but that's the installation so go ahead and run that make sure that's from your front end folder and that's going to take a second and install that for us so give that a minute so while that's installing you can actually look up the documentation for react router dom right here defaulting into explaining everything again but uh this is where we can install it and these are the imports so we can start with browser router that's what we're gonna do and we also have links uh different routers we can use and so on so react router.com that's the website there so let's get that installed that's now installed i'm going to close this one out we'll leave the server on though so let's go ahead and run that import so from so imd from react dash router dom and we want to import browser router and we want to import that as router so we just want to make that shorter and we also want to import the route so the router is what's going to wrap our application and allow the entire application to use these different routes and elements from this router so things like the links and so on so what we need to do is wrap all of this so we'll just go ahead and use route so we're actually using the browser router as router so we're going to do router and we're going to wrap everywhere we want these pages to be so let's just go ahead and bring this in here we're going to close this out so it's going to wrap it and we're going to take this out right here and we're going to add in a specific route so instead of adding our components directly we want to be able to render them as routes so we'll bring we'll bring this in right here and in the route we need to specify the component that we want to render on a specific route so the first one will be the home page we want to specify the path that we are allowing the user to go to that page or the path that sends the user to this page and that's just going to be a forward slash and because this is the home page we need to add in exact so exact is going to ensure that when a user goes to let's say the login page we want to make sure we don't render this component out because every single path technically starts with that forward slash so exact needs to be there so we're going to copy this right here bring this down here we're going to take this login page value paste that in we can now remove exact and we're going to specify the path as login like that so we'll set that up let's go ahead and check our application out so we should render out these two pages so you are now logged into the homepage and we'll go to login and now we have some url routing so that's that form we just created here okay so we also need a header so we want to create some navigation so a user can jump between the two pages so we'll go into components because it's not a page it's a component that can be reused on multiple pages so we'll create a new file and we're just going to call this header.js so this is a react component react arrow function component exported we're going to create the header and in here i want to be able to create some links so we're not going to be using a standard a tag because we're using things with the react router dom so react router dom gives us a value of link here so we can create two links here so we'll do link close that off and the text in this link will be home and we'll just go ahead and set the two values so instead of href we just do two and this is gonna send the user to the home page and then this next link right here is gonna send the user to the login page so we'll just do log in like that and i'm just going to add a span tag to create some space between these two so we'll just do span close that off and let's just add in some space here and then we'll just do a pipe like that so if i save this we can now go back into app.js here so we want to run an import and this is now from dot components and we're going into header we'll bring that in we'll grab this header and let's just put this above or inside of the router but we just want to make sure it's not in a route we just want to render the component as is so we can actually just render that out like this and that'll give us our header so let's check this out now we see login and home and i can actually switch between the two pages so before we start working with the back end or before we actually work with it i want to show you how to create a private route so a private route is going to be a little bit interesting because all we're going to do is use this route right here and we're just going to extend that route and basically create like a wrapper around it so it has some extra functionality and this is where we can check if a user is logged in based on what's inside of local storage so if a user has a token and is authenticated we can actually allow a user to access a certain route or block them so we're just extending this route from react router dom so let's see this is going to be inside of utils here so inside of utils that's going to be our utility functions we're going to create a private route component so we'll create a new file and we're going to call this private route dot js so we're creating the private route let's just go ahead and build out the entire component so we're just going to go ahead and import from react dash router dom so we want to import this we want to use route and we also want to use a method called redirect so i want to make sure i spelt that right so we have redirect and we want to start building out our component so give me a second here i have some notes i want to reference here just want to make sure i get it all right the first time so we're going to start creating this component we're going to set that to const and we're going to call this private route so that's our component name this is going to be an arrow function here so we're going to go ahead and set this up we'll create the arrow function and we're going to return the route here so we're actually going to take this route method and this is what we're going to return from this component so it's the standard route here there's not much to it and in here we're going to pass in or destructure some value so this is going to be the children so the component that is passed into private route which will be the standard route here so we'll do children so we're passing in the children and then we're going to pass in or use a spread operator to get the rest of the parameters so if you look at app.js we have these parameters so we specify the component the path and exact and all these other things about that specific route so we also need to pass this information down to the private route so that's going to be inside of rest so we're basically saying whatever we pass in right here let that be passed in down here so we got the children and we're going to use a spread operator to get everything here so in this route all we need to do is use this right here the two curly braces or create the object and we'll just pass in rest like that so we're gonna throw that in here and then inside of the route itself we'll just pass in children and that should be it at this point so the route at this point won't actually stop anyone from going here but i just want to console something out and make sure it's working so we'll just say private route works okay so let's test this so all we're basically doing is extending the route and we want to see if this even works at this point so we use a spread operator we use route pass in all the children in here and let's save it let's go back to app.js let's bring this in above all these components and we're just going to run this import we're going into dot utils and then we're going to private route and we're going to import private route so let's see if we have any errors it looks good so far now we're going to take this private route and we're just going to replace the home page with private route so if i paste this in here now instead of route it's private route so it should give us the same functionality the only difference is if it's working we're going to see this be consoled out so let's go ahead and test this out looks like something's not imported correctly so give me a second let me try to debug this so i just need to look at some other source code that i've been using so we import the private route from let's see we go into utils private route dot js we're going to save that private route right here and that should be good at this point okay so it looks like the issue is the fact that i didn't export that so i need to go ahead and export it so we'll just do export default i guess i should have read the error because it told me right there so export default and we're just going to export private route like that okay so that should get rid of this error so let's check this out here we go so we can go between the two pages now we are using private route instead of just a standard route that just extends route right here it creates a wrapper and let's see so as we go to that home page we should see that be consoled out so if i refresh this we see private route works so i can go between the two pages and it's all working good so we officially have the wrapper here so for this private route let's create some kind of value before we actually get that token and let's just try to represent a user that's not authenticated so we'll just do const and we'll just do is authenticated or let's just do authenticated like this authenticated and let's just set this to false so the user is not authenticated so if the user is not authenticated what i want to do is check a condition here and actually change something up here so we'll just go ahead and use the not operator so if the user is not authenticated so that means that this value is false what do we want to do here so at this point we're just going to create the question mark here and we're going to redirect a user so we're going to use this redirect value we'll paste this in we're going to redirect a user to the login page and it's not supposed to have that closing tag here so we'll send a user to login so we'll go into login like that so if the user is not authenticated we add in the question mark we send the user to login else we can use the colon like that go ahead and continue on with the request so we're only going to do this if the user or if authenticated is false so let's save this we'll go back here false is not defined that needs to be lower case i was using python this is the issue with using multiple languages sometimes so let's check this out so if i refresh this if i try to go to home let's make sure that you can see everything so try to zoom in here so if i try to go to the home page now it's not letting me so we officially created a private route and that's the first step in the front end to actually making sure that we can block users there's different ways to do this but i like the idea of just creating a component like this and then later on you can change this to depend on whether a user has certain permissions so let's say you have unauthenticated users you have authenticated users and then maybe admin users so depending on what that user's permission is you can create different type of or different types of components to specifically restrict a user so now that we have the private route we want to use the context api to start handling our authentication so i don't want to go over the context api because that's kind of outside of the scope here but just to give you some reference if you've ever heard of redux or mobx there's different ways of working with these state management systems well the context api is something that's built into react here by default so just to give you an idea i just went on google looked it up and i found this example right here it looks like it was from somebody else's tutorial it was just on google images and basically we have this app right here and we have all these different pages and components now if we want to have access to different parts of our components we would put that into like a global store and then those components can be accessed anywhere through the application we don't need to pass them down through like prop drilling where we pass them down by components and we also need to be able to update let's say something in the header bar all the way from a component down that tree right here through the virtual dom so basically we're going to store our information about our user this is why we need it because a user needs to be available from the header we want to say hello and then the user's name later on you want to be able to reference user information by certain pages so that's going to be all inside of a global store so that's what we're going to use context for so context is actually very simple to get started with so we're going to go ahead and build this in and we can create different types of contexts these are like different stores so we created a folder for context and in this case we're going to create a context called auth context we'll do authcontext.js so this is going to be our context right here and we want to run some imports so we're going to go ahead and import from react here we're going to import create context so this is actually how we want to create it so we have create context later on we're going to want to use state and use effect here so you might want to be familiar with use state and use effect i won't be covering those these are just react hooks so i won't be going too much into these so let's go ahead and create our context so to create it we're just going to go ahead and set this value we're going to call this auth context and we're just going to go ahead and use create context so we're going to leave that blank so we have our context and typically we can start using this context by exporting this and then simply starting to use this or bringing it into places like our app or our app component so basically you wrap all the components that you want to use the data from your context and you have consumers and providers so providers provide the information whereas consumers receive that information so i want to build this in a little bit differently so i'm just going to go ahead and make sure this is exported right away so we're going to close out the private route for now we'll close out header home login let's clean this up a little bit so our auth context right here we just created it we're going to export this as a default export so we'll just do export default and we're just going to do auth context so again we could just export it and bring it in right here and wrap this information but we're going to create our provider right here just to clean things up so sorry if i'm skipping a little bit too far ahead but once you see how this is built it's actually going to be very simple so let's go ahead and export something again so we're going to create the provider so we're going to do export const this will be our auth provider so this will be the provider to give information to the consumers so we'll go ahead and create the provider we're going to destructure children so everything that we're going to pass through it and we'll continue on with this function it will be an arrow function and we want to set the return value in the return value let's go ahead and just use that provider right now so we're just going to go ahead and go into auth context so this context right here that we created so we have auth context dot provider so you can actually do this directly inside of the app component but we're going to set this up right here and just extend it so with a provider you need to pass in some values here so let's just say name here or we'll just create this object and i believe we can just do it like this where we pass in name and then the name will be dennis at this point so we're passing in value and this value is what we want to be available everywhere throughout the application so we simply use the value property and we pass in the values right here so we're actually going to change this up a little bit but i want to show you how this is working so we also want to take the children right here we'll throw that in so we'll pass that through and let's go ahead and actually use this so we'll go into app.js here and let's go ahead and bring in our auth context so let's see i'll bring this in at the top level so we'll bring in the provider so we'll just go ahead and destructure it we'll go into context and then we'll go into auth context and we'll bring in our auth provider okay so we're just taking this provider and we're bringing it down into or into the app.js component so with this i can actually wrap all this information so where do i want this name to be available from so i want this name to be available in pretty much every component so i want it to be available in the header in the home component and in the login component technically i don't need it in the login component but i might as well provide it there it doesn't hurt us so what i can actually do is take this auth provider and just like router all i need to do is wrap all the components that are going to use this information so we're going to wrap this in we'll close this off so we'll do auth provider we'll paste that and for some reason prettier the extension printer is not working so it won't auto format that for me but now we have this information brought into our app component so the provider is now going to provide all that information into these components so to be able to use this let's actually go to the home component and at this point well let's go into the header component so i can use this in home login header wherever i want it let's just go ahead and create this message here and we'll just say hello and then we'll pass in the name here so we'll just do user dot or user or we'll just do name like that so i think i passed it in as name so in order to use the name i need to actually use use context so we'll bring this in i believe it's from react we need to destructure this we'll just do use context and let's just go ahead and get this name value so we'll just do let here we'll destructure this we want to get the name value from use context and what context do we want to use well in this case i'm going to use auth context so when i add this in it should automatically import auth context for me if that doesn't you might just have to write that out here so we now have auth context we get the name from auth context right here from this provider and we can get this name value right here so if i save this let's check this out so if i go here now it says hello dennis so that's the core idea of the context provider so let's go ahead and just comment this out and let's actually start getting some information so we first want to allow a user to log in so at this point i'm just going to comment that out because we do want to get a username but not in this way right here we actually want to get that username from the backend so we'll go back to auth context let's take this value right here let's remove it and let's just say user info or context data so we'll create an object right here in our auth provider and we'll just do let context data and this will be an object and we're going to pass in context data into our context provider so in here we're going to have things like the user or we can actually set it like this so the user and then any other functions because we can pass down more than just variables we can also do functions and so on so the first thing i want to do is allow a user to be logged in so we'll set this value in a second so let's go ahead and set some state so we'll just go ahead and do user and we'll do set user so we'll set that value this is going to use state make sure it's imported and before a user is logged in we're going to set this value to null so we're going to want to get the user and then we also want to get the authentication tokens so we'll paste that in and we'll do auth tokens and then we'll just do set auth token so we have a value of this or we have a value for that state and then a way to update it so this will be set auth tokens i know if you aren't familiar with this at all like the ideas of react this might be a little bit more difficult so that's what we're going to do right now we first want to get these values and now we want to allow a user to log in and we also want to check if this user value is somewhere inside of our local storage so do we have this token information in our local storage so let's quickly just build out that login function here so let's just go ahead and create this function we'll call this login user so we'll make that an arrow function and we also want to make sure we add an async here because we are going to use async await we're going to wait on some network calls here so we want to make sure that's set up we're going to pass in the event here and let's see so the first thing i want to do is set the value of response and we're going to use fetch here so we'll just do fetch and what we want to do is actually send some information to this value right here to get the token so we're just going to add that in directly so we're going to take this link and remember that this endpoint right here if we go to the raw data it just needs this media type of application json and then we need to pass in a username or a password to that so let's go ahead and actually send this information so we'll add in that url here so we'll just go ahead and just use that directly right here we're not going to set up a proxy url at this point and in this we need to set some more information so we're going to add in a comma and we're going to set the method the method has to be a post method and now we want to add in some headers so we're going to do headers this is also going to be an object and we're going to set the content dash type and the type here is going to be application for slash json we're just telling the back end hey this is json data so we're just specifying the type of information that we're setting or that we're sending so now we want the body this is going to be like the body of that post this is the data that we're sending to the backend and with fetch we always need to do json.stringify so we're basically turning this data into a string and in json.stringify what i'm going to do is send send a username and we're going to set that to null for now and we also want to send a password so we'll just do password just want to make sure my faces and blog blocking the screen here so the password will also be null okay so let me clear that so we set the method to post we add the headers and we send the username or password so when we send this information we want to be able to send this from the form here so we're going to take this function right here login user and we're going to bring this into context data so we're going to do login user and we're going to pass in this value so this is going to be the key value pair we want to take this function and bring this down to the login page there's different ways you can do this at this point because the context or the auth provider wraps the login page also we want to be able to pass this information to the login page so we add this in right here now in the login page we can actually get this so we're just going to do use context so from the login page now use context and let's set this value so we're going to destructure this the response we're going to get that login user function and this is going to be use context and we're going to do auth context and that should automatically import this right here so we have that function and we want to go ahead and set that right here so on submit when this form is submitted we're going to add an event handler we want to fire off the login user function so in here in the function i want to do e dot prevent default so if if i submit that form by default it's going to send some kind of request it's also going to refresh the page i don't want to do that i want this method right here to handle all of this so we're going to prevent the default and let's just test this out let's actually console it out so we'll just do console.log and we'll say form submitted and let's just comment this out right here so i don't want it to send anything right now so i just want to make sure that function is working so we'll refresh it or we'll go to console let's just do a refresh submit that so form is submitted so it's all working and it's counting how many times that's happening so that looks good here okay so let's go back here let's uncomment all of this we'll remove form is submitted and we want to proceed with this so to submit this data we can actually get or use the event here and we can actually get the form data directly from here again there's different ways and going about this but we can do e dot target so the target is the form so we'll do e.target and then we're going to get a name or a value from that target we're getting the user name here so that's why we specifically added the names the password and username so make sure you're using this value right here so we're getting the username and we're getting the value of that username so we're also going to do the same for passwords so we're going to copy this paste this into the password e.target.password dot value so we're sending this data and we want to get that response so we're going to do let and we need to add in a weight so if we're using async await we're going to do data and this is going to be equal to a weight and we're going to take that response here and we're just going to get the response.json so we're just going to parse that data and we want to console this out so we'll do console.log and let's just get that data so do data so what's going to happen here is we're going to submit the form send our username and password just like we did from the front end earlier and we should get back an axis and a refresh token so let's try this out we'll do inspect let's see if it's all working if we set up the chorus correctly it should work fine i'm like so zoomed in i'm trying to figure out how to fix this okay that should do i think you can see that so sorry about the breathing there so we'll submit that and there we go so we get back a refresh token and an access token so we got that data so that's sent it to this url or this endpoint right here make sure both servers are on and cores is configured and now we got that information now it doesn't log me in because i can send that multiple times it's going to keep regenerating that information so we need to continue on with this process here so let's go ahead and find find out the next step here so we can actually get response here so let's console out response also so we'll just copy this right here and let's see what we have in response so the first thing i want to do is make sure that the response was good if everything went correctly then we want to update our local storage and get these values and actually set this so if i submit that we have our username and password already added in there we see the data and we see response now we see the status text the status code 200 means everything went good we see our headers and our bodies so we see all this information about the response so we're going to get this response right here and we're going to check if that was good so we're going to do if response dot status so remember status gives us back a 200 if everything is good we're going to set that to equals to 200 if everything goes good we want to proceed here else let's just go ahead and say alert and we'll just say something went wrong here so something went wrong we're not going to worry about all the air handling right now so something went wrong and at least the user knows that something's not working so if everything goes good that means we got back the data the username and password were good we got back a token what we want to do is use this set auth tokens value and we want to go ahead and set this in our state so we want to store it in our state and in local storage because if we set it in our state that means we can access this information and check if we're logged in through different routes in our application like private route right here because later on we're going to use our state instead of this hard coded value so we'll go back to this section right here so if the status is good we're going to get that response and set the tokens to data like that so that's going to be the access and the refresh token now we want to set the user so we're going to set the user and this is going to be data dot access now we want to actually get the user information so let's go ahead and actually decode this value and store that user information so we don't want just the token we want to actually get that information so remember when we went to jwt dot io and we added the token in right here and we got back that user information so we want to be able to get this response so we want to get access so we'll take that entire value for some reason i can't see it so let's just quickly generate it so we'll just go back to html form so we'll get this access token and i'm kind of i guess repeating myself a little bit but i want to make sure it's clear we're going to paste that in here so we want this information as opposed to this token stored in the users part of the state so in one part we store the tokens and another we actually want that information so there is a library that we can use called jwt or npm package called jwt dot decode or jwtd code so look this up i believe it's this one right here it's an npm package jwt dash decode we're going to run this install and all we do is we add the token into this function and it will decode the token and it'll give us back that object right there so let's go ahead and run this install so you can use yarn we're going to use npm in this case whatever you're familiar with or comfortable with and let's just go ahead and open up a new terminal and run that installation make sure you're from this front end folder so make sure the file path is correct while that's installing let's go ahead and add in this import we'll bring this in right here at the top so import jwt underscore decode from jwt decode so that all installed successfully so we want to use this method now and we're going to take this value and put that into set users so instead of just passing in the token we're going to get data.access that's the access token and we want to decode that token and then store that user information so let's go ahead and save this and what we want to do now is get this user information and i want to actually pass this down into context data so the token is decoded added into this state right here so that's going to be the user object and let's go ahead and pass this through so all variables will be added above and all functions will be added below so that's just the way i want to store it so we're taking this user and we're gonna go back into login page so we're not the login page but the header so we'll go into the header and now we're gonna throw user in here instead of name so in this value let's go ahead and do user dot name so i want to check this out actually so what i'm going to do is take auth tokens so what did i call that here so we're going to take these we're going to check if we have a token here and then if we do then we're actually going to display the user so we want to make sure that the user is actually authenticated so let's do it this way actually so we'll check the user value so we don't need the actual tokens so here we'll create a condition we're going to use this condition right here so we'll say if the user is there then let's just go ahead and output the user username so bring that in right here inside of these two curly braces and in this case we're getting user name because that's how we saved it so if we have a user go ahead and bring this in so let's check this out if i log in now we see hello dennis and we see the user so if i refresh it the user is going to go away because i'm not storing this in local storage yet so let's finish up in our header here so we'll go ahead and check if the user exists and then we also want to create a condition here we're going to use the ternary operator and we're going to say if we have a user so we're going to create a question here so if we have a user then we want to add in a logout leak so we want to say log out and in this case we're not going to use the link value so log out we're just going to add in a paragraph tag so at this point we're going to add a paragraph tag and we'll just add in some kind of event handler so that needs to be in the text not in the 2 value so we can also do an else value and in the else value this is where we're going to throw in log in so if a user is logged in we want to add in the log out text if they're if they are logged if they're not logged in we want to prompt them to log in and then we also want to display their name so now we can use that context or our global state to actually check this information so if i hit log in or submit that now we see log out it's not working at this point but you kind of get the idea of how that logic works so what i want to do next here is actually make sure that we can stay logged in so what we need to do is allow this to where if i manually refresh the page we can stay logged in so we need to fix this so the first thing i'm going to do here is make sure that whenever a user loads the page let's say they've already logged in they come back the next day we want to make sure that they're still logged into their application so what i could do is just do local storage dot get item and i can ask for the the access token so we'll just do auth tokens like this so i can try to get the token from local storage before i do that let's continue with this login method so once we set this information what i'm going to do is go ahead and do local storage dot set item and in here we can do key value pairs so we can do set item we'll paste in auth tokens and this value will simply be the authentication token so we'll just take data right here and technically i can only store strings in here so we're going to actually have to set this as a string so we'll just do json.stringify and we're going to pass in data like that so it's going to stringify it and it will set it once we log in so this information will be inside of local storage and then we want to be able to get this information so let's try this so once that's done we also want to use history here so let's actually import that we want to redirect a user to the home page so we'll just do from react dash router dash dom let's go ahead and do use history so because we're not in a standard component we need to use history this this way so we'll do use history make sure i got that right and let's set history right here so we'll do let history and we'll set that to use history and that's going to be the method so i'll set that to const so we're going to take history once a user logs in we're going to set these two values set local storage and then redirect a user so we'll do history.push and we're going to send the user to the home page so let's check this out so our code is still a little bit broken but we're just going through this step by step here so if i open up my application here if we'll go into local storage we'll delete the original tokens here i think that was there from before if i hit log in so i have my credentials make sure they're added there we'll submit that we just got redirected we should be redirected to the home page and i see what happened here i'll explain what happened in a second so we added the token in here so now we have the access and the refresh token in local storage so now if i refresh it i'm always going to be inside of this page here now the issue is inside of our private route we didn't adjust this to listen for this token here so we want to fix that so we'll go into we'll close out the header here actually we'll leave that open let's go into our private route and we want to check our authentication based off of what's inside of our state now instead of what's inside of this page here or besides this value so we're going to remove authenticated and let's see so we want to be able to get the user information so we're going to import use context from react so we're going to destructure this from react let's import use context and we want to use the context so we'll set this value to the user and this will be use context so now we want to check if we have a user instead of checking that authenticated value so we'll just use auth context now we imported that we have the user now we just want to say if we have a user then allow the user to see this page so we just wanted to change that up now if i log in now i can officially see this page but there's still an issue here because if i manually refresh this i'm going to be logged out because the state was updated even though the local storage still has its value we need to update the state when a user first opens up the website so you see that the state is null until we officially hit log in other than that it's always going to be null so we can get this value from local storage and we can actually update it directly in here so we can do local storage and then i'm actually going to write out the condition and update it in a second so first of all we want to check if we have anything in authentication tokens so it's going to check the local storage and see if we have this value if we have this value we're going to create a condition so if there's something in here then what we're going to do then what we're going to do while we're just completely stuttered what we're going to do here is we're going to take that token we're going to do json.parse so it's the opposite of stringify let me just make sure you can see that so instead of stringifying it we're now going to parse it we want to get back the object so we're going to do json.parse and we're going to parse that token so we want to get these values back so we're going to parse it once that's parsed then we want to set the value else we want to set that to null so json.parse that ends right here the last value here is going to be null so in get item so we're going to do that right here and we'll do null so if we don't have anything let me just try to recap this we'll create as much space as possible we check if we have a token if we do we get that token from here we parse it we get back the object else the value is going to be null so what we can do actually is get this value and throw that into u-state and something looks wrong here so i want to try to fix this so parse i think i'm missing the parentheses right here okay i think that was it so get item wraps all the way to the end right here okay no so json.parse wraps all the way here and then git token so i just want to make sure i had that wrapped completely so in theory what i could do is actually just take this value i'm going to copy that to remove it and paste it in right here so this will either be null or that token so i just pasted that in so that is now inside of you state so the initial value will be whatever it is inside of local storage so let me save that and let's try this again so let's see we have some kind of issue here so set user all tokens missing a semi colon where is this at what line so yeah the zoom is kind of throwing me off so we have you state local storage.getitem so i think that is supposed to be removed okay so let's recap this one more time i need to go slow here just so if i'm having an issue i know someone else is going to have the issue so i need to fix that so use date starts and closes all the way right here we have our question with the question mark right there we have the condition json.parse closes right there get item closes right here and then null okay so let's save this and let's check this out so now if i actually go to the home page let's log in if i refresh this it should keep me logged in give me a second to try to figure this out okay it's actually based off of the user object too so we need to do the same for the user object so let's take this entire ustate value let's copy this and we also want to get the user value from the state because in the private route we're trying to access the user and that is still empty so that's why it's not allowing me so we're going to paste this over this use date for the user except for for the user we need to decode this value so we're going to take this decode value let's bring this in right here so json instead of json.parse we're just going to do decode so we can just change that right there and that should decode that value i don't think i need to parse it so let's try this i think the parcel will work on its own let's try to go to the home page and it looks like i made a another issue probably the same thing that i did last time so let's check this out else null decode looks like i had an extra value there let's check this out again okay so now when i refresh it i can stay in the home page so that actually works fine and i can't log out at this point so if i actually just delete that token and then refresh it now i'm logged out i can't go to the home page but when i log in it redirects me here and i can actually see this user's information even when i click this refresh button so it persists that login now i want to make this a little bit more efficient and for you state we can actually pass in a value directly so we have the value like this but what i want to do is actually use a callback function because what's going to happen is every single time this component is rendered or auth provider as we navigate through our website technically it's always going to be updating it's always going to check the local storage and i don't want to do that so what i can actually do is take this entire value and i'm going to copy this so copy it remove it inside of ustay i'm going to use a callback function so we're going to create an arrow function in here and we're just going to simply set this value right here to the value i just removed from here so now we use the function so this means this value will only be set once on the initial load and it won't call it every single time so we're going to do the same for this so we're going to copy all of this right before the end copy that and let's add in that callback function so we'll add in the function right here and paste that value in so that's just going to make it a little bit more efficient so it's not so expensive on the browser and always having to call that let's test this one more time and now if i log in everything is working okay so before we start using that refresh token method what i want to do is just add in that logout functionality now this will be really easy here all we need to do is add in a function that changes our state removes that local storage or clears it and then simply redirects a user so let's just go ahead and create a function here and in this case i don't think we need to make an acing function yet because we're not making any calls here so we're going to say log out user so we're creating that function we're setting that value and in this section right here what we want to do is take this update method right here we'll paste this in right here so when log out is called we're just simply going to set these values to null so set user set auth tokens this is going to be null and we can take this local storage value right here paste this in and we're just going to do remove item and the item we're going to remove is going to be auth token so we're simply going to remove these values history.push is going to send us to the login page now so we'll just do log in and that's pretty much it for that function it's actually really simple we're going to take this log out function we're going to pass this into the context data we'll pass this through and we want to add this to the header so we can actually access this so in the header.js file we're just going to go ahead and destructure that so we're going to throw that in right here so log out user and then we'll just do on click let's call that function so on click call the function that should be it so let's test this out we'll refresh it log out we log out a user now we can't go to the home page if i hit submit now we're in there and everything looks good so if i hit log out you'll see the token right here get removed so that's it for the logout function now for the refresh function basically what we're going to do is create a function this function is going to be in charge of simply calling the refresh token method so remember that we have this method right here where we can take this refresh token so that's stored inside of our local storage and the state and we need to call every five minutes we're going to call refresh so remember in the back end with django we have actually that's in the other text editor so make sure both servers are still on we have this value right here so the access token will expire every five minutes so what i'm going to do here is update the access token every uh we'll just do four minutes the reason why we're gonna do that is because it's unlikely or it's gonna happen rarely but imagine that if we're calling this every five minutes let's say on that five minute mark at four minutes and 59 seconds a user tries to make a request to some kind of endpoint what can happen is this access token may take two seconds to respond that's kind of a long time but if it happens to delay then that user is going to have an issue it's going to log the user out and that's it so we want to make sure that the token updates before the user can make another request so we want to update it before that five minutes expires and then once that's updated the refresh token will be updated and we'll add another 90 days to that lifespan so we're simply going to add we're simply going to add 5 minutes and 90 days to both tokens or 5 minutes to the access token 90 days to that refresh token and it will blacklist the original token so in this endpoint we have the raw data we need to send refresh token we have to send the token that we got we submit that it's going to give us a new token and then blacklist what we have okay so we get we have the idea let's go ahead and build this in so we have the login user method we'll clean this up a little bit we also have the log out user method let's go ahead and create this method to update a user so we'll just do update or update token and we're going to add async right here create the arrow function we're going to make sure it's an async function set this value and for this what i'm actually going to do is copy a little bit from here so we're going to take this response and data from the login method and we're just going to bring that down to the update token method so we want to add in refresh make sure you have a closing forward slash there we're sending a post request we're sending this data json.stringify for the body at this point we're just going to send refresh like that so remember we need to send this right here that's what it's asking for for refresh that's what we're going to send to the front end and for this value we're going to clear up clean up the password and username we want to get the refresh token from auth tokens right here so that's stored in here so we not decode it but we store it as an object so that means that when this update token method is called we're going to go into auth tokens and we're going to access the refresh token so inside of our local storage right here refresh is not defined we'll worry about that in a second here let's just uh let's see where is that happening so line 55 let me just save everything right now so okay so refresh is not defined where am i calling that so i'm trying to see where it's actually calling it oh that needs to be re auth tokens dot refresh i think that was the issue okay so when you log a user in we have these two tokens let me try to zoom in so we have access and refresh so we're gonna send that token to the back end so let's go back here we send that token we get the data and all we want to do is simply update the data so we're going to run that same test we're going to check if everything went well with this update method we'll say if response dot status if this is good so if that's if the status code is 200 then let's go ahead and take these values set auth token or these two right here or three and we're going to update this state the user state and local storage so we're going to go ahead and update it if everything went successful so we're going to call that method then we also want to create an else condition if something failed that means something was wrong that something was wrong with the token we want to go to the logout method and we just want to take these values from the logout user and we're just going to call that right here i guess i could just call the logout user method so let's just trigger that right here so that's going to shorten our code here a little bit i don't think that's going to give us an issue so we should be good so this log out or the refresh token method is going to be called every five minutes so to actually make this work we need to use use effect here and call this every five minutes so let's bring this down here and we'll just go ahead and write our use effect right here so this is for our life cycle methods we'll do use effect inside of use effect we're going to pass in a function so we'll throw in a function right here we'll bring that in and we'll go ahead and add in a list of dependencies for these dependencies we're going to throw in auth tokens and we also want to throw in loading which we're about to create so this means that on the first load of the page this is going to be set to true so we'll just do loading and then we'll do set loading so when the page is first loaded we actually want to trigger this and make sure that we have a new token generated and i'll kind of explain where the issue can come in if we don't do this so loading is going to be true so we're loading the page on the first load then if it's uh once we get that initial load we're going to set that to false and that's going to be in the dependencies so in here inside of use effect let's go ahead and set a few values so the first thing we want to do here is set an interval so we'll just do set interval so we're using the set interval method this is built into javascript and what we're going to do here is trigger a function we're triggering this function and in this function we're just going to do if auth token so if we have some tokens let's go ahead and try to refresh this token so let's just call the update token method that's all we're doing we're just checking if it's there and we're trying to update it now let's go ahead and console something out here so we'll just call console.log and we'll just say update token called so we just want to know every single time this method was called so we just want to see this in the console so we're checking if the token exists and then we're going to call update token and make sure everything is running correctly so we want to call this let's just say every two seconds so we can do 2000 it's in milliseconds so that will give us two seconds and this interview method will be called every single two seconds now with this interview or interval we also need to clear it so we'll just do return and we need to clear it so we're going to call a function and we're going to do clear interval so clear interval and i'll explain what's going on here so with this interval what's going to happen is on the first method it's going to call this interval it's going to call this method every two seconds now when we continue to navigate through the website it's going to keep retriggering this function and it's not going to call it every two seconds on the first round it's going to call it after two seconds the next round is going to call it twice and then eight times it's going to keep doubling until we get this crazy timeout error so with set interval we need to set this value and this will be or set the return value and it actually returns back an interval id so the enter interval like that this is going to be an id so after we fire this we actually want to clear this interval and then as we continue navigating through the website it's gonna it's gonna make sure that it's always fresh and that we only have one cycle running i don't know if that makes sense uh you'll have to look into the interval method and it'll you'll probably find a lot of tutorials and documentation on why we need to clear it so this will ensure that we don't just go through this infinite loop so we get an id from this interval value it's going to fire off every two seconds and then it'll clear it once it's done but the interval will continue so we're just making sure we're not re-initializing it every single time so we call this method every two seconds and let's check this out so if i go back to the front end let's go to the console let's refresh it and it looks like we're actually running into some errors right now so let's remove this these two tabs here let's go ahead and open up port 3000 we're currently logged out so at this point it's not calling it or it shouldn't call it if we have no token so let's see we have the interval time we say if auth token so if we have any tokens then we call update token we set the time and then we return that value so update token should only be called if we have an authentication token so let's go ahead and clear this right here let's go into our local storage we'll clear it and that should fix that temporary issue okay so we're on the home page if we go to the console so let's refresh it we're not seeing the update token method called right now because we have no token so that's the first check we check if we have a token now let's see why it's causing the issue so if i log in it automatically fails failed to fetch let's see it looks like it's with the fetch call uncaught promise and let's check this out here so we'll go into the update token method let's see what's going on here so we check the status if everything's good we set the token data.axis and i think it actually might be with a back end so when we were making those requests there's a chance that it might have turned off our server so it looks like it did so let's just go ahead and start that server again so it seems like we're trying to make the request and the request is failing because it wasn't even on so let's go ahead and refresh that and let's go ahead and give this a shot so i'll try to zoom in a little bit when we log in we should now see the update token method called every two seconds so at this point we see it called it's just gonna keep updating it it's been called four times five times and so on so every single time that token gets called the access token and the refresh token are updated in the local storage and in our state so we typically wouldn't want to call it this often five minutes or 15 minutes is a little bit more reasonable so we'll update it once we're done with this testing so what's happening here is we're calling it on that interval and if we go into application if we go into our local storage it's kind of hard to tell but if you focus on these characters here let's try to zoom in a little bit left you're going to notice a few change here every two seconds so let's see if i can catch that somewhere here so let's try to move this over so it's sliding me over to the left because they are being updated but i can't actually see which ones are updating so it's updating the access and refresh token every two seconds and this is how a user can persist on the website so what i want to do here is i also want to make sure that the token gets loaded on the first load so we're not going to see this issue right now but i'm going to build something in so we can actually see it because it's going to be more practical to understand it so when we go to our website there's only two times at this point when our token gets updated on the first one is when we log in so we call the login method and the token is updated and also when we call the update token method every two seconds or later on it'll be four minutes now what happens if we log in and we happen to leave our website but our access token expires after 15 minutes what's going to happen is we're going to try to log back in and if that access token doesn't or isn't refreshed in time and we're trying to make another request to the back end maybe we're trying to get some user data or some kind of items that are related to that user it's going to make a request and that token will fail because it's expired because refresh only gets triggered every 15 minutes so if you happen to leave when you come back we need to make sure that update token is called on the first load also so i want to show you the issue before i fix it so all we have to do is ensure that update token is called on the first load and then every five minutes or 15 minutes whatever you want to set that to so for this we're actually going to go to the back end here and i want to actually render out some user information here so as you can see the network calls are being made right here so this is constantly updating it's being triggered every two seconds so let's update this so it's only happening every five minutes for now so we're four minutes so we'll do four minutes like this and this is going to be multiplied from 1000 to so 1000 milliseconds and then we're gonna go ahead and multiply that against 60 and then four so 60 not 600 so that's going to give us four minutes and we'll throw that in here so now that call isn't going to be called all the time and we'll actually revert this in a second to show you the error and then we'll go back to it so i just want to make sure to slow down those calls so in the back end let's pretend this is some kind of notes application so we're going to go to our database we'll build out a quick model here and we're going to associate this information with the user so it's a little bit of prep work here but i also want to show you how to create protected routes on the backend actually you know what i don't think we need to let's see yeah let's do it let's let's make this a little bit more practical so we'll go into our base app and this is going to be in base and not in api so we're going to go ahead and create a class here we're going to create a note so this is going to be like a notes app we'll just do models dot model we're gonna do some basic prep work so body is gonna be equal to models dot text field so we're setting that value and we also need a user so we want to get associated information so we'll say user this is going to be models dot foreign key and we're going to set that to the user object that's built into django so i want to make sure to get this value so the import is going to come from django.contrib dot auth.models and then we're going to import user and this dcb auth with a u so we import the user model we set that right here we need to run some migrations so let's just close all this out we'll clear it python manage dot py make migrations we'll add this to the database let's see what happened here models.model oh okay so there's a few things i need to set here so i'm going a little bit too fast jumped ahead of myself so for a foreign key we need on delete this is basically specifying what's going to happen to this object when the parent is deleted we'll just do set null for now okay so actually we'll just do cascade so cascade means that it'll delete it so that's going to be good at this point we also need to add in a default value so in the database because we already have a user we need to set null to true and that should allow us to migrate our database so we're going to make the migrations and execute those so python manage.py migrate and then let's run our server again okay so we just added that to the database i'm going to go to the admin panel we haven't even touched the admin panel yet but i do want to add some information from here so we'll do from.models import note we want to register this so admin dot site dot register we want to register the note model now that means we can go to the admin panel from port 8000 don't worry about this error we're not worrying about the home page here or the landing page to django my user information should be pre-filled i'm going to log in and now we can see the notes so we're going to create a note and we'll just say wash car save that and i'm going to attach this to a user so we're going to attach this to dennis then we'll just do add note clean room and there's a save button on the right where my face is covering so we're just gonna click this right here so you know what i'm doing there also need to set a user save that and let's actually add in another user so i want to show you how different users can have different information so we'll add in a user from here we'll say tim add in some kind of password let's confirm this okay so we now have two users so we'll add in a note to tim so we can see that there's three notes and each user has a different note so we'll just say learn how to code so tim doesn't know how to code that's on his i guess to-do list or in his notes so we have notes two attached to tim to attach to dennis so let's go ahead and actually work with this in the back end so we have these values and this is why we created the serializer so we're gonna have to do from django.serializer or from rest underscore framework.serializers import model serializer if you don't know what serializers are they're basically a way of creating json objects out of python objects so we're going to serialize this data and then render this out so it's a little bit outside of the scope of this video so from here we want to do from base dot models import note trying to go as fast as possible here because this is prep work and we'll just call this serializer note serializer and this is going to inherit from model serializer we need to add in the two minimum fields here so we'll just do meta and the model that we're going to serialize is going to be the note and then the fields that we want to serialize is going to be all of them so we'll just do all and this is going to be the body and the user so we have the serializer let's go into our views here and we're going to import this so we'll just bring this down here so from dot serializers we're going to import the note serializer then we want to bring in the model so from base models import note and let's create a view to actually get this data so this is where that error would occur so we're going to create a view here we're going to call it get notes we're going to pass in request and we need to take this decorator and also add it right here let's add in the colon here we'll do return and then we'll just do response and we're going to pass in serializer dot data so the serializer object has a data attribute so we're going to use this right now so to start we're just going to get all the notes so we're going to do note dot objects dot all and we're going to serialize these notes so this is where we're going to get that serializer so serializer and that's going to be the note serializer so we're getting this value we're basically saying we're going to query the database for all these notes we're passing these notes into the serializer and we're saying serialize them and many is going to be set to true meaning there are going to be many notes to serialize so we want multiple items so we have the view it's called get notes we're going to save this let's go into our urls here we'll create a path here so we'll do path this is going to be forward slash or api forward slash notes like that we're going into views dot get notes and that should give us all the notes so let's test this out and eventually we're going to get a specific user's notes here so we'll go here we'll go into api forward slash note notes like that and that should give us that route let's see what's going on here i see what i did there i wasn't supposed to add an api because that's already prefixed from the root urls file okay so here we go we see all three notes here so let's go ahead and actually make this a private route so that's the first thing we're going to do so in our views we want to go into our decorators and i believe this is permission classes so from the from here we also want to go into rest framework dot permissions and there are different types of permissions we can import so the one we want to do is is authenticated so we can create our own permissions later some permissions only allow admin users to actually get information in this case we're going to say a user has to be authenticated now to actually work with this we're going to go ahead and create this view here or update this view and we want to add in that decorator so we imported it so in this case this has to be underneath api view we're going to do permissions classes and this is going to take a list in this case we're just going to throw in this permission so we imported the decorator and then the actual permission so if i save this and that was in the wrong view so i need to bring that down here to get notes so what's going to happen here is if i try to go to this view and i don't pass in a token that's the access token from the front end it's going to block me so i'm going to this view but i have not passed a token now we couldn't use we could use something like postman to test this in this case we're just going to go right from the front and send this token because it's kind of outside of the scope of this tutorial just trying to show you how to create a protected route and how to get a user now before we actually try to get this route here let's go ahead and make sure we only get the users notes here so with that token the view actually knows how to decode that token based off of this decorator so we can actually go ahead and set user to request dot user so it's going to get the user that that is associated with that token it's going to decode it it's going to get the user object and then we can go into user dot note underscore set dot all so that's how we get all the children and that will give us only that specific user's notes now we can't see anything because we can't even access that view because we're not authenticated so let's go ahead and actually get this information from the front end so we'll go into our application at this point we'll leave alt context open we'll just go into the home page so we're going to code this up pretty quick so we're going to need use state we're going to need use effect and we're going to go ahead and create some state here in the homepage so we'll just set this value to notes and update notes or set notes and the state here use state this is going to be an empty array so before we actually load this information in it's going to be empty until we update it now at this point let's just go ahead and create some kind of list so we'll create a ul and we'll create some li items here so we'll loop through the notes we'll do notes dot map and we're going to pass in each note we're going to continue on with this arrow function so we're going to map through all these nodes and we want to create an li tag on each iteration so for some reason it looks like it's not working properly what am i doing wrong here as i'm mapping through it we do notes dot map we create the function oh i did set nodes that's supposed to be notes like that so we're going through this array and we're just going to output a list item for each note so we're going to do li and we'll just go ahead and output note dot body now this is a little bit outside of the scope of this tutorial but we do want to set a key here or a key prop we'll just do note dot id there is an id automatically generated and that's it so if i go to the home page we're not going to see anything here so notes is not defined let's try to refresh this why is notes not defined so if we go up here that's note so set notes okay so i'm on the home page we're not seeing any notes because we haven't actually made the request so let's go ahead and actually make this request then we'll just do use effect and on the initial load we're going to trigger this function right here that's going to be the use effect we're going to add in a list of dependencies at this point we're going to keep it empty and we're just going to go ahead and call the get notes method so we'll just do get notes this will be an async function we're going to continue on with this function that's an arrow function make sure that that's set and we're going to call fetch here so we're calling fetch we're going to notes so this is the endpoint so we want to go to this poor 8000 api forward slash notes we want to get all the notes from this route now we also need to throw in some headers here so the method here is going to be get so we're sending a get request to the back end so we're getting some data in the headers let's just go ahead and set this i actually don't think we need content type but i'll just set that just in case even though we're not sending data so we probably don't need it okay so with these headers we also want to send the token so with the headers we're going to go ahead and add an authorization so we're throwing in authorization and we want to throw in bear and this is where you can actually customize this in the back end in django here in settings you can actually access how you get that token so you can actually change this value and that would change how it's accessing the front end so this is what we're using so capital b right there make sure you're throwing that in bear and then we're going to add in a space and we're just going to add in a string value just in case and we want to throw in the token right here so we're storing that token as we log in and we're sending this on each request specifically to get information that's protected for a specific user so let's go ahead and actually get that token so we want to import use context here remember now we can use that data in any part of our application so we'll do let and we want the auth tokens so we'll get these values right here so auth tokens we're going to throw that in we're destructuring that we're gonna do use context and we're just gonna throw in auth context so that's gonna run this import also automatically we're getting the tokens we're gonna go ahead and on each request we're passing in dot axis okay so need some water here okay so we're sending that token request or we're sending that request on each call let's go ahead and get the response so we'll get response that's gonna be a weight set that value let's parse this data so we'll do let data is going to be equal to response.json we'll get that response and then we're going to set nodes based on that response so we're going to throw in data and that should pre-fill our state so we are going to run into a few issues at this point we should be good but we'll show those issues and then we'll fix them so if i'm on the home page so let's log out let's log back in let's see is that call failing oh i didn't add that into use effect here so i need to trigger this so get notes is going to be triggered right here inside of use effect we'll call that so on the first load we're going to get those notes and let's see so axis is undefined so let's try going to log in i want to make sure we're logged out let's try to log in access is undefined uh what's going on here so it should be set off tokens here let me make sure my head is out of the way here i want to make sure you can see everything sorry if i blocked that earlier so auth tokens is brought in right here from use context we should be able to see it i'm not sure why we're not seeing that i think we forgot to add in auth tokens in the context provider because we have it right here it's definitely working but i need to make sure that it's in the context data yeah so i need to throw that in right here because that needs to be passed into the provider and that's how we have access to it down through child components so we need to fix that let's see okay we have another error node stop map is not a function let's check this out so in home right here it's definitely a function okay so it looks like it's just trying to map through the wrong data i forgot to add in a weight so that should fix it for us so let's try this right now and if it's still giving us an error let's just go ahead and try to go to the login page we'll log out we'll clear everything and let's try to go back here so at this point it's all good i'm logged in as dennis and i can get dennis's notes now if i log in as tim i'm going to get tim's notes so tim only has one note dennis has two here okay so now it's time to show you some of those errors that i was talking about so the first thing is is we want to make sure that we get a new token on the official load so we use the refresh token and i also want to handle any errors that occur right here so let's say that in our configuration in the back end this was set to five seconds let's just do seconds here and we'll set that to five seconds so the access token only lasts five seconds so if we log out here right now let's go ahead and refresh that we'll submit that and we'll close that so let's wait one two three four five we'll just go to six seven make sure we're waiting five seconds now let's try to open that up so if i open this up what's going to happen is because we have not generated a new token we're going to try to use the access token that's in the browser right now which has expired because it expires after five seconds so i'm trying to replicate what a bad call might look like so if i go ahead and open this up we're going to see this error again so first of all i want to handle some i want to add in some error handling right here inside of get notes and i want to make sure that we only set this value if the notes are okay if everything went well so let's go ahead and create a condition here and we'll just say if the response and this is inside of home.js so if the response.status is good so only when that response is confirmed to be good should we set these nodes so we'll go ahead and take the set notes value we'll add that in right here and that will finish that request now we also want to check we'll just do else if we also want to log a user out if something doesn't go good so if the response status we'll just do response dot status text so there's different values you can go ahead and console out response so django will also return back a status text here so there is a status text and the value here is unauthorized so that's the type of text here we could just have it log out on any fail so just go ahead and paste in that status text i want to make sure you can see that so if that response is unauthorized because when we go to this route it's going to give us this unauthenticated user or no credentials provided and the status text will be unauthenticated so if for some reason that fails then what we want to do is just log out a user so really quickly we'll just go ahead and get log out so it's already passed into our provider so we'll do log out user we'll take these values right here we'll go to the home page we'll get that from our context right here from the provider and we just want to log out a user so if something fails something went wrong with the token we want to immediately log out that user so let's try this again we'll go to the react application so we'll log in let's say that we closed it we're waiting one two three four five six so now the token should be expired if we go to this page it automatically logs me out so that looks good that's exactly what we wanted now there's kind of a small issue with this is the fact that my token is expired that shouldn't break my application we should be able to get that refresh token and update it before we run into this because usually when you come back your token will be expired not the refresh token but the access token will be so what i want to do next here is actually make sure that the user gets a new token whenever they first load their page so inside of our auth provider we only get a token when a user logs in and we call the update token method every four minutes here so we set that interval but we also want to make sure that this method gets called when they load up their page first so what's going to happen here is they still may have that valid refresh token but the access token may have expired and then in the home page here we're going to try to make this call and get notes the access token is not going to be valid and it's going to log the user out so before we make any calls here we want to make sure that this is updated and we're ready to go and we also want to make sure that everything inside of our alt context here is called before any component below it is rendered so we want to make sure that all the calls are successful here and then we let these components render out so we're actually going to try to delay this so inside of our alt context we have this loading method and loading is going to tell us if everything inside of our auth provider is done and ready to go and if we can render out those child components so we're going to update this so loading is set to true by default when we first open up the website and we're going to go into use effect here and let's just check loading so we're going to do if loading so we'll check this value here and if it's true that means we're still needing to update our token let's just do update token so we're going to call this and that will update the token now we only want to call this on the first method so we need to set loading to false because we don't want to call this every time use effect is called so inside of our update token method we also want to go ahead and set loading so we're going to check loading again we only want to call this if loading is true so on the first render we're just going to go ahead and update it once loading is done so we'll set that to false so it's going to make sure that we either log our user out or we update a new token and that should be good now if our auth token is not there yet what we want to do is add in a question mark here and make sure that we're not trying to get a refresh token if auth token hasn't been updated so if we don't have anything there at all we don't want to throw an error we just want to log our user out so this will throw an error if we don't have this so this is a little shortcut instead of having to write a condition like if auth tokens refresh exist then render this out this is just a nice little shortcut to let us just make sure that we actually have something before we send it so technically this call will fail and it'll log a user out if this doesn't exist but that's a little nice thing we can do to fix that now down here we also want to make sure none of these children render out before all this is complete here so let's go ahead and actually check this so we'll create a condition and we'll just check loading so if loading is true we're going to render out null else we want to render out the children so this is going to make sure that none of these items are rendered until auth provider is complete so let's go ahead and save this and let's try this again so we'll go back to the website let's log in here and we want to wait five seconds so we'll just wait one two three four five and i just want to check this make sure that our token is actually set to five seconds so it should be expired by now because it sets you five seconds but our auth or the refresh token is still valid so if i try to refresh this page we're still going to be logged in so what happened is on the initial load that update token method ran and we quickly updated what we had in there so we'll just go ahead and console this out so you can see it so we'll just say updated token so console. and we'll just do update or updated token so let's go ahead and save that and if i go back to the website we'll go into inspect here and we'll just check out our console if i refresh this we can see that update token is called and then everything else is rendered out so we quickly go ahead and make sure that we have a new valid access token and everything is good to go so that's it for this video what i want to do is just go ahead and set all these settings back here so i think a valid lifetime here would be five minutes so we'll just do minutes here and we'll just set that to five minutes and we'll update our token every four minutes or you can set that to like four minutes and 50 seconds just to make sure it happens before that token actually expires so that's it for this video but what i want to do next is actually use the axios method where we use that interceptor and actually update the token on every single request and that way we're not setting this timer so it's just a different way to do it and i also want to try doing this with fetch but it's going to take a little bit of customization specifically doing this with react and how react hooks work so we actually might have to write some of our own hooks so i'm going to get to those videos i'll see how this one works and see how you guys like this let me know in the comment section if you found different methods i'd love to get some feedback from everyone
Info
Channel: Dennis Ivy
Views: 11,624
Rating: undefined out of 5
Keywords: Programming, Software Developer, Dennis Ivy, Dennis Ivanov
Id: xjMP0hspNLE
Channel Id: undefined
Length: 129min 52sec (7792 seconds)
Published: Sun Oct 17 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.