Next.js Authentication Tutorial using React Context API and Appwrite

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
authentication is complicated so is the context API in react for that matter let's talk about the fundamentals of adding authentication into an xjs project and let's see if Chad gbt can help us write some of the code what's up everyone my name is James Q Quick and I do weekly videos on web development related topics I spent a lot of time with react and one of my favorite Frameworks which is next.js but things always get more complicated in any framework when you start to add authentication so since I've been working on incorporating authentication into a demo that I'll show you in a few minutes that you'll definitely want to check out I figured this would be a good opportunity to show you how to incorporate authentication into nexjs using the context API and a backend as a service platform which is apprite apprite is actually the sponsor of this video and we'll get to see more about them in the Hands-On portion in short though apprite is a back end as a service that takes care of all of your needs for your database for real-time updates and specifically authentication which is what we're going to be leveraging in this video in the meantime let's go ahead and dive into some of the code that we're going to start with so I've got a relatively basic next.js project and I set it up with Tailwind CSS actually when you create a new project in xjs now they have a config option to set it up with Tailwind which is really nice so I've got some basic styling in here and I've basically got two pages I've got an index page which is the home routes and then I've got a private page which we will be gatekeeping in a minute meaning if someone tries to come to this page and they're not logged in we will redirect them to a login page or something like that for example so we've got these two different pages and we've got this basic display up here just for demo purposes so we've got a nav bar up here to go from the home page which is public to the private page we want to incorporate authentication into this project now how are we going to do this we're going to use the context API so I've got a blank user.ts hook which is going to create a react hook and a context using the context API so we want to do a few things in here we want to have functions for the user to log in log out and sign up so we want to have those functions we also want to track the user across different pages so we want to track user status for example whether or not they are logged in we also want to track a loading State why while we are determining if the user is logged in and this is going to be an important distinction in this video there's lots of different ways to handle authentication I'm going to show you one which is doing all of the authentication on the client side in next.js you have the ability to do server-side authentication as well there's benefits to that in this case we're specifically doing authentication on the front end there are other ways to do it but this is how we're going to do it in this video and then the last thing we want to do is be able to leverage these things to be able to conditionally allow users to go to certain pages or gate keep pages and then conditionally show and hide things so for example inside of the nav bar we want to let's just add a comment in here conditionally hi the private page link if the user is not logged in notice the GitHub copilot is helping me with some intellisense there and there's also one additional piece to this that we don't want to miss even if we hide the link to this page we want to make sure if someone types this URL directly into their browser we still prevent them to get to from getting to that page so we'll cover all of that Hands-On as we create our context so before we get started I wanted to share with you a giveaway for this video so I created this project jqq memes which uses apprite Cloud Nary nexjs and is hosted on versa so it does a lot of the same stuff that we're going to talk about in this video and what you can do is actually create a meme with a funny image of me so it pulls a random image of me and you can say I love JavaScript for this one because it's happy and I create this meme you can download this so it'll open it up where you can right click and download Etc and so apprite has agreed to give away five t-shirts to the most entertaining memes that people create so you can create a meme and then you can uh you can tweet this so you could come to Twitter and use the hashtag it includes the hashtag jqq memes you can do that on Twitter or if you generate the meme and then click on Twitter and then want to get this URL out of the Tweet you can copy and paste that into the comments below so we'll give about about four or five days for people to submit their memes leave them in the comments below or post on Twitter with the hashtag jqq memes we'll choose five of those and send out t-shirts for app right to the winners so let's talk really quickly about why we're going to use the context API and react in relation to authentication in this case so in our application we want to have basically a global piece of state that keeps track of the things that we talked about earlier a loading State and whether or not the user is logged in and the actual user themselves so in react there's a pretty consistent problem that people come across which is prop Drilling and they even reference this in the docs when you go to the context page inside of the docs with react docs and they are pretty amazing this is like the new react docs which you should totally check out but inside of here they specifically reference the word prop Drilling and this is the idea of from a parent you need to send a prop down to a component to a nested component to another nested component so you're drilling kind of that prop all the way down the chain in our case we really want every component and Page any component that we write to have access to the user and that loading state so in this case we want to have kind of like a high level store that we can access and reference that data inside of our different components in that case in react we can use the context API to do just that where we can share that state globally or to a specific subsection of components basically any nested child can access this date in our case we're going to have this globally available so it's why we're going to use the context API in this case let's head over to chatgbt and see if it can help create some boilerplate code to get us started all right so I've got to open a new tab with chat gbt you can find this at chat.openai.com you can do all this stuff for free so you can follow along and do exactly what I'm doing so in this case what I want to do is ask chat gbt to generate uh a hook for us where we can access the different pieces of data that we've talked about so far that uses the context API so let's go ahead and ask chatgpt to do this can you generate react code that creates a user hook that uses the context API and has and exposes the following properties the logged in user and a loading Boolean all right so let's go ahead and ask that and see what we get so here's the example and then we can kind of walk through this so this is where there's kind of some boilerplate code in here that I think is relatively annoying to set up so let's actually look at what we have as it's generated in this code so to create a context in react we call the create contacts function so this is going to create this user context but then to be able to have this stuff be available inside of our application we have to create a provider so this is this user provider and notice it uses use state in here to keep track of the two things that we want to keep track of the user and the set loading state so in this in this case on use effect it's going to try to load the user as soon as the page loads so it's going to make a in this case an arbitrary request to an API User it's going to get that response it's going to update the user and then the loading property now in this case it then it creates or uses that provider to pass in a value of user and loading so it's an object that has two properties which is user and loading now as you wrap your application with this contacts provider that means that these values are going to be accessible inside of any nested component we'll talk about this more in a second the way we access that is by creating this use user hooks this is this last part where we export this hook which uses the context of user contacts now to then reference that we again wrap our application and use provider user provider and then inside of any different page that we want to access the user and the loading State we can use the use user hook that we created so that's the basics of how this works now the other thing I want to have though is can you can you also add three functions that can be referenced in the use user hook for login logout and sign up so this should go back and just kind of give us an updated version of the code for those different things so you see we have the same provider stuff we have the same fetch user which we're going to have to update but then it stubs out a login and then a log out function as well as sign up as well so it should all be the same then it should add those properties to the value here that exposes those properties for us and the rest of our application so if you look inside of the value you see user you see loading and then now you see login logout and sign up which is pretty neat now it even is stubbing out some components for us to handle or to do login and sign up and log out so it even has like these components built for us as well now this actually stopped kind of in the Middle with a few lines to go so I had to do a continue in here for this to finish but here's one of the cool things is we can actually go ahead and reference the sign up log out and login functionality so I'm going to go ahead and copy this entire snippet and we'll just throw this inside of the index page for our application so let's go and just paste this in this is going to look a little ugly for a second and we need to add the little bit of extra code in here so let's go and finish this and finish like this that should be okay all right so we have sign up uh log out and log in and then we need to move these Imports to the top now this use user this is actually going to come from the file that we haven't added code to yet because we're going to update it which is why we're not doing this yet but this will come from dot dot slash and then we'll have hooks and then we'll have user that's where it's going to come from it should be throwing an area or an error because we're not actually using that yet I think that should be it but we'll come back to that in a second so we have our login we have inside of here we have basic use state for email and password and then we call that login function okay then we have our log out function so this is just a button and it calls log out from the hook again we can access this stuff anywhere and then we have our sign up which basically does the same as our login so that all looks pretty good now the only thing we want to do is update this to use the app right SDK so we haven't gotten into app right we'll go and set this up here in a second but let's say can you update the login well let's say can you update these functions to use the app right SDK for authentication now we haven't actually gone to apprite documentation or anything like that this is just kind of do going to do a lot of that stuff for us so you see here it's including the app right SDK so the first thing we would do is just go ahead and install app right so you run an install of app right and you'll have that available now inside of this use effect now it has the check user function which references the aphrite.account.get so this is using if we go to app right npm for example so the app right package on npm if we look for Authentication or account there we go so account this is where all the authentication stuff takes place so this is the thing that we're going to use to reference from apprite to handle login logout Etc all right so let's go back to this example code so we have the check user again it's doing the same concept of what we did before but now it's just checking to see if this user is logged in all right so then it's uh destructuring these properties and then setting them inside of the user great we want to check that that's great so we do this on the initial load of the application then we have our login function which calls create session with the email and password then we have logout which deletes the session sets the user null and then we have sign up which again basically does the equivalent of what we did before and then we have our functions that are exposed to us you through this use user hook so let's go ahead and copy this snippet because this looks good and let's take it into the user hook and let's just paste it in all right so uh this is importing app right from a local file so I actually created inside of here a utils with an app right file so what this does is go ahead and configure the app right SDK by creating a new client it's going to check for a variable that references the project ID that we need to go and create a or set up so we'll do that in a second then it exports this account thing so instead of referencing apprite.account let's do a global replace for that so let's uh just set this to account so I did on mine it's command H to do a global replace and then command enter is going to replace all those and let's see if we can get intellisense now to do this import so now we have the import for um our account from our utils file there so we can get rid of the original import I think this is just a typescript error so we could just label this as any to kind of move past this and my source code or maybe not let's see oh this needs to be uh children children any uh so in my code I actually use like real typescript so don't don't get mad at me for this let's see what's wrong with the ID here and this is another typescript error so we could say that this state is going to be null or an object that has ID email and name and each of these will have a type of string so let's just give the types in here again not the best typescript just kind of showing how this stuff would work so we have the use effects now we can add our typescript in here for email and password so those are going to be strings all right and now we get to some of the point where we need to double check some of the stuff that Chad gbt is doing because this is saying there is no create session and if we go back and get intellisense there is a great email session which does take an email and a password and then we're kind of confusing when we're referencing things in here so since we have an email property here but then destructure one here uh it kind of gets messed up so we can actually use the original email so that login stuff should be working log out looks like it's working okay we just called delete session and then we'll have inside of sign up we'll have three strings this is a string string and string for these three different properties and we'll go ahead and create that session now if you look in here we've got kind of a mess of red squigglies that's actually because I named this file originally user.ts instead of TSX which is what we need for a react component and the last problem we have in here is the typescript issue again we could have gone back to chat GPT and asked it to add typescript typings I'm actually going to paste in a snippet in here which will update the typescript typings in a way that will work so what this does is it defines an interface for the state of the user which includes the properties we've already talked about user loading log out login and sign up then on create context we tell it it's going to have the context of user State and we give it a default state in here and then we actually update that with the values that are defined down here so that should work well and then inside of our index TSX file now all of this code should be working so we import the login from the use user hook we import uh the log out and we import the sign up so let's go and add all of these to our home page so inside of our index again we wouldn't usually co-locate these but we'll just do it in this case because it's going to be a little easier to see so we'll add the login We'll add the log out and that should probably come after sign up so let's have each of these and then in between them let's have just a little bit of margin bottom so let's do a div with an MB margin bottom of 10. let's add one here and then let's add one after each of these all right so that should at least show these different components so let's go ahead and run this and this should actually fail because as we try to load this because we haven't actually included the apprite project ID so to be able to test all this stuff out we need to actually use uh apprite for this so we're going to go to cloud.apprite.io and inside of here this is their Cloud hosting for their backend as a service which is really really nice so let's create a new project in here and let's call this uh next JS auth and it's going to create a project ID for us that's the one thing we need because basically all the other stuff is going to be set up for us so let's go into settings and let's grab the project ID so in this case if we look inside of the aphrite utils file it's referencing an environment variable called next public app right project ID so let's create an environment variable Dot env.local and actually this should be at the root of our directory let's paste in that key of next public app right project ID and then paste in that project ID now this is a a public thing as you could probably guess and that's because the protection in this stuff really comes from authentication of accessing things in the database and that sort of stuff which we're not going to get to in this case all right so let's go ahead and try to run this now and we'll still actually have a failure and we'll explain why so if we come over to localhost 3000 we'll see that this is going to fail and that's because they can't destructure property login of blah blah as it's null so this actually comes down to the fact that we forgot to add the or reference the provider inside of the app TSX so basically wrapping this entire page inside of our provider so in this case we want to grab a reference to the user provider and we want to just wrap this entire thing with the user provider now what this means is everything inside of or nested inside of this user provider component which includes our entire application should have access to those properties so this looks really ugly and let's just kind of ignore that for now but let's maybe look inside of make sure we don't have any errors let's go to our console here and notice it actually shows an error which is 401 that's because the user is not logged in at this point and that's actually correct because remember we do a first check to see if the user is logged in on initial page load so for that to return a 401 means they're not logged in so that's actually correct now this looks worse than I thought so I've added some basic Styles now where we should at least be able to have a better view of the form so you can see this here all right so let's go ahead and give this a shot so I'll use my email here and then password will be I love JavaScript obviously and I think we're going to get an error on it saying uh invalid user ID so we actually want to call a different function in here so we want to call or actually the same function but the first parameter is the ID for the user so if we hover on create this as user ID so in this case we can tell it to generate a unique ID for us to go ahead and create that account so that uh that should work now and then we could call the login function and pass in the email and password now when we call the login function that will then set the user so then we'll have access to that user so we don't actually need to get the session here specifically we can just we could just say call account.create like we had so let's try this again let's type in James and our email and I love JavaScript go ahead and sign up I don't think we'll see anything inside of um inside of a log although we do get a warning here that it's using local storage for uh session management which is okay in this point so we don't have any resets on the form we don't have any navigation on the Forum or anything but let's see if we can now uh start to show and hide some content so what we're going to do is scroll back up to inside of our index page let's actually use the use user hook so if we get intellisense uh in here it's already got the Imports and from this we can destructure the loading property and the user property from our use user hook now what are we going to do in this case uh we're then maybe we could say like if loading and a loading piece of text obviously you make this a much better UI in the future and then we can say if there is the user if the user is logged in if there is a user we will show um we will show the log out and we should also say like this is not loading and uh we could also like short circuit this a little bit to say if uh loading then we want to return our uh loading piece up here so just kind of reorganizing this a little bit so we'll return that component then by the time we get down to these other pieces we can just check on the user so we know it's not loading meaning if there is a user we'll show the log out button and then if there is not a user then we will show we'll have to wrap these in empty brackets but then we should be able to move these around log in and sign up so hopefully now we should be able to tell that we're logged in because we only see the log out button uh also conditionally well let's actually show this so let's log out okay so that actually switches so we're able to track that and it kind of re-updates itself let's go ahead and log in again and and do our famous password I love JavaScript and login and hopefully that will go through the same process and now again the state gets updated for the user and then let's go and do the same thing inside of our nav bar so inside of our nav bar the beauty of this Hook is we can use this use user hook I'm going to get some autocomplete in there for the import so make sure you import that if you're following along but from use user I want to get the loading State and the user again and we can do almost the exact same thing to say like if not loading and user and then we'll take this down here and add our closing parentheses so now we'll see that like we can see this private page but if we log out this link goes away great we've done authentication our job is done but not really because what people can do is they can manually go and type in the slash private route and then they can get to the private page so what we want to do here is have basically an interception inside football reference inside of this private page to check first whether the user is logged in so if we go to uh private and we want to use our use user hook so we'll use use user we will import the same thing so loading and user and then uh basically uh on load so we want to use a use effect um and actually it may be after the use effect because we want to be able to redirect uh based on any changes to the variables uh loading and user so inside of here we'll say if we're not loading if we're not loading and we don't have a user then we want to send to the home page in this case you could you could send like an authenticated page unauthenticated page or login page or something like that but let's do I think we'll just use use router in this case and so from the router we will be able to navigate so we'll say router dot uh push and then we'll push the user back home so if either the loading State or the user State changes and you're on this page we're going to be able to check if it's not loading and the user is not logged in we don't want them to be here uh so we can do that I think this is looking for an extra dependency of the router fine and uh that should be good the other thing we probably want to do is something similar uh to what we had earlier so if it's loading we'll return another uh loading State GitHub copilot is just kind of writing this stuff for me which is all fine by me so on this page there's going to be a little bit of time potentially if you go to that page directly where it's trying to figure out if the user is logged in because that's an asynchronous process so we're going to just show that loading State and if they're not logged in we're going to bump them back to the home page so let's see what this looks like let's go to the home page notice we don't have that button to get to the private page so it's hidden on the navbar which is great but what if they do this and so we'll probably see is that loading State you saw that for just a second it figured out the user is not logged in and redirects them back now just to verify all of this works let's come back and type in I love JavaScript such a good password and that's all again and now our button should be here we should be able to navigate back and forth between the public and private page that stuff is working just as we expect so it's really important to know that it's not just enough to hide nav links for example you also then have to specifically gate that page to prevent people from manually typing in the route that they want to go to so I hope this was helpful this was kind of a fun way for me to learn about authentication with apprite specifically incorporate this into the context API because I needed this for that jqq memes project then I wanted to see how much chat gbt could do for us which actually did a lot we actually obviously had to correct some of the things but the majority of the code was kind of written for us which is really nice we also could have asked it more details to include typescript and all these things but it worked out really well I think so jqq memes.com submit your memes create a meme share the link in the comments below or just post the picture on Twitter with the hashtag jqq memes we will choose five winners of the coolest most entertaining memes and send out apparite t-shirts which are pretty sweet so make sure to do that let me know if you have any other questions throw those in the comments below hope you enjoyed the video and I'll catch you next time
Info
Channel: James Q Quick
Views: 8,635
Rating: undefined out of 5
Keywords: nextjs authentication, appwrite authentication, chatgpt react, how to use chatgpt, react context, react hooks, authentication hook in react, protecting pages in nextjs, web development, chatgpt next.js, react js, next auth, authentication
Id: ZJOmaZaANkQ
Channel Id: undefined
Length: 27min 15sec (1635 seconds)
Published: Tue Apr 18 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.