Next.js jwt authentication protected routes httpOnly cookie with App Directory

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
right so today we're going to be implementing authentication with nextges we're going to be using Json web token and we're going to place that token inside of a cookie and send it to our browser now we're going to do it the proper way without actually sending the token through the Json response and then placing it inside the local storage we're going to do it the actual proper way now I've already made this video and it was using nextges12.something it use the Pages directory now next has updated and it uses the app directory and this is an updated version of it so let's get straight into it I have this form here that has two inputs input 1 and 2 it's for the username and password and a button and also the form it when I submit the form it will take the username and the password and we will continue from there now you can follow along I just created an empty next.js project and type this in we will have to we will do this on the client side because well this entire authentication depends on it because you cannot actually get the cookie if you're doing server side the cookies inside the browser so we need to use so this needs to be client-side you have to import the use client at the top and that tells you tells the browser tells next exactly as I explained right now that this will be on the client side now before we actually start you also have to install some dependencies and that's the cookie axios and Json web token so you're going to close this you're going to say npm install axios I'm just going to wait for that to install I'm just going to do it so you can follow along install cookie and npm install Json web token now I'm using typescript so whoever is using typescript you might need to install these Dev dependencies here the types for cookie and the Json web token and now we can run our server again npm run Dev and now we can continue now first off we have to create an API on our server that will actually check if the user is can log in and if the user can we have to create the token and create the cookie and then return it to our browser so let's create the API part so let's say API now I'm just going to create the API and explain it so we're going to say API auth slash login and we're going to say route.ds now this route.ts is a reserved name which means you cannot name it for example user it will not work the API needs to be named route and inside of this API we also have to have a reserve named of get post delete and so on you can read the next chess documentation so the route names as the page here have to be reserved the page is page.tsx and that's it and the route also route.ts and that's it now for our API points here we have to log it log the user in and the path will be API slash auth login we have to get the username and the password that are passed so we're gonna take the body from the request so this is how you get the body you await the request and you call the Json function and let's extract the username so let's extract the username and the password from the body and let's say that we want to authenticate our user and only a user with the username admin and the password can log in so let's say if the username is not admin or the username is not admin or the password is not admin then let's just return a response that will say you're on authorized right so we're going to say next response and we're going to say let's say message on authorized I spelled this correctly I think I did unauthorized and let's give it a status of 401 and we have to say Json here okay now next response.json message is unauthorized and the status is 401. now this is if the user entered anything else other than admin admin because we want to fake the database you probably will have a database connection here and you'll check if the user actually exists now the next step is actually checking the environment variables I have these two environment variables here jvt secret and the node environment and I'll show you why the second step we have to do is get the environment variables and take the jvt secret and I'm going to say or an empty string now you have always have to check this so always check this you have to have a set environment variable and never use this or your jvt secret or anything else that's high security right always use a strong password here so you get the secret and now we have to sign the token right so we're going to say the token is equal to sign and we're going to import this from not from crypto but from Json web token and what we have to do here is pass the username because I want the username to be saved and the next thing that we have to do is pass the secret and this is secret that we're going to use and the final thing is we have to pass the expiration so I'm gonna say expires n and let's give this a Max H we're going to say Max h and let's say 60 times 60 times 24 times 30. I think this is equal to 30 days pretty sure now we give the max age here and this is how long the token will be valid now once we have our token we have to actually send create the cookie and send this so we're going to say serialize and we have to call the serialize function from cookie okay so we're going to import serialize from cookie and I'm just going to paste this in the cookie is going to be our site jvt it's going to Pat it's gonna take this token that we just created and these are some options that we have here so I'm going to say max age is equal to Max H from the top again this is the same thing the cookies actual max age when it expires and now since we have the token and we have the cookie we can actually send a response here so we're going to say response is equal to message we're going to say authenticated and let's return the response we're going to say return new response and let's stringify this object we'll say response here and it should be a status of 200 and this is the part for the cookie so we need to set set the headers we're going to say set cookie so this is you need to spell it exactly like this and we have to give it this serialized value here so that it actually sets it now this is the entire route we have to test this out now so we have to call this route and see if it works now we can go back to our page.tsx and let's just write a try catch here and we have to write the request here and we have to import axios I'm going to say axios you can also use fetch fetch is really good now and next is extending fetch but I personally like to use axios and it's it's fine for most use cases cases it's very fine so we're gonna call this API route so API auth login the exact one that we made we're gonna pass the payload we're going to pass the username and we're going to pass the password and if the request is good let's just log this out so I'm going to say data and I'm going to say alert json.stringify data and let's redirect the user to slash dashboard for example but if it fails let's take the error and say e dot e s axios error I think this is yeah this needs to be imported and let's just say error Dot message okay so if something fails we're just gonna show the error of course you can set loading States errors and you can update whatever you want in your exact use case now let's let's try this out if we go to the network tab let's type in admin here and let's type one two three as the password of course this will not work because we need to have admin and admin in both the username and the password Fields so if we submit this it should say request failed with status code 401 that's good because it's not the correct username in the password now when we type in admin admin let's say submit we get the authenticated so it works nice we're now authenticated and once now we can go to the application here go to cookies and we can go to localhost 3000 and we can see our cookie here so our cookie contains the token so it's the name it's the same name that we set here our site jvt and it has an expiration date and so on and so forth now we have the cookie and we are authenticated and now with each request this will be sent in the request and that's all we need to actually get authenticated and let's go back to the network Tab and what we should do here is import router so that we can redirect the user when he is authenticated so let's go back to our page get the router we have to import the router we import it from next navigation we don't use router Router is not you I think it can be used but we're gonna stay away from the applications we're going to import it from the navigation one and let's just push the user the user navigate him to I think let's say router.push let's say slash dashboard and we can actually just destructure the push and take the push here okay so this basically means that we don't have to type in router dot something we can just take the push function object destruction you should check this out if you don't know now we're gonna move the user to a separate page here and of course this page should should show only if you are authenticated now let's first make the page and then we can worry about those other problems so let's go to our app directory let's say dashboard and let's say page.dsx and then this page you can just say export default function let's say dashboard page and let's just return a div it says H1 super secret dashboard and let's let's log in again I'm going to say admin admin submit authenticated nice and there you go we're at the dashboard page now we have to make sure that we are at the dashboard page right maybe we're not actually authenticated because I can go back to the login screen I can go back to the dashboard and see everything is fine even if I have the cookie or if I remove the cookie and reload the page so we have to make sure that everything is fine here now we want to protect these routes I suggest making a layout here we're going to say layout.dsx and this layout it complains because we have to export and create the actual layout now this layout should send the request and check if we are authenticated if we are then it's okay but if we are not then it's going to redirect us to the page the default one that we were on just the regular home now this layout should protect all of the pages under the dashboard because we have nested layouts now in nexjs so let's just go ahead with implementing this and we can come with those other examples so we're going to say export default function let's say dashboards layouts it's going to take children and I'm gonna say children.react.react node so this just means that we can pass children to it and let's let's say like this so we should return something so we're going to say Main and let's pass children here okay so we have our layout now so let's say we go back to dashboard and we can add anything we want here so we can say header navigation okay now we have the navigation here okay so what we have to do is actually check if the user is authenticated and let's make a separate route for it and let's go for off and let's call it let's call it me and call to Route there so we're going to say Rod dot TS without uh about this okay now in this route it's fairly straightforward it's a get request and we just have to check if the user is this actually contained that token inside the cookie so what we what we're gonna do here is use the cookie store this is a very convenient way that texture has provided us so we can get the cookies and let's just cancel log this let's see that token but cookie store and we're gonna go from there now inside of this layout we actually have to send the request and see what's happening so I'm gonna call a use effect here and inside of this use effect I'm going to create an async function and call it I like to call the function like this so I don't have to write a separate one and let's just say that we can make a function here at the bottom that says async function get the user okay and let's create a try catch so in here we will write the actual API request so we can say data and we're going to wait axials yet let's import axios okay and what's the API endpoint it's slash API slash auth slash me okay and if everything is fine we're just going to return the user as data and the error as null I like to return data like this so it if everything passes you have the user and the error if there is null everything is fine now I'm gonna remove these errors don't worry we're gonna type this out too so let's say if an error happens I'm gonna cast this to an axios error and let's import this and we're gonna just return the user null and the error should be err okay and we can remove this because it's redundant there you go now we can call this get user function right here so we're going to say cons user and the error and we're going to get the user and let's check if an error happened well obviously we're not authenticate it so we have to do something about it so we can redirect our user the someone that wants to to see the top secret dashboard we have we want to move him somewhere else so we can check if an error happens let's just push it to the home page and if the error did not happen well let's see what to do so if the error did not happen if everything is all right now we have to add types here so I just I'm gonna add this interface here this is for you typescript users this basically means that we expect an object that's a string and an axious error so I'm going to say that this get user here expects a promise and of a of the user response I have to add a weight here because it's a promise okay now we will use we'll do something with the user here but first off let's let's check where we are now when we go to our dashboard and we don't have the cookie as you can see here we're getting redirected back now if you can you can see that we can all we can see the dashboard even though we're not authenticated it's we can see it for a couple of seconds that's why you can just do basic react stuff and you can create a state so we can say use state and inside inside of here we could say is success for example and set is Success you could say it's a it's false at the beginning and it's a Boolean type and of course at the end we can say set is success to true and we can hide everything so if it's not a success we can just say loading I forgot the return statement okay so we can go back to dashboard and it says loading and we're back okay it says loading and we're back so no one can see anything now there is one thing here that we have to do and well that's actually implement this part so we have to actually validate and verify that jvt right so we have to take the token and I'm gonna open the console here and we have to take the token out of the cookie store we have to check if it exists right so I'm going to say Tolkien is equal to cookie store dot get let's say our site jvt now I what I do recommend here is for both of these routes we have the rsight jvt string now this is hard coded and it's not really good to use so I would suggest that we make a constant directory and inside of it make it an index.ds file and let's say const cookie name let's say our site jvt and let's use this cookie name instead of okay name you have to export this constant I keep forgetting these small things and let's say cookie name okay and now we can replace this RSI jvt here too so we can say cookie name and now you don't have to worry about hard-coded strings because you know there can be typos and there can be big problems because of these typos now we can also move this max age here so we can go to the constants and we can say export cons but I'm not going to bore you with that in this video that's easy whole separate video about how you should manage your variables in organizing your code now we have to take this token and let's log this token out okay let's reload the page let's go back to dashboard okay it's sent to request and the token is undefined it cannot see the header because well it's pretty obvious we don't have it inside of our cookies so we're going to say we're going to log in right say authenticate it and now we can see our site jvt right and we have to take the value from it so we're going to say token dot value or you can just use object restructuring so we're going to say value okay and now we have to actually verify this so I'm gonna do this with the token I'm going to say I'm going to say if token doesn't exist well we're not authenticated so we can return some response I can say return new response actually let's not write the code there should be a response here right yeah you can copy this response and let's import this and there you go now that's if the token is missing but if the token exists we have to write a try and catch again and let's just try to verify this so I'm going to call verify Json web token I'm gonna pass the token value I'm going to say const value is equal to token there was an extra curly bracket here and we can get the value from the token and now we have to verify this so we're gonna say the value of the token and let's get the secret and again we can get the secret on this here okay and let's pass the secret and if everything works out you can you can get the username if you need and you probably will need it because we place the username when we sign the token in but for this example right now I don't need it so I'm just going to return a response so let's take for example this response and let's say response copy this code here and let's say it's our user they use it's yeah actually let's say it's user and we can say super top secret use okay we return the response and if something fails again we're not sure but it may be the validation fail the token expired whatever whatever can happen let's say something went wrong and let's give it a 400 or whatever is convenient and appropriate for the cash here and now let's check this now if I go to the dashboard I can see the dashboard if I remove this token and I reload I'm redirected back if I get this token again and I'm authenticated nice and let's just break this token so it's it's some gibberish it's not it's not even the legit token if I reload it's going to redirect me back because this is not good this is not okay someone messed with it now if you want to remove these tokens for example if you want to log the user out which you can do is you have to set the end set the same thing but with the max age at -1 which means it will expire instantly so let me just show you so if you set max age minus one and I try to log in again I'm going to say admin and I submit authenticated you see the cookie is instantly removed because the minus one is just expired instantly it's in milliseconds or seconds I think so if you want to implement the logout route and if you want to stop someone you can just return the serialized the response here you can set the set cookies create the cookie and just set the max stage to -1 that's how you handle logging out and that should pretty much cover everything that's been in the last video that's now deprecated and now you know how to implement your own Authentication with xjs
Info
Channel: Tenacity Dev
Views: 885
Rating: undefined out of 5
Keywords: Next.js, nextjs, nextjs auth, Next.js auth, Next.js Authentication, nextjs jwt, nextjs http only cookie, nextjs app directory auth, nextjs 13 app directory auth
Id: IUbNmsk9diY
Channel Id: undefined
Length: 25min 29sec (1529 seconds)
Published: Tue Jun 13 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.