JWT Authentication Node.js Tutorial with GraphQL and React

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

I walk you through setting up an entire project using JWT authentication.

Technologies used:

  • React

  • Apollo

  • Typescript

  • GraphQL

  • TypeGraphQL

  • TypeORM

  • PostgreSQL

πŸ‘οΈŽ︎ 54 πŸ‘€οΈŽ︎ u/benawad πŸ“…οΈŽ︎ Sep 20 2019 πŸ—«︎ replies

Thanks for the work

πŸ‘οΈŽ︎ 6 πŸ‘€οΈŽ︎ u/dushyantjoshia πŸ“…οΈŽ︎ Sep 20 2019 πŸ—«︎ replies

love u ben <3

πŸ‘οΈŽ︎ 4 πŸ‘€οΈŽ︎ u/lucastrvsn πŸ“…οΈŽ︎ Sep 20 2019 πŸ—«︎ replies

Is this considered to be the β€œgold standard” for authentication? Thanks for the video OP

πŸ‘οΈŽ︎ 4 πŸ‘€οΈŽ︎ u/Swoo413 πŸ“…οΈŽ︎ Sep 20 2019 πŸ—«︎ replies

I was just checking out your repo after watching your last video and reading the Hasura article you linked to, looking for the best way to handle ssr auth. I'm super excited to go through your new vid.

Thanks for all your hard work and great videos!

πŸ‘οΈŽ︎ 4 πŸ‘€οΈŽ︎ u/9aquatic πŸ“…οΈŽ︎ Sep 20 2019 πŸ—«︎ replies

Amazing class - clean and concise to the very end. Loved it!

πŸ‘οΈŽ︎ 3 πŸ‘€οΈŽ︎ u/oldyoyoboy πŸ“…οΈŽ︎ Sep 20 2019 πŸ—«︎ replies

upvoted & following

πŸ‘οΈŽ︎ 4 πŸ‘€οΈŽ︎ u/[deleted] πŸ“…οΈŽ︎ Sep 20 2019 πŸ—«︎ replies

You need to sharpen your Vim skills my man! I strongly recommend Practical Vim by Drew Neil.

πŸ‘οΈŽ︎ 2 πŸ‘€οΈŽ︎ u/YodaLoL πŸ“…οΈŽ︎ Sep 20 2019 πŸ—«︎ replies

Anyone have any opinions on cookie sessions vs jwt? For persisting user sessions ?

I have heard that cookie-sessions should be preferred, any thoughts ?

πŸ‘οΈŽ︎ 1 πŸ‘€οΈŽ︎ u/[deleted] πŸ“…οΈŽ︎ Sep 21 2019 πŸ—«︎ replies
Captions
and welcome to my JWT authentication tutorial so in this we are gonna be building a full stack project to show you how to integrate authentication with JW TS and the entire thing so we're gonna be doing this in a way where we store the access token in memory that's what we're gonna try to implement and this is a more secure way of doing it now I want to show you guys what technologies we're going to be using to actually build this project we're going to focus on JWT in general that's kind of the main focus of the tutorial but we're gonna be building a back end and a front end and see how they interact and so these are the things we're gonna use to do that and don't worry if you don't know all of these I'm gonna be walking you through the entire process so if you want to learn any of these this is a good time so for the whole entire project we're gonna be using typescript we're also going to use graph QL and type graph QL this allows us to basically integrate really easily type script and graphic ul together on our back-end and then we're gonna be using Postgres sequel to store our users for database and we're going to be using type arm to interface as our ORM and then lastly we're gonna be using react and Apollo to tie everything together so Apollo we're going to be using to make requests and react and we're also going to use it as our server with Express so yeah so we're gonna be using node.js as well so here is just a quick overview of what we're actually gonna do in this video so to start off we're going to build it back end so for that we're gonna start by just setting up a graphical server with type graphic you land type warm after that we're gonna go over how you can register a user create a user in your database then we're going to log in users and get them access tokens and create refresh tokens for them then we're going to go over how you can create mutations and queries so these are just routes and graph QL how you can authenticate them or protect them so for example if I want to make sure that someone has an access token before they do thing we're gonna see how you can do that we're then we're getting over what how you can actually refresh a token if it expires and then lastly we're going to talk about how we can actually implement how you can revoke a refresh token for a specific user or revoke all the Refresh tokens for a specific user say if that user logs out or something or forgets their password and you won't order their account gets hacked and you want to basically invalidate all the sessions this is how we're gonna do it all right and then after that we are going to be doing some front-end stuff and see how our front-end actually interacts with our back-end so first we're gonna just set up the project and setup with Apollo in graphical code generator so this is gonna allow us to very easily create queries and mutations that are type safe because we're using typescript then we're going to just create a couple routes using react router and CA with register and login form and then we're gonna see how we can protect those routes and we can persist the users session so when they refresh the page we're going to make sure that the user is still logged into their account then we're gonna handle what happens when we make a request and the token is expired how can we refresh the access token but the user doesn't even realize it they're not even logged out we just automatically in the background handle this and then lastly kind of just go over how you can fetch who the current user is and say display that user in the header or if you want to display this user and your page how you can get the current user so that is the plan for this video we're gonna be covering all these things and we're gonna be starting with the backend right here cool so without further ado let's go ahead and get started so we're gonna be setting up the graph kill server and type graph QL and type arm so what I have with me here is just terminal open and I want to just start the project and we're going to basically create some boilerplate code from type form to do this so to do that we need to install the type warm CLI so you can do so by running the following NPM I - G type warm now I'm assuming you have a node install on your computer so if you don't you're gonna need that I'm on 12.6 right now and then I'm using MPM 6.9 so when they install a note am/pm will come with it then after that we're going to say type warm in it so this should install this CLI so we can now run this command I'm calling my folder or my project server you can call it whatever you like I'm in basically a base folder called JWT off example and I'm going to create a server folder and a web server or a web folder and then here I specified the database I'm gonna be using as Postgres so if you want to follow exactly use this as well but really the database used for this doesn't matter we're not really doing anything database specific alright so you should now see a folder called server and if you go inside that you should see you have a package about JSON with some stuff inside of it readme which we can kill TS config this is kind of a TS config is kind of lacking so what I would recommend is changing this so the TS config that i use i have stored in a package called TS config JSON so if you'd like to have the same TS config as i have just run the command oops run this command MPX TS config dot JSON an MPX should be installed when you install NPM slash note so this is basically going to download a package and then run this CLI and what the CLI does is it asks you if you're using a react project and in this case we're using node side select node and just puts a TS config with options that I prefer alright so we're gonna be following that and then our package drop JSON is a little out of date when we get this project so what I like to do is whenever you have an out-of-date package JSON you can upgrade all the dependencies inside of it by saying yarn upgrade interactive so yarn is kind of similar to NPM I prefer using this so I'm gonna be using yarn from now on so if you don't have that probably install it is pretty nice so yarn upgrade interactive - - lay I run this we don't even have a lock file yet I guess we have to run yarn to actually install these dependencies first and then we can run this command so let's do that so when this is done then we'll just rerun this upgrade interactive and I don't know if it just automatically does it alright this is what I thought so this is basically just asking us which dependencies we'd like to upgrade so I would like to upgrade this one and this one and this one and this one so what I did here is that you just use the spacebar to say you want it and that fills in the green dot and they do the up and down arrow to actually select them and then I'm just going to do enter to install everything alright so that warrant config actually has the information to connect to your database so in my case I said I'm using Postgres it's localhost this is the port the username password in the actual database so if you don't have Postgres installed go ahead and install that now and create a database so I'm gonna just call my database jvt off example I'm going to copy this and I'm going to say create DB jvt off example so now I have a database set up if you don't know what this is go Google how to create a Postgres sequel database on your computer and this is one way you can do it so once you setup a database put it there and then your username password you're gonna need to create a user for it I have a default one called Postgres I believe so we'll see if this works this should work for most once if you don't have a user go create Postgres user and stick the credentials there alright so once you've done that you should be able to run this right here and failed to load yes aline we're not going to worry about excellent for this let me just turn off you Salons real quick so I'm just gonna disable for this workspace and we will reload all right so we should now be able to run this so I believe in our pictures of JSON yeah we can run start and this will run this so let's do that and see if it works so when I do yarn start couldn't find a Oh need a CD into my server and [Music] so it's inserting user and we see this cool so if you see the same output that means it worked and you can see the actual code for getting this to work this is just some type arm stuff to create a user and make sure the database connection works so at this point our type warm is successfully set up I want just close this now so the next thing that I want to do is actually set up our graph QL server so to do that I'm gonna say yarn add and we're gonna install these three packages Express Apollo server express and graph QL and then we also need to install the types so for express and for graph QL Apollo already comes with them alright so yarn add as a dev dependency should have a node already good types node you need this whenever you're doing typescript and node.js stuff so this is to make sure we get a good Auto completion and we know the types for the graph QL package and for the Express package so install both of those alright so here I'm going to import Express from Express and we're gonna create an app here and we're gonna be doing some async and await stuff so what I want to do is I'm gonna comment this out by the way if you don't know how to bulk comment you just select everything or you can just drag like that and you put command and / or control / / and that will actually comment all out so I'm gonna create a little function here alright so this is a lambda function right and it's just calling itself and then I put parentheses around it and so then I'm making it asynchronous so now inside this function block I can actually write a sink and a weight code and we're gonna put all of our basically logic to start stuff here all right so we have app then app dot listen and say port 4,000 so this function gets called whenever the app starts or the server starts so I'm just going to console.log + now and I'm just going to delete this for now so I just have a reflect amount of data and Express here and if we want to verify that our setup here is right we can just say app get and we can ignore the first parameter so whenever I want to just ignore the first parameter of function I usually just put an underscore for the variable name but this is also known as request just sometimes see that too you just put the beginning so we're gonna say response dot send and say hello all right so I'm gonna just run my server to make sure it works and so now I just want to go to localhost 4000 and then go to the index route and it should send hello to me so localhost 4000 slash and now I see hello so perfect so that means Express is working correctly so now we need to integrate the graph QL portion so we're gonna import from Paulo Server Express get Apollo server and just so you know you can keep all your express routes so we can keep that there if you want to and we're going to say a new Apollo server and then this is where we can put settings so I can put typed ups this is where we declare with a string our graph QL schema so I can say type query hello returns a string and then I can create resolvers so this is a object which contains a mapping basically we get the data that our schema needs so we have a query and we have hello and this returns a string of some sort so hello world alright cool so Apollo is happy with us so far so now we're just going to say Paulo server dot five middleware and we pass in our app all right so once we've done this what's going to happen is we find what our graph QL stuff is here and we have added our graph QL stuff to our Express server here so now if we restart our server see if we made any errors nope looks like it started if we go to this / graphic ul we should can see graph QL playground so this is some old stuff that I've done in previous projects but if you're coming here for the first time it should look like this so this is a cool thing you get when you use graph QL this is an interface that just allows you to query and see how everything would work so I can go over here click the docs and I can see what's available to me and I can run hello so over here you can actually write your query so I'm going to say hello you can run purify and here we can now run it and see the results so we can now see hello so this is a little playground where we can run queries and see the results so cool so if we see that Apollo is set up and expresses good so let's continue on from here the last thing I want to do in this section is just setup type graph QL so basically this is a perfectly valid way of doing graph QL but when you start doing type script stuff it is harder to get the types working and you do some duplicate work so type graph QL is something we're gonna add to make our life easier so we're gonna say add type graph QL so this do I spell it round type graph QL oh I think there is I feel a dash in between it so like that all right so what we're gonna do is instead of creating our schema like this we're gonna create it in a different manner so now I'm going to create a file here called resolvers and can import from type graph QL and here I'm going to say at resolver and here I'm going to say resolvers so basically now I can create my graphical schema inside of here and as I create it I'm actually gonna tell type graph QL both my graph QL types and my typescript types and it's basically gonna check both of them for me so I'm saying that this class is a resolver and I guess we're gonna be doing user stuff so I'm gonna just call this a user resolver instead of that so let's call it user resolver and I would like to do a query and we're gonna do hello and this is gonna return hi so queer we got imported from type graph QL and here I can tell it what type it returns by putting a function here and then an upper case type so in this case we're returning a string so like that all right so instead of over here passing type deaths and resolvers we basically just did the equivalent of this in our user resolver over here that's what this is so now I'm gonna say oops leave it too much schema and we're gonna say a weight build schema and build schema we want from tech graph QL so inside of here we're going to pass in an array of resolvers our user resolver all right so let's just recap what we did there so we are using this build schema function from type graph QL and what it does is it takes our resolver over here and it's going to create a graph QL schema out of it and we do a weight here because this is a a synchronous function so now we can just restart our server to make sure everything is working all right so it's up and running come back over here you can refresh you can see my hello one no and if I run this we can now say it says hi exclamation mark and that's exactly what we have over here so cool so now we're going to create users or create our register mutation so in graph QL mutations are what we create when we want to update something create something make it change to our database so we're going to say at mutation and this is going to be a decorator let's close some of this stuff that comes from type graph QL so this is how we define we want a mutation then here we're gonna say register and we're gonna say return and we can put our body and stuff inside of this now for a register we need to take some arguments so in this case I'm gonna say arc that's coming from type graph QL I'm going to say this is going to be email which is a string and how this works right here is so this is the name of the graph QL argument so this is what the user will actually pass in this is my variable name I call it email same name this is the typescript type now tech graph QL can infer what this type is but if it could not infer what we can do is we can say as our second parameter here a function and it will automatically know right so this is us explicitly saying that this argument is of the type string but explicit should be fine for the Supes so we'll just do this all right and then I also want a password all right so we now have two arguments email password therapy paint that are being passed in and now inside of here I want to create my user now I'm gonna want to create the user in my database so we're gonna start with how do we actually define our database and create the schema for it that's what our entity is over here so our entity so you can see this is how you do stuff in type form is you create a class you add fields each field usually maps to a column and those are database columns so in this case I'm gonna create two columns called email and password and I'm gonna keep this ID field that's all well and good and give that save and I'm gonna say here extends base entity this is just a type worm thing that allow us to say user dot Save and allows us to do commands like that it's a little bit easier it's called the active record pattern so we're gonna be using that and you'll notice all this is coming from type form over here and you annotate this classes entity to say that this is a database table and that these are the columns we can also explicitly say the name of our table so I'm gonna just call mine users here that way doesn't have a conflict with the user table but again you can call this whatever you like so the next thing is how do we actually tell type form to create this and know this exists well one in our arm config we have an entity mapping so you see how it says source entity source entity and that's where all our stuff is located so that's how it knows about it and then in our index over here we just need to create a connection like this so let's start I'm going to say a weight create connection and that's pretty much all you need to do with type warm so now the connection is created it knows where your entities are and it knows what the connection information is all from your arm config so if any of that stuff is wrong this is where you go to fix it okay so we create a database connection we have our database setup do we have it set up to synchronize we do so what this means it's going to automatically create the database tables for us and that's what we want so now in our resolver over here we can do something like user dot insert and we can insert our user inside of there so I'll make this function asynchronous so we can do this now remember one is you don't just do email and password you want to hash your password before you store it in the database so we're gonna be good citizens and do that as well now feel free to use a better hash than this but I'm just going to use bcrypt so if I'm gonna use argon go for it but we're just gonna use bcrypt j/s for this and then I'm gonna say add a dev dependency install the types so some libraries come with typescript types some dolt this one doesn't so we need to add it separately all right all right syringe import bcrypt and then we can pick which function we want here I'm gonna choose the hash one so this is going to be the hashed password is equal to hash and here we pass in our string which is the current password and then a salt I'm to go with 12 and we're gonna pass a weight here because this is an async by default if I hover over this you can also see it this is a promise all right so now we're gonna pass in this hashed password also I'm not sure what this is complaining about see what it's string is not assignable oh we go to our user entity here I left this as a number should be a string and by the way the database columns are automatically inferred that this should be a text column but you can explicitly say what the datatype of your column should be with type arm as well so I could say this is a Postgres text column and by the way if you saw me just like hop back over to my entity file the way I did that where was I here is control and then work command and then clicked on it and takes you to where it was created all right so I can insert my user into the database this way so now what do we want our mutation to actually return well we could just return a boolean true or false whether it worked so I wanna say it returns a boolean and we're gonna say true it worked and if we want to just do a try/catch we could and on the air we're gonna log it and return false it did not work alright so this is going to be art register function so I'm gonna go ahead and start the server now you notice we're constantly stopping and starting the server let's make our lives a little bit easier so there's a package called node demon that can restart this for us so we're going to install this guy and this is a dev dependencies so I added dash D alright so of this yarn log here we don't really need that let's kill it so now in our package dot JSON and the scripts start we are gonna say no demon - - exec in front of it so basically we're telling it what to run here and then this is going to go ahead and automatically restart when we make a change to our server alright so we're gonna start this up and so let's go ahead and see our docs here I can see the registers there so mutation we're gonna say register we're going to say email Bob password vault [Music] so we run this we hit a true so that means it worked correctly if it didn't go check your logs see what we wrong with your register now - to make sure we can actually see this guy in the database I thought real quick we might as well just make a query for this so let's make it query and we can call this users and then we can just return all the users in our database and then we're gonna say user dot fine alright so this is a query that finds all of our users and in our database and then returns them so here I want to return an array of users I'm gonna do this so the only thing that may be a bit odd is this data type here so you notice we have user if we click that that is this class right here so we can actually use this type as a type graph QL type or is it graph QL type and the way we do that is by saying that this is an object type and we can just annotate these fields so we can have a field type here and a field type here and I don't want to expose the password so we can choose which fields we want to expose and which we don't so I don't care to show the hash password so all I'm going to do is expose these two fields also it's going to infer string it cannot infer a number because it doesn't know whether it's an integer or a float so it's you're just going to do int ear and this is coming from type graph QL all right so save our server should be restarting here and you'll notice the air we got before we add this object type well before cannot so this is the air you'll get if you do not add the object type and actually set a graphical type it'll say cannot determine graph QL output here's at the bottom cannot determine graphic you'll output for type users so that'll happen whenever you don't actually explicitly specify the type here as an object type when you use it as a type here so that's how you do a ray of users and we specify what fields we want to expose so now if I come back over here you can do a new tab you can grab all of our users can grab the email and ID field nice you can see our dude there so now go ahead and add more users if you like and see fetch them here and make sure that works for you that is how you register users so now let's go ahead and login these users and give them an axis and refresh token so to do this we're going to create a new mutation and actually I'm going to just copy the one we have here because we can keep some similar attributes or structure so this is going to be login it's going to take an email and a password and the first thing that we're gonna do with our login function here is see if this user exists so we're gonna say the user is equal to user dot find one we're gonna wait this and then we're gonna say where the email is equal to this email all right so we're searching to find this email and if a user does not exist we just want to throw some kind of error so we can just say thoroughly error invalid login all right we could just give some generic error or we could just be more specific did not find user so depending on your use case and specs pick whatever error message you want but we couldn't find a user to actually log them in the next thing is we need to actually compare the password and see if they passed in the right one you know say valid is equal to and this comes from bcrypt and I'm gonna get the compare function so we're gonna say compare and looks like we pass in the plain text string so that's this and then the hashed password which is going to be user dot password alright so now we have this valid boolean so if it's not valid right in through an error [Music] and they pass in a bad password but if book these things are right the user has successfully logged in right they have successfully logged in so at this point we want to give them the tokens so they can stay logged in and they can use that to access other parts of our website or our API or a graphical schema all that jazz so what we're gonna do here is we're actually going to return the access token so here we're going to say access token and actually we'll turn what that value should be the Refresh token we're gonna pass in in a different place which we're going to talk about in a second but first I want to just match our mutation type here and make sure it all lines up so here I'm going to create a new object type called login response and this is a class and this just returns an access token which is a string and this is a graph a type graph QL field so login response is what we're going to return and if you want to get the type script to checking it you can put it here too and this should be promised so now we told type graph QL what the graphic you'll type is it is an object which has a single field access token and it's a string and then we also said typescript verify that we are returning a promise of the type login response so like if I got rid of a character there it's gonna tell me it's wrong because it's expecting this format so cool so that's setup the types let's go ahead and actually return the correct token now so to do that we are going to install a new library so we're gonna add a library called with JSON web token so this is a library that just helps us create invalidate JW TS and we need to add the types for it so we're going to do yarn add - D types so here we're gonna say sign so here I can say sign and sign is the function you call to actually create a token so what you pass it is a payload so what you actually want to be stored inside of this token so in this case I'm gonna store the user ID but you could store more info if you want like the email profile whatever you care about the second parameter is the secret alright so this is a random string just create it like that for now if you want to this is a string you need to hold on to because this is the secret that we use to verify whether the token is valid or not and the last one if we hover over we can see is the options that we have available to us and the thing that we care about in this particular case is expires them so this case I'm going to set how long my token should be valid for and I'm getting a little off screen so let's pull this up okay so I'm going to say 15 minutes but again depend on use case you can set this a different time but in general you want your access token set to something shorter so like 60 minutes maybe a week is probably too long I'm gonna set mine to just 15 minutes and we may come back and change this to something even shorter for testing but we can keep this for now so let's go ahead and just run this and make sure we actually get some kind of token back from this so we're gonna start a server back up and by the way I didn't really show that I was ctrl C to get out of this that was kind of a soon Bush probably say if you want to cancel out of this being run you can control C okay so do a little refresh we should see a login now so if I run this I can see my BOB user so let's try to login with Bob [Music] alright so the first thing I'm gonna do is I'm gonna say Bob at Bob calm one so this is an incorrect and we also have to there we go ask for an access token back so you notice I put the wrong email in Nice I just want to make sure got the error could not find user now I have the wrong password and we got a problem this did not work so let's go back and see what I did wrong and I see what I see my error immediately I just forgot to wait compare so if we hover over it you can see that the compare should return promise so we'll wait I give that a save now let's try this again wait for our server start back up here alright I'm gonna run this again and now this is exactly the air we expect bad password so now if I put my real password Bob nice we get our access token now and so cool so this worked this is our JWT that we actually want perfect and that's kind of how I want my JWT be created and returned like this so now I want to create a refresh token as well so let's do that now the Refresh token is a little bit different because we want to store this in a cookie soda store it in a cookie we actually need to use the Express res and we need to say res cookie to create a cookie so to get access to this we need to access the context or pass this end through the context in graph QL so how do I do what I just said well you over here what we're going to do is we're going to say context and this isn't our Apollo server or in our index right now we're going to grab the response and put it inside of here that's all there is to it and while we're here we're also passing the request so there we go so the request and the response are now inside of our context so in our graphic you'll resolvers we can access both of these all right so I also need to create a context type so I'm gonna say my context my context es and I'm going to export and interface this is just for typescript purposes so I'm gonna say rec is equal to Express I think I think I want to I just want to make sure I get this type correct I'm gonna hover over this and this is what responds and we will try it auto importing these think I want to do it like this request and response [Music] cool so I think I set this up correctly so now what I can do is in my user resolver over here you can say at C T X stands for context and make sure you do a comma here and now we have access to the context here and you'll notice I also I'm using my my contacts type I'm importing that so now I can D structure this and I can do requests and res is inside of there so at context this is just a type graph QL thing to give us access to the context all right so in this case all I care about is the response here so here I can say response dot cookie and I can say the name my cookie call it JIT this is something where I kind of just usually pick a generic ID name so really no one knows what the heck it is so we're just going to do that and then for the value this is we're gonna pass in our actual token so that's where we're gonna do something like this now in my refresh token you may want to store different attributes personally I'm just gonna store the user ID again in this so I can know who this is for and then the value here you're going to want to put a different secret than what you used here so I'm gonna do some other value and then lastly our options you're probably gonna want to make this last longer so the shortest I would probably do is maybe 7 days so this is something where maybe you the user hasn't accessed your site for some amount of time so whether you wanna make that a single day maybe seven days maybe a year they haven't logged in then this is gonna log them out and this token has expired so pick whatever time you want I'm gonna go with seven days I think that's a pretty good length of time they haven't visited my website in a week we make them real aughh in lastly you have some options for the actual cookie itself the domain whether it's HTTP only some other stuff so we're gonna set it should be only two true on that way it cannot be accessed by JavaScript we're gonna come back and probably set the domain in the path later but we're gonna come back to that but just note you have options available when you're creating this cookie now we're gonna actually see if we get a cookie back so this is the interesting and fun part so I'm going to open the inspector here and I'm gonna click Network and you can see the basically requests going out here so I'm gonna clear this you can see there's kind of a task that goes in the background that just constantly pain we're gonna ignore that so we're just gonna have to clear that I'm gonna run it real quick and then if you click on the right one it should have your login here you can see I got an access token back and we can see if we get a cookie back my case cool it worked I'm actually a little surprised that did work but I'm glad I did so I could see the response says dude here you can see the value that means I got to cook you back so it is working sometimes you have to mess with cores to get this working the other thing you need to make sure you do is to go in your settings and and settings is this cog over here where is it I think it's secre dentals there it is so request stock credentials by default this is set to omit make sure it says the word include and then retry the request and see if the requests here you have cookies you can also go to the headers and look at the response headers should see a response header that says set cookie like this if that worked then you were correctly sending cookies back but you will not get a cookie back if you are not doing this so make sure you're doing this part that's very important alright so assuming that worked for you we have successfully logged in the user and sent them a refresh token and an access token so now we're ready to start cleaning this up a little bit so what I mean by that is we are kind of just putting the creation of the tokens in lined here I want to abstract them into their own functions and treat these secrets in a better way I want to store them in environment variables this is a good place to put them because you actually don't want anyone else seeing your secret and you may want to use different secrets and development versus production so let's go ahead and do that I'm gonna create a new file here just called off TS where I'm gonna stick this stuff so I'm gonna say export kant's create access token and inside of this actually we don't need to make it a sync so we're gonna take a user as a parameter well auto import for us all the user that we're going to accept here is just our our entity over there so I'm port from dot slash entity slash user and so now here we're just going to say return and then I'm gonna copy this so now if we need to create the access token in other places we can and this is coming from JSON web token and then we're gonna do the same for this one so create refresh token takes a user and then we're gonna return this so now back over here and just say create refresh token and making me sad I'm not getting auto completion so I'm just going to reload my window if you hit command P and then or command shift P it'll automatically add the carrot for you if you say reload window that's how I'm running this command right here but what I'm going to do is we're going to call this function and we're gonna call the other function right here so refresh token passing our user create access token passed in our user so now we have a really nice easy function we can call whenever we need to create one of these tokens all right so now here I talked about how I didn't want to just store the secret here so what I'm gonna do is I'm gonna create a dot M file inside here I'm going to say I'm gonna put my caps lock on access token secret and then this and then just write some random characters and then my refresh token refresh alright so and then to read this environment file what I like to do is yarn add by the way it gets rid of any terminals you had open to when you refresh the window I was surprised and I went away I'm so I'm gonna install a package called dot F this goes ahead and we see our index file here import dot and slash config it's gonna read and those two variables and to make sure this all work you can say process dot m dot and then the name of our variable to make sure it worked all right so let's get some rid of some of these so now if I start my server oh you know what did I yeah I did so I accidentally installed the packages and the wrong I installed the packages in the root so I'm gonna get rid of that I did not mean to do that in my server folder that's where I want to install dot F all right now we'll restart this and see if it works Oh import sign and we never used it so yeah we're done with our JSON web token import inside of our user resolver now so we can delete that and cool so I can see my two secrets they're perfect so I'm gonna remove that because I don't actually want to console.log them because they're secrets for a reason and so now what I'm going to do my off file over here this will paste them [Music] so instead of putting just a string there I'm gonna put the environment variable as the secret now for typescript it gets mad this because it's possibly undefined I'm gonna just put an exclamation point to say I know it's defined in the cert that it's not going to be undefined so to make sure everything works make sure you actually pass your secrets in okay so there we go so now we have these stored environment variables and we have cleaned this up a little bit the next thing is now we're passing tokens back we kind of have authentication that we can do now for routes and what I mean by that is I can create a route and I can protect it now [Music] so we have hello let's create a function called by so let's say I only want users that are logged in to be able to access this query for whatever reason so to do this the easiest way is for us to check whether the access token is in the header and then validate if it's correct now to be able to repeat that logic easily we're going to stick in the function and we're gonna stick it in some middleware to make it easy so we're gonna say use middleware and this is from what's library yep type graph QL and so what I can pass here is basically a function that gets access to the variables in the context and it can check whether the user should be have access to this so you can see this is up type middleware we're gonna copy this because we're gonna need this to create our middleware function we can even create our function inside of here that way we get type definitions so this if we hover over it I think it should give us what this the values of each thing is I imagine this is a parent okay ID structure this so we have access to the context is the thing that we care about and then the second I believe is next yep so what next does is this returns the actual resolver goes to the next middle air so we can have as many middlewares as we want running before our resolver runs and so next is what tells you that you're done with the current middleware logic so you wanna make sure and have this at the very end of all your middlewares so what we want to do is access the context and we don't actually have specified what the context value is all right let's just create a new new file I think they'll be simplest and call off is off the middleware let me get rid of the word mill where I'm just gonna call this is off it's a little bit cleaner so I'm gonna copy this paste it here and it's off is what's going to be passed here okay so what this is going to be is a middleware and I want this from Ted graph QL this thing now exists mill where function will do and then we need to pass in what our context is in angle brackets so now if I do context rec a we get Auto completion now so we want to get access to the headers and the one we care about is authorization or authentication I forget actually whether people call it authorization or authentication it's called authorization that sounds nice so here we're gonna say authorization okay so this is the logic we're gonna check first so we expect the user to send a header called authorization of the format where it says bear in front a space and then the actual token looks like something like that so we're gonna put in a try-catch in case anything goes wrong we're going to say authorization dot split by space and the token should be the second value here so it's possibly undefined yep so if they did not pass an authorization throw new error not authenticated so if the user didn't pass in a header when they made this request then we know just to throw this error that they're not indicated next thing that we're in a try is parsing out a token so we're splitting by strings and getting the second value and that's going to be our token and then here we're gonna say validate autocomplete for me import from JSON web token it's enough oh it's verify not validate there you go so we're gonna call verify and what this what this returns is a payload so now if we hover over this we can see what we need to pass in the token itself and then our secret and then any other options we don't think there's any other options we want to pass in we're just going to pass in this token right here and then we're gonna pass in a secret so it's a secret we're gonna pass in is the M and it's going to be this one right here so the access token is what we expect and so I'm gonna console any kind of error that we get here and so if something went wrong for whatever reason we could not get the payload or for whatever reason the token could not be split or maybe it verified it and the token was bad all these things mean that the user did not give us a good token and they're not authenticated so weird you can just throw this error otherwise if it got passed this everything worked because verify throws a err if it is expired or invalid and then it's going to return either a string or object this is whatever the payload and when I say payload that's what this thing right here when we signed our token that's the payload but very passive as an object here and then the same secret that we use to sign our token we have to use to verify it here all right so the payload we can actually just store on the context and that's what I'm going to do so here I must say payload is the optional object which has the user ID so if the user is logged in this payload is there so here I'm gonna say context dot payload is equal to Caleb so I'm setting it here that way I can access it later yeah that's what I figured so this is of type string or object so I'm just gonna say this is of type any and pass it into the context here so now in my resolver I can say context payload and have access to the current user ID of the user so let's see this in action alright so we're gonna say bye and our by function and we're also gonna say and actually instead of I just say your user ID is and then pass the user ID of the user so we can get this by accessing the context [Music] and then side of here we're going to say payload and because we have is off checking things if we didn't get a payload then is off is gonna throw an error so it's not even to get here so we know we can just do payload dot user error user ID I mean and it should be there we can even do a CL of the payload to make sure that worked to okay so we did a lot of stuff there well let's see this in action test it out so context we don't need an is off okay so server restarted try it out alright so we have our access token available here it probably expired by now so first thing I'm going to do is we can add headers right here I haven't added any headers so I'm gonna just try doing by and calling it see what happens so cool we got not authenticated so now what I'm gonna do is I'm gonna say authorization and then I'm gonna say bear space right and I can put some garbage value and ran again get not authenticated let's go ahead and login user and copy this token and see what we get all right so we have authorization and let me pull us up make sure you guys can see this so authorization space or colon we do bear space and then actual value so this is just a standard way of usually passing in your token so we'll follow that standard and let's run this and cool so it saw that we have a valid token passed in and give us a ID of one back now if we just like mess with this token a little bit you know got rid of ID you can run this you can see it authenticated this is invalid token that we passed in and so there you that is how we can now authenticate different queries or mutations so to recap what we did and we can see what the errors are here Jadey malformed if you want to and you can do different things depending on what the happened with the variable or the token so maybe the token expired maybe it's invalid maybe it's malformed maybe it has the wrong secret so you can do different things depending on that but to recap what we did is now we have this is off function which we can add to any query or any mutation it's gonna run before our resolver and what it does is it's going to read the header and verify that the the header itself and the token is correct and if it is correct it's going to set the payload inside the token to the context that way we can actually access it inside of our resolver here and so now we have a very easy way where we can put this all over our project and we can access the tokens value inside our resolver so there you go that is how I like to authenticate different routes or resolvers in graph QL now we're going to handle the case where we make a request and our token has expired since their access token only lasts for 15 minutes we need a way to pass a refresh token in and get a new access token so that's all we're gonna build now and we're actually not gonna do it using graph QL this will make more sense later but basically we only want our access to a refresh token to be sent for this particular request and so for our cookie only to be sent on a single route or request we need to give it a specific path so we're going to do is create a special route and express that handles refreshing so we're gonna come over here and create an app dot post and I'm gonna say slash refresh underscore token and so this particular route is specifically specifically designed to handle refreshing the JWT token and so I don't want to go to slash graph QL that's our normal route we go to when doing this and so what I can do is I can say our cookie only works on this route and that that that helps with security purposes where our token only gets sent when we are refreshing so that's why I'm not doing with graph QL I want to make a special route for it so that's why we're gonna be doing it this way and so we have this app dot post and basically what we need to do is we need to read the Refresh cookie and that's what we're gonna do first that's we're going to start with so we're gonna do that and we need to validate that that token is correct and then we can send them back a new access token so to start off with I'm just gonna say request dot cookies and well not dot cookies about header I mean and so what req dot headers does is we can just print the headers that are sent to this post route and the reason why I'm going to do it this way is I just want to make sure we have everything set up first correctly because not a test if this route is working we're no longer going to be using graft well playground like we have been using I'm gonna be using postman so you can use whatever you want to test this out but you need to have some kind of a tool to send a post request I'm gonna use something called postman so if you want to install this you can it's spelled like this if you want to just use curl or whatever you have as a tool go ahead and do that but what I'm going to do is make sure I can actually send a cookie over here so I have this saved and I can open up my server that's running and just make sure that it's being sent over here so the first thing I'm gonna do we're gonna make a new request here it's going to be a post request and we're in stimulus to localhost 4000 / refresh token and I'm gonna add a cookie a domain is localhost we're going to add a cookie so my cookie name here is going to be jid and the value is going to be just a random string or something like that say so this is just to demonstrate us sending a token and now let's go ahead and hit Send now if I come over here I can see the cookie was sent perfect and I can see the value of it so that looks like the cookies being sent correctly we're gonna cancel the request cuz actually forgot to end the response all right cool so now that we have that working I want to just install now a library that will parse this cookie and put it into an object and so that's gonna be called cookie parser I'm going to say yarn add cookie parser and we're going to solve the types for it so now we're an import cookie parser and yeah I didn't think there was a default I think it's just default import so this is Express middleware and what we can do is we can just say app use cooking parser and you want your middleware to run before any of your routes so I'm going to put it all the way up here alright so I have this so now if I do wreck I believe cookies I think this is the correct variable now I believe this is going to parse the cookie string and put into this so now let's do yarn start running again make sure that works all right server server's up we're gonna go ahead and send our request and now nice we see a nice object broken out between the variable name and actual value so now let's get into it with the actual logic of this so this is going to be Const Koken is req cookies dot JIT so that's just whatever I called it right and so here I'm going to say if we didn't get a token we're just going to return and here we're going to say response dot send and here we're gonna say okay is false and access token is just an empty string so we just don't send them back and access token so now assuming we got a token back I want to validate that the token is actually something we created so I'm going to say it counts and we can try catch this [Music] try catch and we can console.log any air we get and if we get an air we're gonna go ahead and return a false response and so inside of here it's going to be the payload and I'm gonna create the payload up here so here we're gonna verify from JSON web token the token passing in our process and I called it refresh token secret so we're just making sure that this secret was used to sign this token and token hasn't expired all right so I'm just gonna say this payload is of type and so if we get to this point in the code we know that the token is valid and we can send back and access token so what I'm going to do is in the payload here I have access to payload user ID and so I'm going to use that user ID to get the current user so I'm gonna make this an async function that way I can say user and then I'm going to say dot find one and then we're gonna say ID is using this ID and then we're gonna wait and if for whatever reason we can't find a user we can return this back though we should get a user from this um if it made it to this point and so then we can just say okay it's true and sent back a new access token so we're going to call our create access token function passing in our user and so there you go you can add extra logic to this refresh if you like but this is a bare minimum and it will work so let's recap what we did so first off we read this cookie which should be our refresh token we make sure we actually get a token else we threw an error well not throughout we're just returning in there then here we are making sure that the token has not expired and it's valid if there's some air with it we return false then we use the payload and if we go back to our off function we stored a user ID in the payload and we use that to fetch a user in our database if we find the user we create a new access token for them otherwise we just return out if we didn't so now let's test this make sure it works so server's up and running all right so now let's go ahead and run this we can see okay's false access tokens empty makes sense we didn't send a good token now I thought this would be kind of fun let's try sending an access token right so let's copy this and let's send this so we're gonna go into our cookie paste this so this should not work because it is using the wrong secret so if I send this we consent it says okay is false and if I go to my server logs we can actually see what the air is it can sit it says invalid signature all right so that's just it was signed with the wrong secret that JWT so now the last thing I want to make sure that this does work is I'm gonna just go to the network tab over here clear this and don't try logging in I'm gonna click on that response and actually copy the response cookie so I'm actually going to go over to the header I can see this set cookie JIT is equal to and I'm gonna copy the value of this token so you can see it goes to two lines but this is the thing that we want to copy and then I'm gonna paste it over here make sure it works so paste this in cool now I'll save that so now we're gonna send this cookie up now hopefully will happen is we get a new access token back so we'll send and cool so it worked so it used that Refresh token that we got when we logged in and it gave us back a new access token and as long as our refresh token is valid we can keep running this and get new access tokens now another thing that we could add here if we wanted to is whenever they refresh their access token we can also refresh the Refresh token because the Refresh token could expire and say seven days so let's add that logic here as well so we can just copy what we did in our user resolver over here and create a refresh token lynx-o so this just Rick creates a new refresh token and since the back is an HTTP only cookie and so the purpose of this is because we said that the refresh token expires in seven days if we ever refresh the token should also give a new refresh token so this means that the user could be State login for longer than seven days if they continually use the website and we can also split this off into a separate function so send refresh token export cannot send refresh token because we're now using it in two places so whatever options I pass in here I want to work in both places so all I need to do this is a response from Express [Music] and then a token so now I'm gonna copy this paste it here and pass my token in here so now I have this logic encapsulated so if I ever want to change the name of the cookie or change any options it updates in all the places so now I can just say send refresh token and sadly it did not auto import and we can pass in res and this and we can manually import this and so now I can call this and my resolver over here awesome so now I have that in both places we're good and we have our refresh token working so now whenever our access token expires we can call this endpoint and we can send our Refresh token and it'll send us back a new access token now we're gonna set up a system where we can revoke these refresh tokens so the idea is if the user maybe forgets their password or maybe their account gets hacked we want to revoke all the sessions that user has and there's a couple ways we can do this we can set up like a blacklist or a whitelist of the tokens that we've used but there's this method that I quite like that's very simple or basically we keep the version of a token and we can increment this version that will invalidate all the old tokens and so that's what we're gonna implement so how it works is we're gonna go to our user so I'm going to command click this user here we're gonna add a new field on here so this field let's call it token version and this is a number it's an integer and if we do comma and then an object here we can pass in extra options so I'm gonna say default and default it to zero so now what's gonna happen is whenever we create a refresh for a refresh token we're gonna pass what the current token version is so let's go to our off file over here and we're gonna just pass in an our refresh token here the token version alright so now we're gonna pass this version so let's let's just follow the chain of logic here so it starts at zero so we're gonna save this zero inside of this token then what's gonna happen is when we actually refresh the token which we're doing in the index over here we're gonna check if the version matches the version saved in the user so assuming we found a user we're gonna add one last check here so we're going to say if user dot token version is not equal the version that's in the payload so payload token version then we know that the token is invalid so now all that we have to do to invalidate the tokens for our particular user is we change the token version so usually we're gonna increment this version it's the way I'm going to do it here so we're gonna go to our user resolver over here and we're just going to create a new function or new mutation that we're gonna allow well see this is not really something we normally expose to other people to be able to revoke the tokens for somebody but in this particular case this will be simplest for us for just testing purposes so don't actually make a mutation like this but instead create a function that you can call for example and I forget password or that you can internally use this owns account gets hacked so this mutation can just return a bull in and we're just gonna say revoke tokens for user and specifically this revokes the refresh tokens so let's be specific revoke oops go free refresh tokens or user and we'll just take a single argument which is the user ID so user ID and this should be a number so we have to explicitly say that this is an integer and we import that from type graph QL all right so this user ID to update this we basically just want to increment the version the token version so here and type will type arm the way we can do this is we have to get the repository this is one way you can do it so we can say get connection dot git repository for the user and then there's an increment function that we can call and so we pass in how we find it so by the ID we pass in what the field we want to increment in this case we call it token version and then we say by how much we want to increment just one and all right so we have a weight here so we need to do a sync and we're gonna return true so now what's gonna happen is let's say I create a bunch of refresh tokens well you wouldn't create a bunch of but let's say the user were to come in and login so let's say I've logged in as Bob so oh my servers down let's run it so basically going to log in as Bob here we're gonna come to the network and see what the refresh token is cool so we're back up login as Bob we get our access token and I'm gonna look for the login request and grab the cookie for it so I'm gonna get to set header and copy this now if I want to just see what this looks like I can go to JWT IO and here they allow you to paste your jout and you can see what the payload is so I'm going to paste this in just to show you guys what's in my payload right here so I can see that it has a token version of zero so I can go ahead and we can go to postman over here you can pass in our cookie get a save and we can request new access tokens and as long as a refresh token is valid we can do this as many times as we want all right so now what we want to do is we want to revoke this refresh token so we can come back over here and we're not going to actually revoke this specific token but we're gonna revoke all refresh tokens that this user has so if we come to our users over here we can see my BOB user has an ID of one so we can say mutation revoke refresh tokens for a user one and there's nothing we need here and we're gonna run this so it says true so now what should happen is when we try to refresh our token it's going to come and see that the token version inside of the JWT is zero but we just increment it to one on our user so now when I come over here and try to refresh with this refresh token it's gonna say sorry you can't refresh with that token anymore so this is a simple way that I like to use to just wipe out all the sessions for a particular user now note as long as that user has an access token they can still do things so what this will do is if you revoke sessions for a user it's gonna be at most 15 minutes the user can still access the API and this is based off of our is off an art is off or just off the amount of time that you pick here so this is where the amount of time you pick for your access token could matter so if I revoke all the sessions for a user or all the Refresh tokens they can still access the token with their access token for 15 minutes or so okay so that's that we saw getting revoked now you'll notice when we log in the new Refresh tokens that we're creating are with an increment token version so we can grab another one and I can grab this Refresh token and I can paste it here and so now you can see this Refresh token has a token version of one and so that's how it work and so this also you can keep track of how many times has a user's account needed to forget their password or - they got their hack that you need to revoke all the the Refresh tokens so there you go that is how you can revoke Refresh tokens so we're pretty much done with the backend so now we're going to move into setting this up on the front end and how we can actually authenticate and react and refresh tokens and all that fun stuff so we're gonna head back over here and setup the react project and we're going to use create react app to do that so I wonder I went ahead and already ran this because it needs to install a few things but what you're gonna run is MPX create react app then whatever you want to call it I called mine web and then we're gonna do the - - typescript flag so it installs with typescript so when you do this you should get a new folder with all the react stuff inside of it so I'm just gonna CD into this Web folder and the first thing that I want to do is set up Apollo and be able to make a request to our server so I have the server running and a separate terminal tab and I'm just going to keep that running so there's a few files we can kill I don't need app dot CSS have dot test or index that CSS or the logo to SVG you know what let's kill the serviceworker too so the things that I'm leaving here is just the index and here we can kill these two imports so we just have this left and in our app dot TSX you can clear the return out here just say hello and remove these two imports so we're just gonna simply this a little bit and start from that and let's go ahead and just run the project and make sure it's working so I'm gonna say yarn start and then we're start adding some stuff to it okay I'm not gonna worry about this warning this just has different type script versions also gonna kill the readme just don't want that in my project alright so from here we are going to start by adding Apollo it says hello here so it looks like it was working so to add Apollo inside of our web folder or our react project we're gonna add three packages Apollo boost Apollo react hooks and graph QL so we're gonna add all three of these dependencies and then we also need to install the types for graph QL Apollo already comes with them so we don't need to install it for that library and then when this is complete what we're going to do is create a [Music] Apolo client so we're gonna say import paolo client from Palo boost and it looks like my yarn might have failed but I think it still installs it so I'm not gonna worry about that error I've seen that before so we're gonna say yarn add Deb dependency the graph QL types alright if I hover over this we can see if typescript is picking stuff up another thing that you can do is if you ever see typescript on just loading or sitting and looking like it's not working is if we do command shift P open up our menu you can type typescript restart server and run this restart TS server command and that usually fixes stuff that sometimes fixes things when auto imports aren't working and BS code too so cool now I see it it looks like it's working better now so we're gonna create our client which is equal to an Apollo client and here we're just going to pass in the URL to our server which is that hup localhost 4000 / graphic UL I'm gonna close this next we just need to wrap our entire application in an Apollo provider provider [Music] and this is coming from the hoof library at least I believe Hookes comes with it comes with the pol provider perfect and now we're going to pass this Apollo client that we created here and to our pala provider so now in our project we can use the Apollo hooks library and make requests to our server so in our app over here we're going to say use query and we're gonna make our first query to our server so I'm gonna say query and by the way this is how we only I just pass it like this I haven't actually used use query directly in a while and we'll see why in a second when we add graphic you'll code generator but here I say gql in front of it so this is how we're gonna actually make graph fuel requests to our server so here we can say you see I said gql which ought imported from graph QL tag which really we didn't install graph fuel tag it's really coming from Apollo boost so you can also import it like that so inside here we're gonna actually write our graphical query that we want to run so usually what I like to do is go to the graph QL playground and copy the query from here because they get auto completion and it's syntax highlighting it's easier to write so let's do that so I'm just gonna write a query called hello this is just our simplest one to make sure it's working let me see hi here perfect so I'm gonna copy this paste in here and then data loading so I'm gonna say if loading return loading otherwise I'm just going to turn data into a string and display that so we can see what data is and let's come over to a react app module can not be found oh also my server it's over here I've actually never seen this before I'm just gonna try restarting the server and see if it fixes itself otherwise we may need to add like tortillas config something maybe it could be causing the air but what I expect to happen is when we okay yeah it looks like I just needed to restart the server there so we should expect I said I was expecting possibly an error but it looks like it worked just fine so that's good um we haven't set up cores in our server so we're gonna have to do that at some point it's working now so we're gonna wait till we actually hit an actual error before we do it but cool we have Apollo set up now we're able to request this from our server the next step is we're gonna set up graphical code generator to do so we're going to go ahead and install the command line for it so to do that we're going to come to our web package here and I'm going to say yarn add and we're going to do as a dev depends eat graph QL cogent slash CLI and after this is finished running what we're gonna do is we're gonna initiate it and initialize our project they have a little CLI that will set up our project with a config and basically we're gonna get a little config over here and that's where we can for example create a new folder here called graph QL inside of it we can put all our queries so for example I can create our hello query and we can write it like so I'm just gonna leave this import up here like so and then what it's going to do is it's going to read this graph you'll query and it's going to create a component for us that we can use well in this case a hook that we can use alright so that was finished so now we can say MPX graph QL code Jen initialize so here this is where we're gonna fill out a little questionnaire so I'm gonna keep this selected press ENTER where is your schema so ours is at HTTP / / localhost 4000 / graphical and here it's asking where our operations / fragments are this is actually you know we can do in this way I've been I've been wrote written dot graph QL files in awhile let's do that actually so we can write this as a dot graph QL file like that I think so I'm gonna say all mine are in the graph QL folder here so I'm gonna say source slash crack ul slash star so I'm saying I'm where to look for all your queries and mutations in this case I'm gonna put them in this directory source graph QL and then look for all the files that are star graph QL pick plugins react Apollo I actually don't want this one I actually want the hooks so we're gonna check that off actually maybe we need this I don't know if we need to need this room I'm gonna keep it for now and maybe we'll remove it weird turn by the way I was hitting spacebar to toggle that on and off where to write the output I like to call mine nup this is fine I think we keep the default you hit enter just to keep the default do you want during an introspection file no I keep the default for the name what script in your patch up JSON call this Jen so and then we'll hit enter so now clear that and what that should have done is we now have a cogent llamo file and in our package of JSON we should have a generate script we should also have these three dependencies and also the generator so now I'm going to say just run your arm to install those dependencies that added and then when they have installed what we can do is we can do run yarn gen and it's gonna generate this for us some and it looks like by default it may generate not hooks so we're gonna have to do add a setting for that so we're gonna say yarn gen plug-in oh it needs to the extension dot TSX so on line five here we're gonna add that just an X at the end will regenerate this now we can go into here and we can see what is actually available to us so we'll see that's the other thing you see how it says unnamed underscore one underscore query basically we got a bunch of typescript things whenever you write your queries now you're gonna want to write a name for them like this and give them a name so I'm gonna just usually I just called what the name of this is but you can give them different names if you have queries that use in multiple places so I'm gonna call this one just hello and now we're gonna generate this again and now perfect now we're actually gonna get some actual stuff here and now you can see we get some components so if you want to use Apollo components or higher-order components this is how you do it we're gonna use hooks so we're going to and you can see it's red here we need to change that but this basically generates typescript types for us based on the graph QL and so this saves us work and automates some things notice at the end result is this gets a little simpler alright so let's go ahead and change our code Jen over here so that it also accepts hooks so at the very end here we're gonna add a config line and then underneath it we can add what things we want to change so for example I want to say with hoc false with components false and with hooks true so I'm turning off that I don't want it to generate components or higher-order components for me and that I just want hooks so we'll give that a save and then we'll regenerate this and now we can come look at this Oh looks like it's still generate the components maybe this is with component yep that looks like it fixed it so now you can notice we are just importing from react hooks at the top here and now we can see a single hook that it creates for us it should be called used query use hello query hook yep so now we have this function that we can use so how do we actually use this now well if we go to our app TSX over here instead of writing it like this we can say use hello query nothing changes here now but now if I say data and data can possibly be undefined so we can say if loading or not data we're gonna say dot dot dot loading otherwise I'm going to say dot and now I can see I need some type information I can see that this property has the word hello on it and it's returning a string and so that's what graphical coder gives us is we're going to know what the types of these are so that's really nice and we don't need to import that there anymore so cool we can see hello hi at the top of our application over here still and this is gonna be our new workflow now we're gonna write a query like this hello then we're gonna generate the types for it and then in our component we're gonna come over here and we can use that query there so cool we have graphical code generator all set up now next we want to create some pages like a register page and a login page so to create different pages we are going to be using react router to do our routing so let's go ahead and install that package so we're gonna say yarn add react router Dom and then we also need to install it types for it because this does not come with types oops and then when that's done in our app TSX I guess is where we will put all our routes so I want to rename this file to routes and our index file over here we need to change oops strong my sound so routes and this should be routes and now this should be routes so just changing the name here because I want to put all the routes in this particular thing so it's very clear and we're gonna just install the types for react router Dom here so yarn add dash D at types react router DOM and we'll let that run and now what we can do is we're gonna get rid of this use hello query we don't need it and kind of just clear out this this file and can rename that to routes and I do prefer using named exports like this so I'm going to do that and that means we're gonna have to switch in the index again so we'll do that at second so now we're gonna be importing from react router Dom get the browser router and we're gonna do a switch and then we're gonna have our routes so route and we're gonna say not to but path and then we're gonna render hi so just to verify everything is working we're gonna just say switch route and we'd do a single index trout here that just says hi and then we're gonna say I'm exact here so it matches exactly the slash and then our index over here let's just update this to do a named import like that so excellent let's just make sure our server hasn't crashed nice so now if I come over here did I just say hi like that yes do you okay good so to make sure I'm putting too many high so I wasn't sure if that was coming from graph QL or is coming from this just ones verify nice so we have this let's go ahead and now create the routes I talked about so for example go to create a new folder if you want to called pages and side of here you can create a register so RH we're gonna create a new component here on register I've sure this a few times but be good show if you haven't seen it how I just did this was with a snippet so if you go to code preferences user snippets you can create your own by typing typescript react and I'll link this in the description below if you want to copy my snippet but this is the snippet that I use for our H this just creates a new react component for so I'm gonna be using this a bit so if you want to follow along you can create this for yourself as well or something similar to it so it's import react and then I do an empty interface props and it looks like this alright so let's continue on so we have a register here and we're going to say register page and I might create another one called login and then we're gonna have home so one of the mistakes that I've done and previous kind of projects like this is not having an index page so we're gonna just create a little home page that links to all of our pages so this is our home page and in our routes here let's create these three routes so now we're gonna say oops I want to kill two here we're gonna say component and pass in the home component here and then we're gonna have a slash register slash blog in alright so now we have our three routes for us here alright we specify our paths and then our components where the path what we should be rendering and then we have our imports up here alright so we can close this let's come over here to our home page and create a few blanks so we're gonna say link [Music] and we're gonna stay register and then we're gonna stay login now we can just navigate to our pages there and maybe this is good to actually have as just navigation that we have everywhere so in that case I'm gonna copy this go back to our routes and the way you can add just like navigation to everything is I'm going to put on every page as you can do something like this so remember a div here that just wraps everything and then we're gonna have a header here and then I'm gonna paste in the header links and I just did command period while having my cursor here and that's how I was able to import all all of those things so we're importing link from react router Dom and then I think that was the only thing that auto imported so now in our home over here I could just say home page and we don't really need anything else alright so let's see what all that work got us make sure to save servers up running good so now I can click over to register click over login we can navigate our different pages nice could also make a thing for home if we want so we did that a lap pretty fast so let's just recap what we did so we created three different pages and we also created basically a header component that we are rendering on all the pages and we just have in our header component three links and when we click on the link and navigates between the pages and so we have this routes using react router so that's cool now why don't we go into our register and actually register some users um so just want to clean up close the couple tabs there so here we are going to basically just create a form to start off with I think is going to be the best thing and you're gonna use a form library but we're gonna have such a simple form that we're just going to use regular state so I'm going to say email set email and staying for a password and then we're gonna have a form element wrapping everything we're gonna have a div inside of here and have input and the value is going to be email placeholder email and then when this changes we're gonna say II set email is equal to e target dot value all right so this is how we're gonna do our input fields when we type it's gonna update the state in our email state they're copy this do the same thing for our password alright so I just replace password there and set password for on change and then we can have a submit button or we can call it register and we're gonna make this button of the type submit so what that will do is now in the user types enter or click that button it's going to submit the form so on submit here why to fall it refreshes the page so we're gonna say e dot prevent default and then here we're gonna say form submitted this email and this password also we can set the input field here now we're not gonna do that I'm gonna say we can do of a type email but that doesn't really matter that much I'm just going to say type password that's the more important one because it's gonna hide the password now all right so let's see this guy now all right so I got my console log here I can now type some stuff type some stuff register and now we can see the values submitted here that I use for both so cool that is just a basic react form that we built with just regular state to submit our form now when I submit my form I actually want to make a request to our server so that request is a graph QL request so we're going to create a register graph QL file inside our graph kill folder and here is where we're going to write our register mutation so that we're gonna write in our playground can copy this if we want now we're not gonna copy it because we need to add some variables first so I'm going to name this register and this is going to take an email which is a string and a password which is strength so you'll notice I'm putting a dollar sign in front of this this is how you write variables in graph QL so you put that in front and then you specify what the data type is so in this case is strength and then you can pass it in by doing the following email password and we're going to copy this paste it over here and the reason why we are doing it like so is now we can pass in arbitrary emails and passwords so like I said earlier our now process is going to be we created or we added a mutation I'm now gonna run Yarn generate inside or yarn gen inside the web folder that's gonna create a hook for us so now and you can click on graph QL and look inside of it and see what the hook is if you want to and then enter register we're gonna say Const use register mutation so we can call this register so here you put brackets and then the name of whatever you want the function to be called I'm calling mine register and then we can say register and we can pass in what our variable should be on this case our email and the password and then we can get a response on make this function asynchronous response is equal to a weight register and then we can console.log be response and you know let's go ahead and keep the form submitted just in case alright so now let's try creating a user this way so react app over here so I'm going to register a user Bob at Bob to calm any let's create it you can see register is true that means our user got created and I think it'd be nice if we cleared the register form maybe when we did this or maybe afterwards we take them to the home page or something like that so let's take it to the home page after they submit their form and before we actually do that let's just verify that the register did work so if I come back to our playground our users tab we can run this and see if new users got created it did perfect we can also add this logic to our home page to see new users - I think that would be good to do so let's do those two things real quick all right so we're not going to take any props really for our register here so I'm gonna get rid of it to a page but we are gonna say route component prompts so this is a react router thing or react route or Dom thing really and this gives us access well we have access already to all D for example history and it'll you can see if you put an object here and then in control spacing and see what you have access to now thanks the typescript but the tell typescript what you have access to this is how you do it this is the props that are passed in because we made it a route so you see how we made register a route that's this is us making it or out here so what that's gonna give us is this history prop it's gonna pass down to it and the history prop allows us to say history about push and then we can go back to that page so now I create a new user and we register it's now going to take us to the home page nice so now on my home page that would be nice to just show who would the users have signed up so we're gonna say users graph QL and this one I kind of just haven't memorized so we're gonna just say query users ID oops and email and we're gonna generate that and can go use users query you can see it right there and that's what we're gonna use on our home page use users query now if you want to pass any options to this you can pass in an object here the one I'm gonna pass is going to be fetch policy network only this just means that it is not gonna read from the cache is going to make a request to our server every time and that's what I want to happen and this is we don't worry about updating the cache so I'm gonna say data and I'm just gonna say if not data we know we're loading otherwise I'm gonna say users and pass this as a div and we're gonna have a unordered list that we're in just display all of our users so I'm gonna say data docked users dot map and here we're gonna say X dot email and then we can have I don't know a comma and a space and let's display their ID as well and then whenever we're you're mapping through an array and react we need to make sure we pass in a key so we would pass in the ID of the current user as so this is a unique value that's a good idea for a key so let's look at our users now so I can see I have Bob one Bob two and we have this random dude here so now if I register a new user we come back to the home page and we can see our user available to us there so now we can come just keep track of the users we've created so far nice so now we have a register page we can see all our users the next step is to actually take one of these users and login with it we're gonna head back over to vyas code and our login and start off so we're gonna copy our register stuff because the form is gonna be basically the same so I'm just get the entire component here and paste it in and I'm gonna command a dot or command period on here and that's it allow me to add all missing imports and I'm gonna rename this to login so now instead of use register mutation we want to use login mutation so I'm gonna create a new file in our graph QL folder called login graph QL and we're gonna come to our playground and do a similar thing here so login email and I want to just copy this paste that in because we're gonna use the same two variables email and the password here [Music] now I'm gonna copy that paste it in here so now we have our login mutation we're gonna generate the hook for it alright so it should be in here now and I like to also just click on the graph QL file whenever i generate the types because these code caches the type so it doesn't always update unless i click on the file and it does and so that also helped me get auto completion so now when i type over here use log and mutation it's gonna be available for us and i'm going to rename this to log in and this should be login alright so we'll give that a save and now let's run this guy just wanna make sure our server is up and good it is so now let's come over to our project and i'm gonna copy this guy cuz i remember the password and we retire login so I'm gonna say a login login well I thought here on the register page let's rename our button down here to login all right so I'm gonna log in and looks like it worked I can see my access token here perfect and it redirected me to the home page now the other thing that we want to get working here is we get have access to access token we want to make sure we're also getting the Refresh token working as well and my guess is it's not gonna work by default but we're gonna see so I'm gonna go into my cookies I have some stuff inside of here I think this could be old I'm not sure if the cookie is being automatically set or not so I'm just gonna clear this and we're gonna start over and make sure this is working so I'm again I have inspect open right-click inspect to open this application cookies and then localhost 3000 so let's login you can log in here looks like no cookie got set this is what I expected we need to change some things if we look in our console over here sorry our network tab we can click on graph QL we can filter it by it and look for a one that says post request and if we hit preview should be one that has the word login cool so what we're looking for in this request is a response headers and in here we should see it's a set cookie similar Tower you're seeing it when we were doing in the playground and we don't so why is that well there's a few things we need to do to get this working the first thing is we did not in our index so in our web over here when we create a Pollock lion set credentials to include so we're gonna do that so now when we actually send the login request huh this is actually taking a little bit to load shree fresh this is my login page no that's my home page oh there we go okay so this is what I was waiting for I was like I was expecting this err a really long time ago so now we're actually finally getting it so we have a problem with our cores so I wanted to teach you guys also how to read this error message because this is a very common one when you're doing web dev stuff so it says access to fetch alright so this is the server we're trying to access that's this first string so we're trying to access this server and we're trying to access it from locos 3,000 which we are and it says it's been blocked because the value is equal to star come and this is this is the main things you want to read is alright I'm requesting the server from here and then you want to see it says the value of its the header must not be a wild-card so you want to see what the value of it currently is alright so the current course value we're sending back is a star and it says we can't send back a star so we know we need to change the course value now and also it says this is occurs when we said it credentials to include so now what I like to do to actually fix this and change course is to go to our server so I'm going to close this stuff and I'm going to go back to our server and our index over here so by default Apollo will actually do cores for us but in my opinion it's a little bit easier to set up if we just ignore the cores that Apollo gives us so we can do that by where we call Paul the server to apply middleware setting cores to false and now we can add cores ourselves so we're gonna head back to our server so I'm a CD into the server folder and I'm gonna say yarn add course so we're gonna actually add cores ourselves and this is going to be some Express middleware that we're gonna add and we also need to install the type for it so yarn AB at D of course all right actually I actually don't know if we need the types or not looks like they do exist for some reason I just had like a glimpse in my memory that maybe I feel like I've installed Coors before and it had types but I can't remember all right so we're gonna import Coors like this and then we can say map dot use Coors and then there's a couple things we want to say first credentials true that way we can send back your cookie and then what our origin is so the origin is whatever we want to accept so the air we are getting is because the origin was set to star and so when we're trying to request this it said you cannot have star as the origin so what do we what should we set it if it should be star well it should be locos 3000 all right and again so let's look at this again let's say I mess this up and I write the wrong origin like I think this is the wrong origin that we have to put HTTP in this and not just this how can we know if we mess this up first off let's make sure our server has restart and all that good stuff a TAS and now I'm gonna refresh over here and now let's take a look about how our error has changed so now it says we're trying to access from this origin it says it's been blocked by cores it says the header value is equal to this right so our header value is locos 3000 when we're trying to request from this origin so they don't basically it's saying these two values don't match and this is going to be a very common so I've had this happen to me before and so all you have to do is take the origin that it tells you to right here and that's the origin you want to put on your server so I'm gonna copy this and then so that's basically why due to debug and fix the cores problems is so now I can set my origin to here and that's basically the right thing whatever our front-end react website is the URL for it that's what we want set as our origin all right so we're gonna save this and now if we refresh we should be able to actually request the users again so perfect now when I log in we should be getting our cookie back so this is the fun part where we're going to see if this all worked actually let me go copy my user all right so we have application so no cookie is set paste this in you also see the network tab we can clear it you can run this so I'm gonna click on this I can see the post request and this is where we get to do some fun debugging prop maybe let's see if the cookie showed up okay the cookie showed up we just don't see a header for it a reason sometimes chrome shows the header sometimes it doesn't I thought maybe it didn't work because I didn't show the header but you saw in the playground it would say like set-cookie header for whatever reason that's hiding it from me right here so I don't see in the response header but I do see the cookie got set because if I go to application cookies I see the JIT cookie got set and I can see the value here so our refresh token is in our browser we have access to the access token here so we have our two tokens available to us one is in a cookie one we're gonna use and set in a variable but one just recap real quick for those of you that had problems with the cookie what you need to do so first this is very important getting your course set up so you notice I said app dot use make sure you have this at the very beginning here or as early as you can it's very important to add the cores before you actually apply middle layer so make sure you apply middleware after this has been added also make sure your origin and it's this credential set to true and then back in our website make sure when you start or when you create the Apollo client they have credentials set to include so if you have all those things the cookie should be getting set and you can see it there ok so what I want to do next is we can log in and get an access token we want to use that access token and send it up in the header whenever we make requests so for example we made a request over here called by and this request requires you to be logged in to access and we had to send an authorization bear token up in there to get that to work so we want to do the same thing in a react out so we're gonna just copy this by and we're gonna put it inside of here so by doctor fql and so I just want to run this query and we're gonna just run this query and see if it works or not and if it works that means we're logged in if it doesn't work that means we're not logged in ok so we have this let's generate the types for it good so now let's create a new page which I'm gonna call the TSX we're going to use the buy query and we're gonna see if we get any errors so if air will console.log the air and return air otherwise we can just return it that it worked and actually I guess we can display the data also we need to know if it's loading so if loading we're going to return div bloating and then if there's an error we're gonna display that there's an error if for some reason there's not any data we're gonna say no data otherwise we can display date it up by all right so the whole purpose of this component is just to try to access some authenticated data so we're gonna create a new route for it called slash by and we'll create a new header as well all right so now we can link and actually go to this page so let's just try it out and see what happens so if we click on this we can see we an error you can see exactly what the error is if we open up our console probably yep so it says we are not authenticated all right so now we're gonna fix this we want to be able to log in and send the access token in the header so how do we do this well first step is to actually store the access token somewhere so I said we're just gonna store the access token and a JavaScript variable in this case typescript but we're just gonna create a file called access token TS and we're gonna export let access token it's an empty string so this is just gonna be a global variable that we can access the access token from so now when I login what I'm going to do is we get the response so after we log it we can just say access token well first we can just say if we got a response and response dot data if this just is checking to make sure we didn't get any errors from the login for some reason so this assumes it worked then if it worked we can say access token is equal to response dot data dot login dot access token and this is just going to be imported I'm gonna restart my typescript server so just again that's command shift P and then restart typescript server you can just type it up here and so now this should be able yep I can auto import this and because it's not a variable this is a string oh you know what it doesn't let me just set a variable like this I thought I could do this for some reason but I guess it doesn't like it I'm not sure if this is a typescript thing so what we're gonna do instead is we can create a function here called set access token and we can make a function called get access token so now from get access token we'll just return the value oops and then here we will set it so now in our login we can call set access token so it's still going to be a kind of a global variable we just have functions that wrap it now just set and access it okay and we don't need use register mutation up there so I'll remove that so now we have this stored in a variable the next thing is to actually send this in a header so to do this we're gonna come back to our index file over here and we're gonna say on each request we have access to the operation and what we can do is we can say operation dot set context and we can set the headers and the header we want to set is the authorization header so what we're gonna do is we're gonna say prompts access token it's equal to get access token and then if there is an access token we're gonna do bearer and then pass in our access token otherwise we can just pass an empty string for the authorization header we were just not logged in the other way we could do this is if we have an access token then we can actually set the authorization header so we can do it this way too so we only do this if we happen to have an access token and we're gonna handle the case where it's expired in a second but now when we log in and then make a graphic you'll request what's gonna happen is we're gonna read the access token and we're going to set the header and so this should be sent with the request so let's see this in action so I'm gonna just go to home copy this user we're gonna log in real quick alright so we are logged in now let's try coming to bye and nice it worked it says your user ID is 2 so we successfully logged in and sent our access token to the server now this is great but now when we refresh the page because we're storing the access token in just a variable it's gonna go away so if we refresh we can see now we get an error so what we're gonna do now is when the page first loads we're gonna try refreshing our token to get a new access token so the user stays logged in even when they refresh the page so to do that we're gonna head over and create a new component which I'm gonna call app TSX and app over here what he's gonna do is just render our routes so now in our index over here I'm going to render app instead of routes and really this guy is useless right now but what I want to add to him is the actual refresh so let's do that so by default I'm going to be loading so I'm going to say true and we're set we can have our set loading here so we're gonna say if loading returned a div loading so here we can set some kind of loading animation or in this case you could return just null or we could do a div whatever you want to do to indicate that your app's loading you can put it here and what we're going to do here is have a use effect and we're gonna do this just once when the application mounts and what we're gonna do is we're going to try to refresh our token and get a new access token so here I'm gonna say fetch and we're gonna send a request to localhost 4,000 slash refresh token and we need to say credential set to true that way we can receive a new cookie and why is it upset oh this needs to be set to include not true so we're gonna say fetch dot then and this is getting long so let me save it so you can't do a sync and a weight so I couldn't just await this fetch right here inside a use effect so what we're gonna do is stop then syntax so we're saying dot then and we can say X dot JSON dot then and so we're doing so this is how you get the information back from a fetch request as we say X JSON we want to read the JSON data this is going to return us another promise and actually let's clean this up a little bit instead let's make this asynchronous and then we can just wait it here I think there's a lot cleaner to look at and I'm just going to just console.log what data is giving us back and then after this we can say set loading to false so the idea is before app renders right so by default we're just going to display this then when it's displaying that we're going to try to refresh the token and then after it's done that we were just going to say false and then we load our entire application so let's see this in action it says not found did I call it something else I actually just forgot what I called the route so let's go to our server and index I call that slash refresh token slash refresh token and oh I just need to make this a get request we're sorry a post request so by default when you do fetch you do a get request by default haven't done REST API requests in a while but there we go let's give it in our try and now we can see what the top response is awesome so in this case it was able to get us a new access token and we can see okay is equal to true so perfect so now here I can say access token and we can say set access token is equal to this access token then I'm going to get rid of the console log there but if you want you can keep it so let's see what the end result is so now if i refresh it's gonna load and then it's going to display the application and we're gonna be logged in and we're gonna get a new access token all right so we can refresh a couple times see it in action and cool so now we are persisting the user between refreshes and again just to recap how we're doing that is before we render our application we are sending a request to our server and we are sending basically a refresh token to get a new access token and with this new access token we're then just setting it before we load our application now just to show you if we were to say delete our refresh token and we refresh we're gonna get an error here so perfect so now we're gonna handle the case where our access token has expired and we may not have refreshed the page but we're just kind of browsing the website it has expired and then we try making a request we don't want the user to be logged out so we'll see how we can handle that so the first thing that I want to do to just to show you how this happens is we're gonna go to our auth on our server and instead of having 15 minutes time for our token let's make it 15 seconds so I'm gonna save that close our server for now and I'm gonna head to our [Music] by function or by component here I'm just going to say network only for the fetch policy so what this means is every time we visit this page it's just going to make a new request to get the data so that'll help show what's going on here so let's login and now we see our ID is 2 now we come back to home if we come to the network tab we can clear this and see what happens now let's hope it's been 15 seconds it hasn't so we'll wait cool it now it's within 15 seconds so you notice I was just kind of clicking back and forth between the links until it's been in 15 seconds my token has expired I tried making a request and we got an error here so the user should never experience this it should just seamlessly refresh in the background so how are we gonna do that well we know when the token expires it's basically what we want to do is we want to check if the token has expired and if it has we want to get a new one before we do the request so to help us out with this we're gonna be using this library called Apollo link token refresh and to use this library we create a link and we need to pass this link with to apollo link dot from and to be able to do this we need to migrate off of apollo boost so we're using apollo boost over here to just create our apollo client and so we're no longer can use apollo boost because we need to have a special link so we're gonna follow this guide to migrate away from apollo boost i recommend coming to it because we're gonna be copying a big chunk of code and basically trimming some stuff so if you go to the after portion of this we are gonna copy this right here and copy this entire thing and i'll link this below in the description but you're just going to go to the boost migration advanced migration section and we're gonna paste this in I'm also gonna try to go through this slowly because there's a few things that we need to cut so let's start at the very top we're not gonna be using appalling State so we can remove that and we're no longer you're gonna need a Paolo client from Apollo boost the rest of this we can keep in all these things we're automatically installed for us when we install a power boost so I'm just going to keep them for now and not like individually install them okay so here we're creating an in-memory cache we don't really need to pass any setting stars so we're gonna do that this request function we already wrote our own so we can kill it this is the thing that we want to keep so this is the request link and it's going a new Apollo link we're gonna say candle is of the type any to get rid of a type error and then right here you can see this is where we're adding or can add we have access to the operation so if we scroll down to what we were doing before you'll notice with the operation we did this so we're gonna copy this and paste it up here alright so this this code right here is where we would get the access token and set the context that way we could send the access token in the header so we're gonna put that logic right smack here and then nothing else needs to change with this new Apollo link here so if you're typing this out this is what it looks like we're gonna keep this handle stuff that Apollo gave us we're not gonna make any changes really the only reasons we have this request link is because we want to set the context and we may be able to use the set context from Apollo to clean this up a bit but we got this from Apollo migration guide so I'm fine using just that too alright so now this is us creating the actual client on-air this is gonna learn some we get a graphical error for now I'm just going to print there we can kill this with client state and the new HTTP link we just need to change the URI to the one that we are using which is this little post one alright now we can delete our old client and this is our new client so we haven't added any additional logic this is just the equivalent non Apollo boost version of creating the client so again so here's the client we're creating a custom well we're not really creating custom link but we're creating a new link based off of catching errors this request link thing which is really just setting a header and then this HTTP link which is going to actually do the request for us and then we're gonna passion the cat we pass in the cache so on top of this this is where we're gonna add this library so the whole point of doing that is we can now add this new refresh link so if you want to copy this miss logic as well come to this github repo so I'm going to copy all of this and I'm going to paste it in here all right so let's start from the top first thing is let's actually add this library to our code I had not mean to copy all that okay so it is called Apollo link token refresh I'm going to copy that and this this library was written in typescript so we're gonna get types and don't need to do anything else for it I'm gonna copy this import statement and add it to top alright so the first function that we're gonna write here is her fill out is this one right here which is is token valid or undefined so the logic for this is going to be first to get our token so we're going to say get access token and then we're going to check if we don't have a token so if we don't have a token then we can return true the token is undefined next what we want to do is try reading the token and see if it is both a valid token it's like not malformed and to that it has not expired so we're gonna set a try-catch and we're going to decode the the token inside of this so if it has any kind of error we're gonna say false the token is invalid and and so after this inside of here we want to be able to decode this token and to do that we're gonna install a library called a JWT decode so JT - decode we're yarn at it and this we need installed the typescript types for and when that's done we're gonna import it from the top here [Music] and let's install it types for it yarn ad - D ad types / day of et decode and now what we can do is we can say Const expiration is equal to give T decode and then our token so here we get the payload of the token something that's automatically added to the payload for us is when the token expires and that's of the form exp so we can just get that by doing this next we want to just check if it's expired so we're gonna say if the current date is greater than the current expiration date of the token right and then we have multiply this times a thousand because I believe this is in microseconds or milliseconds I don't remember I just remember this calculation I did a while back and go to get these things to match and then we're gonna return false else we return true alright so the logic is if the if the current time is greater that means we've passed when the token has expired so now it is invalid so we return false the token is not not valid otherwise we know the token is still valid so we're returning true here sweet so here is the logic for checking whether our token is valid or invalid you can also if you want to check any kind of other check here you could this is really all that I think is necessary for now for that alright so the next thing that we're going to do is the fetch access token so this is actual fetch function to get the new access token so for us we already wrote that so we can just copy this from our app and then handle fetch this is going to actually read the access token from the response so to be able to read it we have to pass and what our field name is I called mine access token camel case like this so I'm going to pass in that so it's access token field and then whatever you called it and then here we have access to the access token all we really need to do is set the access token now to get Auto imported something for me yeah I don't want this there's nothing I need to do in the handle response but go ahead and read the comment here in case in your application you need it and then here we can handle any kind of error we're just gonna say your refresh token was invalid try relog again and you know it's constant log back to layer itself I don't have to get rid of that okay so keep this and then that's it I think we have it all set up let's give it a try now so again well let's see you'll see this in action then I'll explain exactly what this is actually doing for us I don't think I started my server so start that back up and so what we're gonna be looking for is in our network log here so you wanna keep the inspector open and keep the network vlog open we're gonna just clear here and we're gonna go to home and we're gonna kill our axe our refresh token and just restart from the beginning alright so I have no access token I have no refresh token and we have to refresh there we go I'm gonna copy this from the home so I can log in alright so now I have an access token I can access by now I'm gonna look at the network tab when it's been 15 seconds what I'm going to notice a network tab is we're gonna refresh when I try making a request so we're gonna clear this I think it's been about 15 seconds now I'm gonna click on by and you'll notice one of the request was to the refresh token route and we can see that it sends us back a token and we can see the users data is by now and we get that data back so you notice to the user they have no idea that this is happening and this is something that they just are seamlessly using the site now and we just do in the background whenever the token has expired we refresh a new one for them and so they can just go on using the site making requests and we handle the case where we need to make an extra request to get the Refresh token for them all right and you can see as I was going back and forth every 15 seconds it fetches a new token and so yeah so that is what our our link here is now doing is it checks if the token is valid or not if it's not valid it's going to call this function and get a new access token for us and then it's going to set that access token here and then that access token is actually used in the request itself and that's how we're able to just continue using the site with it so now that we got that working we're pretty much done with persisting the users session when they refresh they're gonna stay logged in and as they use the application they're gonna be kept in the same session and we're just refresh in the background so we can go back to setting our access token back to fifteen minutes now so I'm just gonna go back to the on file that we have and change 15 seconds to 15 minutes now I'm pretty much good with that now the only difference is gonna be that we check to refresh the token every 15 minutes now instead of 15 seconds the other thing I just wanted to mention is I didn't know if I really went over when this handle error function gets called in our token refresh link so this gets called whenever it tries to fetch an access token and this end point since back in error I'm in our particular access point the way I made it is we don't throw errors back we just send back an empty refresh token so if your application sends back an error this function will be called in this case this function is really not gonna ever be called unless the server's just like totally down or something but this doesn't send in air so just note that that's when this is called and depending on how your server responds this may be called or may not be called in this case it's totally fine for us not to do anything in this because what we're just never gonna see it called this the way we set it up all right the other thing I just want to mention real quick is this token refresh link logic gets called on every graphic you'll request to check whether the token is invalid so it only does something if it finds the token to be invalid though all right so that's that the next thing that I wanted to go over was how to actually fetch the user say I want to display who the current user is in the header or somewhere in the application itself so one way we could do that is by reading the token so we can just go to our access token over here and read the data inside of it assuming we have one now the way we set this up I don't particularly like it because we have this in a global variable so accessing this and react is kind of could run into problems because whenever the access token changes it doesn't cause a react application to refresh or rerender now if I wanted to actually go with this method and read the information from the access token I would recommend sticking this in some kind of state management library so you know when the token has changed and it causes react to re-render and you get the new data but I'm not gonna do it like that in this case instead I'm just going to request the data from the server so we're gonna make a Apollo query called me and we're gonna get the current user it that way so both ways work it just depends in your use case whether you want to read from a token or just get the data from your server because maybe you don't want to actually put this data inside of a token because note all the data inside a jvt is accessible it's public all right so with that said let's go ahead and add this so we're gonna start with creating a new query in our user resolver on the server so I like to call this query me and it's gonna return a user or null so to allow us to send back Noel's responses we can say comma and then an option you can say Noble is true so inside me right here I want to do something very similar to our is off middleware so I'm hitting command and then click to go view it so I'm gonna just copy some of this code here and paste it here so we need to access the context [Music] context is equal to my context so inside of me here we're gonna read the authorization header to see if the user sent us an access token if not we are gonna return null so we want to return nulls instead of returning and care and then we can verify from JSON web token I hit command and period to bring up that little menu to import this for me and we're gonna turn null here as well and if it makes it all the way down here we're gonna return null otherwise we're gonna return user dot find one and we're gonna say payload dot user ID so whenever we verify the token and get the payload inside of it the payload assuming it is you know a valid token we have stored in there the user ID and you can see it's giving me an error just say that the payload is of type any here and so we're gonna use that user ID inside the token to fetch the user so this is where we can get all the fields that we want from the user and return it here I guess we actually never get to this point so we can just remove this null ok so again to recap what this me query is doing is we read the token from the header if there is no token at all we just return null there's no currently logged in user otherwise we parse the token make sure it's valid and we use the user ID inside the token to get the user and we return that user here oops I do not want a new version docker actually remind me later maybe I do okay so we can now make this request from our front-end so I'm going to create a new graph QL query called me graph QL and go back to a graph QL playground to write this out I'd say me and then we get our email and ID I think in you may have more fields to add to this then we do so you can fetch as many as you want from the user we have it pretty simple right now and we're going to generate the types for this and then we're pretty much done now we can use this query wherever the heck we want it so let's say we want to get this in the header so I'm gonna create just a new function to make this real simple or I could just really I could do it up here now let's just make a new component so I'm gonna make a component called header TSX and I'm gonna copy my header guy and we just need to import link from react router DOM and now we're gonna render our header in our routes so now inside of here we can just call our new query [Music] and I'm gonna make this just network only to make my life easy right now so it's just always gonna request from the server but feel free to deal with updating the cache and all that fun stuff and Apollo if you want to so we're gonna say data and loading or I'm not even gonna worry about loading for this for the case that we're going to do so all I'm gonna do now at the bottom here is data otherwise we're just gonna do return actually non empty string all right so if we get data and we get a user all right cuz this isn't can sometimes be null then we can display a div that says you are logged and as data dot me dot you know all right so now in the header we are loading the current user and just display it so let's check out our application so currently I can see I am logged in as Bob at Bob to comm so perfect and if I want to here I guess we don't really have a logout function we should add that I was gonna say is let's see what this looks like if we're not logged in and maybe instead of null go back to our header and say not logged in and ok so this is actually kind of a funny funny thing is we actually want to we don't want to show them this message not logged in if this happens to just be loading so we actually do you need to know if this is loading so we're gonna say let body is equal to null so this is usually what I like to do if there's like three states and we're gonna set this to type any as I say if we're loading body is equal to you know also data and a dot me body is equal to this did I copy that else body is equal to this and then down here I just display body and I'm just playing null for loading you could also do something else for loading if you want do here but this could also you could extend this if you have more States this is usually what I do if I want to display multiple different states for a particular like one single space so sweet so I'm gonna go to my application get rid of my refresh token and just refresh the page so we can see we're not logged in now and now when we log in we should set me query so we're gonna go to a pages login and here we just want to make a change where we update the cache after the user logs in because right now we're not doing that and take a look what's gonna happen so we try logging in and it logs in just fine but this header does not update so we just need to let Apollo know that we actually have a user now so the way we can do that is in our login right here we're gonna say update and we're gonna have access to the store and then what the response is but the thing is here we're actually not returning a user from login so I actually want to do that so I can get that information and update the current user so let's go to our server real quick and just send back the current user so this is in user resolvers and at the very top we have our login response so all we're gonna add is we also now return a user and this is a type that we need to explicitly say what the data type of it is for graph QL so that's why I'm doing this all right so now in our login down here we're just going to also include the current user so what that allows us to do is in our graph QL you can say user ID email and now we're going to have access to that right here so we can say data and we need to regenerate the types because we created we made some changes to it and I just want to see what kind of type definition is we're gonna get for this I think it says data could possibly be null so if it is going our turn null and data dot logon dot user so I'd like to update the cache and set the current user equal to this so I'm going to say store dot right query and so my query is going to be the nee document and my data is equal to this now something you want to make sure you do when you update the Apollo cache like this is that all the same fields that you're getting when you login the user you're also fetching in the meet so for me I have ID and email and login I have ID an email so they match so let's see if I set this all up correctly so we're gonna kill the refresh token refresh and now try logging in and to grab our Bob at Bob calm and go to our console up looks like I'm just missing a field and me so I want to show you guys this so it's very easy to mess up what you write down for your data so I did not format it correctly for this query so because of that we get this error in our console missing field me and this now the easiest way to figure out what the heck you're doing wrong is to actually add type definitions for this so here you can actually pass in me query and the actual type for this and then I can do an object and just get straight auto-completion so it expects possibly a type name like that and the me value we know is actually a user so it should be like this I don't think I want to just tell you guys to if you control space it's gonna actually autocomplete query for you for the type name here this is also optional so we probably don't need it but now we can see this is the structure that it was expecting and we can see we're no longer getting an error because its checking the structure of this against what this type is here in the me query and this was something that's Auto imported from us from the generated graph tool types up here alright so we have our me document that were passing in this is now the correct data so let's try this one more time clear a cookie refresh login and now you can see as we login it now displays the current user so perfect that's exactly what I wanted and now anywhere that we actually want to display the user we just use this hook let's use me query hook and we have access to the user so feel free to use this all of your application to get the current user and I just want to mention if you are gonna place to use me query in your application that I'd recommend just looking into how the fetch policy works because you probably don't want to use Network only everywhere because this will not utilize the cache but what you can get Apollo to do is cache the result of the me query so you can use it all over your application and then it only sends one request to the server so that's pretty nice and so we can just remove the fetch policy to get that behavior by default Network policy or network only I like to set if I'm testing and then when I'm actually ready to start doing stuff and updating the cache with Apollo I'll do it like this all right so one other thing that I wanted to do that I didn't mention being of this but I thought that'd be helpful to fit in is how to actually log the user out so I kind of have been manually doing that by actually going in and killing the refresh token in the cookie and so basically when we until a refresh token then the user can't lock in anymore or can't do anything we also need to clear the access token as well now we're gonna actually do this where we can create a button the user can click on it's gonna actually log them out so let's go ahead and implement that so to start off what we're gonna do is just create an endpoint on our server to clear this cookie because this is an HTTP only cookie we can't access this through our website or in react we're gonna have to on our server remove it so what I'm gonna do is I'm going to create a new user resolver and we're gonna create a mutation and this mutation is just going to be called logout doesn't need any arguments we are gonna need to know the context though and the type is going to be my context and we're fine to just return a boolean from this and all we need to do is get the response and similar to how when we login user in setup here down here at the end we send a refresh token and this is the token we send we want to send a refresh token that is empty and that will log the user out so I'm gonna say send refresh token send the response and then just an empty string and that will log the user out we could also do res clear cookie which will send back an empty cookie and it will expire it right away that's another option I like just using our send refresh token function because then I make sure I'm creating the cookie with the same name and the same attributes and all that matches up so cool so now that I have this mutation I can call this from my react application and it will clear the refresh token out for us so let's go ahead and use this so I'm going to go into graph QL and create a logout graph QL and I'm gonna say mutation logout and all we're gonna do is call logout and there's nothing else you need to add to this because we're not selecting any fields or anything and I'm just going to generate the types for this and I'm gonna just I turned off my server so I'm gonna restart it or actually JK I kept it on and yet my servers back on - so perfect so both my servers are on I generated the types we can now utilize this logout button and then go see what it does so I'm gonna click on graph QL about TSX to load it in and go to our routes so actually I guess we have our header component now we're gonna go into our header component and we're gonna add a new button here button logout all right so we want to log out the user when they click on this so what we're going to do is up here rest a log out is going to be a user logout mutation and I'm gonna make this asynchronous so we're just gonna call log out and that'll go ahead and clear a refresh token but the other thing that I want to do is actually clear our access token as well so I'm going to say set access token is equal to a empty string or actually want to set null so if I click on this I'm gonna allow us to pass in a string or actually you know what we're doing an empty string for default we don't have to pass a null we'll just do this it'll be the same effect we just want to have something that is no token then that's what that value is so we clear the refresh token we clear the access token whenever you're using Apollo it's also a good idea to reset the store whenever you log the user out so right here the second parameter of the mutation here we can actually get access to the Apollo client and then down here I can say a wait client dot reset so what clients sometimes undefined yep I'm just going to assume that it's defined and you can assume some things defined in typescript by put an exclamation point immerse a dot reset store all right so let's start running this now so what should happen is we should kill the Refresh token should kill access token and we should clear the cache so everything should be reset after this so I'm just gonna refresh the page here we have our logged out button here can see I'm still logged in as my Bob at Bob calm so I'm gonna press logout and we can see I'm no longer logged in I can see the value of my refresh token is empty and now if I try going to by you can see we're not logged in so nice and if we want to we can conditionally show this logout button and only show it if you're logged in so we know they're logged in if we if it's not loading and we have a current user all right so we're gonna say not loading and data and data dot me so if all those conditions are true where you're going to display our button here and we can do a ternary so it is if it's true we're going to display this otherwise we're going to display no and then we won't see our logged out button right here but now if I log back in don't have Bob on my clipboard right now let's copy that you can see we're logged in and we have this option to log out so awesome so now we can log the user out whenever we want to or these are themselves can press this button and log themselves out now one last thing that I'd like to do is just set the path of our refresh token now the reason why I want to do that is right now every request we send we're actually sending our refresh token with it so for example if I go to the by route and I click on the graph QL requests in the network I can click on headers and see what the request header is and I'll just not show cookies I thought I was gonna show me cookies here I guess maybe it doesn't show the cookie 4 in Chrome for some reason so what I was gonna show is that the cookie was sent on every request with the header but Chrome is not showing it to me so there's no way to see it maybe if I open this in Firefox we can see it not now [Music] so now logon as this user and we're at the network tab I'm going to clear and now I'm going to go to our buyer out and we can look at our post request and this is what I want to show you guys so you can let's let's lift this up and let's zoom in a little bit just let me zoom into the panel this but if you go to the request headers you can actually see that we are sending a cookie here's our jid cookie and what we'd like to do is we only want to send the Refresh token up whenever the user goes to refresh their token so we can do that by modifying the path on our cookie so I'm gonna go to our send refresh token and just say that our path is slash Refresh underscore token so now what this will do is now when I try to send a request and I should clear my cookie so I go to storage let's clear all these not as familiar with the Firefox inspector she's gonna backspace and kill all of those cookies so refresh it's gone let's login alright so I see my refresh token here and you can see that it's on the path refresh underscore token now so now if I go to the network tab and I clear this and now I go to by I click on my request I can see that there is a cookie or at least there we actually don't want to send any cookies right now and I don't see my cookie in the request headers at all so that looks like a good it didn't work with the path and now if I were to say refresh the page all right we should have sent a request to the refresh token and we can see that our cookie is being sent in the Quest's header now so what that path is doing is it's now restricting and we're only seeing the Refresh token for when we want to actually refresh it so this is just a good practice to start doing so cool we are done with everything that I wanted to go through in this tutorial for those of you that made it to the end I hope you liked it and you got some value out of it if you did I really appreciate it if you give this video a thumbs up and share it with someone who wants to learn or needs to learn about JWT authentication
Info
Channel: Ben Awad
Views: 182,275
Rating: 4.9658651 out of 5
Keywords: jwt, jwt authentication, JWT Authentication Node.js, JWT Authentication Node.js Tutorial, graphql, react, jwt react, jwt graphql, graphql jwt
Id: 25GS0MLT8JU
Channel Id: undefined
Length: 184min 8sec (11048 seconds)
Published: Thu Sep 19 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.