Next-Auth V5 Tutorial (OAuth, Email, Server Actions, Server-Side Auth, Client-Side Auth, Roles)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey everyone in this tutorial you will learn how to use next off V5 next off is the most popular authentication library for nextjs and version five is currently the latest version actually it's still in beta but I wouldn't use any older version to start a new project anymore because there have been a few changes a lot of them for the better and in this tutorial you will learn how to implement this the goal of this tutorial is to get you up and running with next off as quickly as possible and also make you able to implement it into your own project for this reason we will not build a huge fancy project with a ton of features in this tutorial instead I've prepared some starting code I will later show you how to download the starting code and then we will step by step add next off authentication to this starting code or instead of downloading my project you can also go ahead and add it to your own project right away if you already have a nextjs project that you want to add authentication to and we will cover quite a few topics in this tutorial we will Implement Google and GitHub login via o Google and GitHub are just examples once you know how this works you can add even more providers like Discord or Facebook login or whatever there are a ton of them we will also add login via email magic links so we will actually get sent an email to our email inbox and when we click it we will log into our app and this will actually work we will learn how to protect our pages and also to our server actions and API endpoints so that only authenticated users can access them we will also learn the difference between server side authentication and client side authentication which I think is often overlooked in other tutorials because those are two completely different approaches and they have important implications on caching so we will take a look at the difference between these two we will also learn how to add user roles so we will add an admin role that only one or two users have and depending on this admin role they can access pages that normal users can't and we will also learn how to update the user data later so if you want to change the username or change the role we will learn how to do this from within our app again we will not build a fancy project but if you want to build project tutorials then you can take a look at my other tutorials on this channel some of them also used next off as part of a bigger project this tutorial here is more focused and the only prerequisite for this tutorial is that you are already know how to use nextjs and the app router I have a tutorial on this as well I will put a link here in the top right corner of this video to this nextjs tutorial in case you haven't used nextjs yet then you have to watch this other tutorial first and then you can come back to this one okay one more thing before we start I have a free react best practices calls that you can get if you join my email newsletter and the email newsletter is something you should be subscribed to anyway because there I send tips round about every 2 weeks about react of course you can always unsubscribe if you want and you can get this free react best practices course under coding andf flow.com react bestest practices there is a sign in form for my newsletter when you will join you get sent this free email course and I'm also working on a newer bigger nextjs course and I will send updates about this course to my email list so it's worth being on this email list again go to coding andf flow.com SL react best practices and join and then have a lot of fun with this next off tutorial all right so let's start by setting up our project again I've prepared starting code that you can download and then we will add next off to the starting code in the video description below there will be a link to this repository called next off V5 clone this repository or download it as a zip file whatever you prefer and then open it in vs code I assume that you know how to get clone a repository if you don't then just Google it yeah and here's some starting code I have prepared there is a logo in here there are a few pages already but they contain these two Doos that we want to replace for the actual code later the first thing we have to do is install all the packages that are listed in the package.json because they are not pushed toward the GitHub repository by default we can in install them by opening the command line and running npmi which is short for npm install this will create the node modules folder up here which basically contains all the content of these different packages but you probably already know that so after this is done we could technically start our project but there is some code in here that won't compile yet until we added a bunch more code so you can't run it yet but yeah and here are a bunch of different to-dos that we want to replace for the actual code maybe let's also take a quick look at a different packages I have installed this project uses shety nuui for the UI components I use this in a lot of my newer projects it's just a beautiful component library that looks good out of the box I'm using this here but this is not so important for next off this doesn't play any role if you have a different project that you is different packages you can still use next off the same way next off also works with different database adapters here we will use the zel storage which is a post database we will set this up later and we use Prisma as the OM but next off has a ton of different database adapters so you don't have to use Prisma you can also use something like drizzle or a ton of other ones later in the documentation you will see which ones are available and how you can install them but this project uses Prisma and then I've just set up the bare minimum that's necessary the benefit of downloading the starting code is that you have the same version numbers as I have even if you watch this tutorial like in a year or in two years when you run npmi you install the exact same version numbers this makes sure that this tutorial will work even in the future and there won't be any version updates that break the tutorial but after we are done with the tutorial it's good if you update these packet is to actually get the latest versions and in the future of course eventually next RV 5 will also not be better anymore right now it's in beta but here to follow along you only have to download the starting code run npmi and then you have the same starting point as I have one more thing later I will create a separate Branch for each part of this tutorial for each topic so you can switch between these different branches and see the code for this particular part of the tutorial again okay cool next we go to v.com and log in here Vel is the hosting provider and they are also the team who created nextjs and who build it we will later host our project here when we deploy it and here we also want to set up our postgress database again you can also use a different database provider but I use this one here because it's just so easy to set up when you log into your Vel account it's a good idea to log in with your G iub account which makes it easier later to deploy our project but you can also connect your GitHub account in the settings afterwards I will show you how to do this later so in our Vel dashboard and by the way it's okay if you have a free hobby account it will still work because luckily we get one free database even if we don't pay anything which is very generous and here under storage we create a postgress database we have to give it a name let's call it next off V5 tutorial DB maybe and the region should be close to our users I'm going to pick Frankfurt because I myself are in Germany and for developments this will probably be the fastest because it's close to where I live yeah and I like Vil postgress because it's so easy and quick to set up and again the first database is free so here we get different installation instructions those are the ones for Prisma I actually already added this to the starting code so there's this schema. Prisma file in here which already contains this section we only need the environment variables so we open this tab here click on copy snippet go back in the project but Prisma can't read from the n.l file it has to be this normal n file so in the root of our project so outside of any folders here we create a new new file called. en and I already added this to get ignore here at the bottom so we don't push this to GitHub which is important because the N file contains database credentials that we don't want to share public yeah and in here we paste these postgress credentials and they will automatically be picked up later by Prisma and then we can connect to this database and store stuff in there why do we need a database in the first place well for one to store the user data like the username profile image URL roles and other information but there we also store our sessions sessions are what tell our server that a user is logged in how exactly this works you will see later okay now that our database is ready we can start setting up next off okay under off js. the/ getting started we find this official tutorial here you don't have to open this you can just follow along I will show you everything step by step and this covers next off V5 beta as I explained this one is currently still in beta it has been rebranded from next off to just off JS but this is not so important in our project we already installed the package in the starting code next off 5.0 beta 16 at the moment and when I then click on nextjs I find some instructions on how to set this up so we already installed the package next we need an off secret which is just an environment variable with a random string we can create it with this command npx next secret let's do this we open the command line again run this and then we get this first we have to confirm this with Y and then we get this random string here which rec copy into ourn file this will be picked up by next off automatically we can also wrap this into a quotation marks for consistency but it test the same result okay let's see what the next step is so we have our off secret then we need to set up an off TS file and we can put this anywhere in our project so we go back to the project and we will put it directly into the srz folder so right click on srz we call the file RTS this is just a naming convention you can name this anything you want and here we insert this code please pause the video and type this out by hand or copy it from the documentation if you opened it then we need this route Handler here which later handles sign in sign out and so on if you don't know what the route Handler is you will have to watch my nextjs beginner tutorial which I Linked In the Beginning okay so I copied this as well and this needs a very specific folder structure so pay close attention now because this has to be named correctly every single folder we right click on the app folder in the srz folder we create a new file then we type API slash off slash square brackets in these square brackets we write dot dot dot next off S one word like this/ route. TS which creates these three folders with this route TS file in there and every name here has to be correct yeah and then here I paste this code again please pause the video and type this out okay let's see what the next step is we need this middleware but this is optional this will keep the session alive if we don't have this middleware the session will time out after 30 days so if I log in and even if I use the website after 30 days I have to log in again which is not a huge deal but with this middleware the session will be kept alive as long as the user is visiting our website Within These 30 days and they don't have to log in again let's add this to our project again the place where you put the file and the name have to be exact otherwise this won't work we have to put this directly into the srz folder and call it middleware dots this is a special file type in nextjs which basically creates a piece of code that will be executed before we access our website every time and in here we refresh the session with this bit of code this simply Imports this off from our off file the ofs file that we set up earlier in the root folder okay and next we want to connect our database so there's another menu Point here again there are a ton of different adapters that we can use even if your database isn't listed here you can create your own adapter we're using using Prisma in this tutorial so we click on Prisma we already installed the packages the environment variable alsoo which points to our B postgress database yeah and then we just have to connect this Prisma adapter which will then take care that next off stores all the relevant data in this database here they create a Prisma client in the same file but we will put our Prisma client into a separate file so that we can reuse it throughout our app because we wanted do a database operations to update a user for example so back into our project here is the slip folder and I actually already prepared this I have a bunch of other tutorials where we set this up from scratch I simply copied this from the Prisma documentation when you Google for Prisma client nextjs or just Prisma nextjs then you can find this code here this is the code that I copied into the project and the reason why this requires so much code is because in development when we save changes in our project our server basically restarts and by default this would instantiate a newer Prisma client and after a while we would have too many clients and then it would start working so this code simply takes care that when we save changes in our project we reuse the previous Prisma client okay there's just a little change we have to make in here this is why I added this too by default Prisma doesn't work on the edge The Edge is this content delivery Network that the zel provides and enabling The Edge is usually oped in so we can decide if we want to use this or not but nextjs middle Wares always run on this Edge because they have to run very fast because they're executed before every single request to the page and because we use off in here which in turn later uses our Prisma database Prisma has to be Edge compatible but by default it isn't luckily for a while now it has been possible to make Prisma Edge compatible but we have to do a few additional steps which are explained here so what we do is we remove this to Du and instead we write con neon neon is the name of the database where postest uses a service called neon under the hood which provides these postgress databases but of course the name of this variable here doesn't matter then we instantiate a new pool and it looks like we have to import this manually so up here we import pool from neon database serverless which is a package that I already added to the starting code parentheses curly Braes in here we have to provide the connection string which we find under process. NF dot let's see the environment variable we need is the postgress Prisma URL up here so process. nf. post Prisma URL then below we create a const adapter equals new Prisma neon again Auto Import doesn't work so I import this manually Prisma neon to which we pass this neon object and then down here on the Prisma client Constructor we add curly braces and pass the adapter and luckily it's as easy as that to make the Prisma client Edge compatible and now it will work inside middlewares because this Prisma neon client uses a different way to connect to the database under the hood which is compatible with Edge runtimes okay and when we go back to the docs this is also briefly explained here and next we need a database schema we use post here so we need this one I will put a link to this file in the video description below so you can copy it from there yeah and this contains the different tables in our database that are necessary for user authentication so user information accounts which are these different Google and GitHub login accounts so there is some information about them stored here as well verification tokens are necessary for email login and finally we have the session again the session is what tells our server that this user is actually logged in there will be a cookie set in the browser of the user when they log in and this cookie will be connected to a session instead of database sessions we could also use J WTS those are two different strategies of authentication the benefit of jwt's is that when we open our page we don't have to fetch decision from the database every time because it's a database request that we always have to make however the downside of jws is that you can't invalidate them so for example if you ban a user or a user changes their password you can't destroy their current sessions so if they are locked in with a JWT that's valid for a certain amount of time then they will be able to log in even if they are banned or if their password has changed you can't force them to log out that's the downside of jwt's there are ways to solve this of course the most common one is to use a very shli JWT that's only active for like 15 minutes and then have a refresh token strategy which automatically refreshes the token after it has expired however this refresh mechanism will not work out of the box you have to implement this yourself and the tutorials I have seen so far that use jwt's didn't do that instead they just create one long lift token which has the exact problems I told you about you can't invalidate these tokens so long story short we avoid all these problems by just using good old battle tested database sessions the downside again is that the session is stored in our data datase and it has to be read from the database but we always have the latest upto-date information if we want to force a user to log out we can simply destroy the session we can remove it from our database and they are not logged in anymore similarly if we ban a user or if we change their role this information will be available as soon as they open our website again immediately this is why I'm a fan of database sessions they just work they are easy to use and they don't have these sec security issues and also I've never run into any problems with speed they are still very fast because accessing these databases is fast anyway I copy this into my project again I will put a link to this file into the video description we actually have to make some modifications here so you can copy it from there and this belongs into our schema. Prisma file so there will be a link to this file in the video description I paste this here but now we have this twice so I remove this we also don't need the authenticator so I remove that and this whole authenticator table down here again I cover Prisma in more detail in my other project tutorials if you want to learn how to set this up from scratch yeah but here please just copy paste it from the video description below and a model is just a database table model is the abstraction that Prisma provides over post address to make it easier for us to work with our database just one change I want to make in here so by default the table will have the name of the model user but a naming convention is usually to have lower case and plural as the name we can change the name of the table without changing the name of the model with this add at map function here this way we can change the name of the table to users and I wanted do the same down here add at map to accounts the same for sessions add add map sessions and one more down here add at map rication underscore tokens save this then we open the command line again and we want to push this schema to our database which we do with npx Prisma DB push if this didn't work make sure that all the connection strings in your n file are correct for me it worked so now when we go to our Vel database here and open it and click on browse we have these different tables they don't contain any data yet but our database is ready okay okay lastly for the preparation we go into the ofds file again and we have to connect Prisma to a next off so we set up this Prisma client right so here at the top we want to set the adapter to Prisma adapter I don't know why autoc complete doesn't work I import this manually Prisma adapter to which we pass the Prisma client which we import from our lip folder yeah and now next off is connected to our database it has all the models that it needs but we don't have any login providers yet so we can't log in yet next we will add these login providers and we will start with Google login however we can already start our project in development mode npm runev then we can open Local Host 3000 and we see this amazing website again I kept this simple on purpose because all I want to do here is adding these different authentication features we have a bunch of different pages this one later to update our user data we also have slash admin which we want a block for non-admin users later and we also want to put a button with the currently logged in user here in the top right corner and a menual with different links there is just one problem in our console we see this error here with the edge light loader which is related to Prisma I showed you how to set up Prisma so that it works on the edge right with this Prisma neon adapter the only problem is there's one single library in there that doesn't play along that doesn't work on the edge which causes this whole thing to be buggy in development mode I didn't notice any problems but when I built and deployed the project everything suddenly was super slow there are open GitHub issues about this problem right now and I assume that this will be fixed soon so later you can install a more upto-date next off version and this problem will probably be fixed but at the moment this problem is there and we don't have a choice then to work around this and the way we work around this is to disable our middleware for now because again the middleware runs on the edge and this is causing all these problems so what we do is we rename the middleware and add an uncore in front of it because then it's not active anymore and we won't have this error message here anymore this again means that our session will not be kept alive after 30 days the user will be locked out after 30 days but this is not a huge deal they just have to log in again for another month again later after this bug has been fixed you can update the next off version then you can add this middleware back in and it should just work but for now we disabled this okay now let's add Google loog in so in the next off documentation there is another section about this different auth medication providers or off here are some examples but there are actually even more and the cool thing is once we have set up next off you can add as many of these as you want and next off will take care that they all work together that we don't have duplicate user data and it will also take care of all the backend logic because there are actually quite a few steps necessary to get this to work and next off takes care of them it sends the necessary request to for example Google server it handles the response and so on so we don't have to do very much so let's start with Google login so in order to get this to work we need a Google ID and a Google secret which we get from Google for this we go to the Google Cloud console under console. cloud.google.com and this is free but for every or of client no matter if it's Google or Facebook or GitHub you have to set up some kind of app on their platform to make this to work so here what we want to do is we want to create a new project let's call it next off the five tutorial again of course the name is up to you I don't have an organization so I keep this at no organization we create this project then we have to wait a short moment and after this has finished we click on select project which selects this new project up here oh okay then we click here on the navigation menu go to apis and services credentials here first we go to the or of consent screen and set this up just follow along we want to make this app available for external use so everyone can sign in not only our own team we have to give this app a name again next of V5 tutorial by coding and flow for example user support email here we select the email that is available which is the email address of this account important you don't want to set an app logo because as soon as you add an app logo your app first has to be verified by Google's team before you can publish it if we don't set an app logo we can just publish it right away and make it available for production here you can add links to your website privacy policy ter terms and conditions and so on I think authorized domains is not necessary and then contact information info@ coding andf flow.com Ander whatever you want can also be a Gmail address then we click on Save and continue then we have to add the Scopes that we need and we actually only need these two scopes at the top which contain the profile information of the user that logs in like the profile image and the name and they are also not sensitive so we don't need any special permissions to use them we don't need any sensitive Scopes because we don't want to do anything like accessing their Google Drive account we just want their profile information save and continue we don't need any test users save and continue again confirm everything and then we click on back to dashboard so the content screen is set up next we click on credentials here is where we get our API key we click on create credentials and we need an O of client idea not an API key o of client idea application type is web application and again we give it a name next off V5 tutorial website for example authorized redirect URS here we have to to add something because when we log in via Google it redirects us to a page on our own server and this page then reads the profile information this is handled by next off but we have to redirect to a specific URL in development this is at Local Host right so HTTP without the S colon SL slash Local Host colon 3000 SL API SL off slal SLG gooogle make sure to spell this correctly remember earlier in our project we set up this route TS file under the same folder SL API SL off and then the cetch all route and this handles this callback URL this is just one of the things this handles this handles a bunch of different things and one are the Callback URLs of the different o providers later of course and production we need to add another URL to the actual production domain not Local Host but for now this is all we have so we create this and then finally we get the client ID and the client secret let's take a look into the next off documentation again because we want to use the same environment variable names so we copy this first you can also just type it out by hand go into the N file add these two here but of course replace this for the client idea that we get here again we can wrap this into a quotation marks and here we put the client secret this one boom we saved this we can close the Google Cloud console and now the only thing left to do is to add this Google provider to our RTS file so here our project of TS we want to add the Google provider again I have to import this manually and the import looks like this next off/ providers SLG gooogle and the cool thing is this will now just work all the complicated backend Logic the back and forth and reading the profile information from the Google account is handled by next off for us so when we save this and run this project in development mode we should now be able to go to a local host 3000 slash because we don't have a login button yet we have to go to this URL manually API SL off/ signin and here we should find our signning screen with the Google login button isn't this cool when we click it if you're getting an error here then you are redirect URL in the Google Cloud console is probably wrong go back and double check it to make sure it's correct and then I log in with one of my Google accounts confirm this we get redirected to the app and now we are logged in now we don't have anything on the page yet that shows us that a user is actually logged in but we should see the session in our database and the accounts so what we do is we open another console or just cancel run def for a moment and run npx Prisma Studio which is cool feature by Prisma this opens Prisma Studio under Local Host 5555 and here we can see our database tables we have one new user a session and an account in here so that's the user who just logged in we read the name from the Google account the email address as well and even an image and connected to this is this account row here yeah which is the Google account with the necessary information and the session which again tells our server that this user is actually logged in and in our browser there is a cookie that is basically the key to this session if you don't like how this Pat looks design in page you can also set up your custom page this is described in the documentation we won't do this here and later when we add additional login options like GitHub or email login then they will be added to to this page here automatically again you can replace this page if you want to do this it's described in the documentation now let's add GitHub login as well for this we go to our GitHub account and I just noticed that I forgot to set my pronouns in case you don't know my pronouns are actually asnc and await but this is not what we are here for we want to go to the settings which you can find here and all the way down to developer settings here we can set up an or of app and the interface here is much simpler than on Google again we have to give the app a name next off V5 tutorial homepage URL here we can actually use anything we want for now next off tutorial we.com just as a damier description is not mandatory and here we add the same callback URL as we added on Google just that the last part has to be changed to/ GitHub because this is the GitHub callback in next off again later in production we have to uh change this to the production URL or set up a second app one for development one for production this is usually what you want to do and then we register this application then we copy the client ID here go back into our project in the N file so this is the off Google idea and now we also need the off GitHub idea which is this client idea and then we need the off GitHub secret make sure to spell this correctly because again these variables are picked up by next off automatically if we name them correctly so off GitHub secret we get this here by creating a new client secret we we copy this in here and this is all we need for now so we can close this then we go back to the RTS file we import the GitHub provider and then just add GitHub to the provider array just like that we get a new sign up option on our page here and now we can sign in with GitHub as well so I'm Lo into my coding and flow GitHub account so this is what I can log in with into our app just one thing I want to clarify the users in our app are not actually connected to the Google or the GitHub account so there's no connection between them we only use this data to log in and then we create a session on our own website but there is no ongoing connection to GitHub or Google they are basically just responsible for letting the user sign in and then telling us okay the user is actually the one he claims to be here are his profile information do with this data whatever you want just to clarify this so now if I log in as coding and flow we should have a second user in our app again let's open Prisma Studio we now have a second account in here which is GitHub and what surprises me right now is that this is connected to the same user ID I thought since this is a different email address this will be connected to a different user but it seems that since our session was already active it connected this account to the same user which I think is usually what we want but we only have one user with this Google email address but this user is now connected to GitHub and Google I was expecting this to create a different account but yeah this is apparently how it works we can also try logging into a different Google account which should create a second user for this let me destroy the existing session so that I get locked out we can delete this record for now in Prisma Studio again I go to/ API SL off sign in and then I log into this other Google account here and the cool thing is that we also get all the security features of the O provider so for example I have two step verification enabled for my Google account so I have to do this on a new mission machine before I can log in which is another layer of security continue and now we should have a second account let's see let's refresh the page yeah and now we actually have a second user with a different email address info at coding inflow this one doesn't have an image but it's connected to a different account okay one more thing I want to do for now is we go up here in the next off object in the ofs file here we add this theme value which takes a JavaScript object here we can set a bunch of different values like the login button color and so on I just want to set the logo to/ logo.png and this file is in the public folder here logo PNG so when we save this and open our login page again SL API slof signin we have our logo here which is just a nice touch yeah so we will Implement email l in later and if you need additional off providers again you can look into the documentation but they all work the same pretty much you just have to set up an app on the or off providers page yeah and next let's actually add the button to log in and a way to show the currently locked in user with their profile image and so on and we will start by doing everything thing server side this is why this sign in function here looks so weird it doesn't use a button it uses a form and this form executes a server action the benefit of this is that this works in server components even without JavaScript so let's go back into our project and set this up in our project let's open the nafb bar. TSX file which I already added to the starting code and here we want to show the currently loged in user by default in the nextjs app router this component is a server component right this means we can make this an Asing function and fetch data in here here we want to fetch the currently logged in user which we can do with con session equals a we off this off function is coming from our of TS file we export this here this way we can get the current session of the logged in user if the user is logged in this will have a value and if it doesn't it will be null in here we can find the user under session. user which is now either defined or not depending if the user is logged in now the benefit of hedging the session server side is that as soon as the page is opened this data here will be available so the user will be shown in our enough bar here in the top right corner later as soon as this page has loaded from the server there will be no delay lay between the first time we see the page and until the user pops up it will be there synchronously because before the session has loaded we don't even get back the page from the server the other option is to load the user client site this way we can first load the page then we will not see anything here in the top right corner for a short moment or some kind of place holder which is for example how YouTube does it and then after like a few hundred millisecond the user will pop up there are benefits to the client side approach as well we will later learn what these benefits are and how we can implement this for now we focus on the server side authentication okay so in our nafar we fetch the currently loged in user and depending if the user is logged in or not we either want to show the user button which is another component I have prepared this is a dropdown menu which shows the image of the currently locked in user and some other stuff we want render this here and if the user is not logged in we want to render a signin button instead and the signin button is basically what we saw here in the documentation this part here we can put it into the same component we create a function called sign in button here we want to return a form again we can't use a normal button with an onclick listener because onclick requires JavaScript and this doesn't work in server components but we can use forms and form submit buttons in server components because they don't require JavaScript so to this form we provide an action in form of an async function like this for now let's keep this empty let's close this form tag add the closing tag below and I explain server actions from scratch in my nextjs job to board tutorial I will put a link to this into the top right corner as well in case you want to watch this and here I have a tiebo that should be function okay so this is the form and in here we can put a button for this we use an uppercase button which is one of the shed CN components that I've already prepared it's an import from the UI folder because this button will already be styled again we can't use onclick listeners here but we can use a form subit button which will then execute the server action even without JavaScript and this button will say sign in and then we fill this server action here again this is how they do it in the documentation we make this a server action with this use server directive again I explained this in my other tutorial where I cover server actions from scratch and then below we call await and then design and function make sure the import here is correct it has to be imported from from our RTS file and we have to call this because there's also another function that works on the client which we will use later but here in a server component we need this one from the off file now of course instead of using a form we could also just put a link in here to/ API off/ signin the URL we opened before this is actually what I have done until I realized that they use a server action here in the docum mentation but there are two benefits of using the server action that I found for one if you set up a custom login page under a different URL then this will automatically redirect you to the correct URL the other benefit is that when we lay the hover over the login button if this is a link it will show the preview to this/ API URL which I think is kind of ugly if we use a server action it will not show this link preview it will look like a normal button which just looks a bit better to the user in my opinion but again using a link here wouldn't be wrong anyway this is our sign in button and we want to render AA inside the enough and here we want to check if the user is defined if yes we want to render the user button which I showed you earlier to which we have to pass the user and if not we want to render design in button which brings us to design in page let's say save this open our website again and we are currently logged in here's the drop- down menu now this user doesn't have a profile image if you logged in with a user account that has a profile image you will see an error right now don't panic we will fix this in a second to show you this error I need to log out but we don't have a log out button yet so let's go back into our project and into the user button down here somewhere I left another to-do add lockout functionality so we remove this and again this is a server component and to not have to turn this into a client component we can use a form here again to which again we pass another server action in form of an async arrow function we need the use server directive and then we call away sign out again which is an import from the off file we cers we close the form tag and put it below the button here and then we add type submit to this button as well so it submits this form this is a lowercase b button because we don't need our button styling because this is part of the drop-down menu here so let's refresh the page just to make sure the changes have been applied and now we should be able to lck out which destroys the session sign out and instead of the user button we see the signin button Perfect by the way this only looks a bit distorted because I changed the zoom level of this page normally this text should be right in the middle anyway now I want to log in to an account that has a profile image this one here which we already used earlier because then we see this error which we get because we haven't WID listed this URL yet we have to do this because in our user button we show this image in the next image and we have to allow the URLs where we can load these images from in the next config file so let's go there here we go into this block rewrite images column curly braces remote patterns column square brackets because this is an array in here we put an object with C Braes host name which res to this part here in the front whatever URL you see here it's probably the same one I have l3. googleusercontent.com we put this in here nothing else save this and then we restart our app in development mode so contrl Z to stop the execution then we run npm run def again and refresh our page and then it should work taada and now we see see our profile image here just one thing actually this approach is not really secure because there is a reason why we have to allow these URLs to load images from because the next image that we use in here automatically resizes these images and this takes up compute and this costs us money on basil so you have a certain number of images that you can resize for free and beyond that you pay the problem is if we allow this URL to resize images theoretically other users could use our website to resize their images I don't know how this works exactly but I know that it's possible so ideally the host name should be a URL that you own so only you can resize images on your website what I usually do is I don't take the image directly from the Google server instead I upload it to my own image storage when the user signs up I didn't want to do this here because this takes additional steps and I want to focus on next off but I will do this in my upcoming nextjs course so again you can learn more about this course and keep updated by going to coding andf flow.com newsletter there I will send regular updates about this course and once it's available I will tell you about it and yeah in this course we will Implement an actual file storage and upload the user profile images there but here I skipped this step another alternative is to not use the next image by the normal HTML image tag instead like this which doesn't automatically resize the image which means that we don't have to add this host name and this will still work but there we can't use this Avatar placeholder as the fallback at least not in the same simple way this is why I used a next image here but just to keep that in mind in production you usually don't want to keep this in you want to load the image from your own server or at least a file storage that only you have access to okay enough talk so now we already logged in with two different users and here on the front page I simply want to show a list of these users the purpose of this is to just show you how you can load the user data from our database if you want to show it somewhere and later we will also set up profile Pages for these different users so back into our project we go to the page TSX file in the root folder here inside app to do display users here this is what we want to do again this is a server component so we can make this an Asing function and just fetch our users in here so let's do that const users equals await Prisma do user. find menu which will fetch all users from our database and down here I simply want to render them in an unordered list which we sty with list disk and list inside and by the way I set up prettier in this project so if we press the formatting shortcut it will automatically reorder the classes into the appropriate order because I use prettier in all my projects okay and here we want to take our users that we fetched and map them into UI elements so we take each user and for each user we want to render a list item it needs a key which will be the unique user ID from our database and each user will show a link to the profile page here we add a back Tex string to SL user slash and then user. ID we close this link the text for the link will show the user name but it can be undefined so as a fallback we will instead show user and then the user ID just so that we can show something here to click on and I also want to style the link I simply want to underline it when we hover over it with the mouse and now when we take a look on our page we see two floran valters but those are two different ones my two different accounts accounts this one has a profile image this one doesn't and this is a page I've already set up here under user idea page. TSX again I explained these path placeholders in my next JS beginner tutorial this is something I don't want to cover here I also implemented generate metadata so that we show the user name here in the top in the title of the page again this is all covered in my next JS beginner tutorial and then I simply render this user data I also added an artificial delay here so that the page takes a moment longer to load on purpose so don't get confused why this is so slow I added 1.5 seconds here why because later I want to show you how to cach this page statically which works differently depending if we have authentication on the page or not but you don't have to worry about this for now just keep in mind that this page is slowed down artificially it's not because our database is slow it's because I have this delay in here yeah this is this page next I want to give users the option to update their username to change it to something else for this we have the settings page but right now this doesn't do anything yet and also I want to protect this page so that we can only open it if we are actually logged in because right now if I log out I can still view this page but doesn't make any sense because because we don't have an account that we are logged in with right so let's do that next so when we go back into our project we have this page in the settings folder so in app settings page. TSX which we want to protect and I've split this up into this page TSX file and the separate settings page component which is necessary because this is a client component because it needs some features like toast and form input fields that require JavaScript but we can only set the metadata here on the page TSX file so we have to split this up and also here we now want to do server side authentication to protect this page and again this is only possible in a server component again the benefit of server side authentication is that we don't have to handle a loading State as soon as we get this page back from the server we know if the user is locked in or not and this works very similar to what we did in our nafar we create a con session call await off again get the user from session. user which can have a value or not and then below we check if user is undefined then we want to redirect which is an import from next SL navigation to the login page which is at/ API SL off/ signin and what we can also do is we can add a question mark and this callback URL search param make sure to spell this correctly in C case with an uppercase Z here we can Define the URL where we want to get redirected after we logged in we want to get redirected back to/ settings so we don't get redirected to the front page and now when we save this and then log out we should get redirected to the login page so we can't open slash settings without being logged in sign in with Google and then we get redirected to the settings page and now we can use it so this is how you protect the page you load the session on the page and then you decide what you will do with it later we will see another example on the admin page where we also render a different UI depending if the user is logged in as an admin or not now another option is to handle authentication in the middleware which will be executed before every time we open a page and some people prefer this but actually the zel themselves W against using middleware for authentication for one it's not really that secure because you have to remember to add all the paths that you want to protect here it's more secure to actually do this close to where you fetch the data on the page itself second we can't share the user data between the middleware and our page so we have to fetch the session here again to get the user data and there are some other reasons so I don't use use middleware to protect my pages I do the off check on the page itself I think that's better and this form itself is in this settings page component and for this I use shedy n form component I'm really a fan of them they integrate with react hook form and they are pretty easy to use forms are just notoriously complicated again I don't explain how to set this up in detail here but I have other tutorials where we add this from scratch here I already added this one form field for the username but right now when we run this the server action at car's update profile is empty so it doesn't actually update the username yet that's what we want to implement next just one more thing on the settings page I want to load the name of the currently locked in user so I want this field to be populated with Florian Balter by default when we load the page for this we go into the settings page and what we want to do is we want to forward the user that we already fetch here in the server component to the settings page so that we don't have to fetch it in here again and then use this to populate our Fields default value so we add an interface which we call settings page props this will take a user and we import user not from Prisma client but from next off then down here we destructure this prop from the settings page props and here I added this to do add default value from current user so res set it the name to user.name but if it's undefined we have to file back to an empty string again save this but of course we also have to pass this prop here to the settings page and now when we save this and refresh the page there is the username in here automatically isn't this cool so we go back into our project and here we have this actions. TS file in the settings folder those are the server actions for our settings page and we already called This Server action when we submit this form but in here we don't do anything yet besides passing the name out of the form input field by the way here is a link to the Z actions tutorial in case you want to watch this and here we have to check for authentication again even though the settings page cannot be opened by a non-authenticated user we still have to check authentication in the server action again because you could always circumvent the front end and call the server action directly and this works exactly the same as on pages we fetch the current session with a weit off this time we only need to the user ID not the whole user object so let's create a const user idea which we get from session. user. ID if the user is not logged in they can't update a profile right so below we check if exclamation mark user ID then we want to throw an error that says unauthorized the error messages up to you VI now on the front end this error would just be visible as an error toast this is how I've set this up on the settings page if there's an error thrown we catch it and we show a toast but this error toast doesn't say unauthorized instead it shows this generic error message which is enough because remember we are not supposed to be on this page if we are not logged in in the first place so we don't need a human readable error message we just need an error that aborts the server action because this is never a valid scenario to be in so a generic error message is enough okay if we get below it it means we are logged in then we want to get the name from the input then we want to update the user in our database which we do with Prisma user. update where column craes the ID is the ID of the currently logged in user which is the user idea and then we set the data that we want to update with we want to overwrite the name this is how this works now Prisma will update the user entry with this idea with the name input we sent to the server action and at the bottom we call revalidate path with the homepage URL like this this does two things for one if the front page is cached which it will be by default then this will cast this page to be rendered so the data of the users will be fetched again it will be updated and then it will be cached by Basel so that every time we open this page we just get this cached version and we don't have to access our database every time but R validat path also clears the client side cach router so it refreshes the page basically it's similar to calling router. refresh so it's almost the same like pressing the refresh button here in our browser after we updated the name which takes care for example that we see the latest username here in the nafar user button but it will not look as drawing as a normal refresh instead it will be pretty much invisible just the data here will update and again this is what revalidate path takes care of let's actually try this out let's change the name to just floron submit profile updated down here and you see the new name here in the user button button we can refresh this and we still see the up to-date data and on the front page we now see a Florian and Florian water and if you don't use server actions but API route handlers so these route. TS files to handle your back end then it works the same then you still fetch the session check it and you return an error response if the user is not logged in okay next I want to add an admin role to one of our users which will allow them to access our secret admin page and then there are a bunch more important topics that we need to learn that you should definitely not skip so make sure to watch this whole tutorial all the way to the end to add our new atam in roll we go to the schema. Prisma file and to the user table and somewhere in here I'm going to put it here but the order of these fields doesn't matter we put another column called rle we make it a string and by adding the question mark we make this column nullable so if a user doesn't have a role they are a regular user but we can set it to a string like admin for example and then I press the formatting shortcut shift alt F on my machine to align this properly save this and then we have to push these changes to our database so we open a newer terminal and run the command that we already ran earlier npx Prisma DB push if you get a warning here then confirm it and then let's open Prisma Studio again with npx Prisma studio and then we should see this new column in our table in the user table there is our role and now we can go into one of our accounts for example this one and change this in here directly in Prisma Studio save the changes of course you can also build a functionality inside your app where you can change these roles like an admin dashboard but another simple way is to modify your database directly for example we are Prisma Studio okay and now this user here has this admin role okay and then I have prepared another to do in the user button TSX file I want to show this menu option here only for admins so let's remove the to-do uncomment this and then basically what we want to do is now first of all we want to import this icon here which is just a lusid react icon and then we want to render this conditionally by wrapping it into curly braces we want to render this if user. roll is equal to admin right yeah admin not admin and again the cool thing about database sessions is that we always have to up to-date data because when we open a page we make a request to our server to fetch the current user session and if that role changes we have this information available on the front end and back end the only problem is typescript doesn't know that this role field exists on this user object because by default next off only returns us these values here when we add additional fields to our next off user table we have to have typescript a bit this is described in the next off documentation what we do is we click directly in the root of our project create a new file we write types SL nextus off. d. TS like this which creates this type folder with this file inside it these d. TS files are socalled typescript declaration files and in them we can basically modify the shape of existing types like the shape of the session and the user type in the next off Library make sure to call this file next off D.S and in here we write declare module then again next minus off as a string curly braces in here we want to modify the user interface like this this is the existing user type of the next off library and here we can add this new role which is a string or null because remember this column is optional a user doesn't need a role and then we want to modify the session interface as well because from the session we get the user object and we want to make sure that it has the correct type so in the session is this user variable right so these names have to match lowercase us user colum we want to say that this is this user type here so it has this additional role field and then we create an intersection type of course we also want to keep all the default values in there right because right now there's only the role in there but the ID and the name and so on are gone but instead of adding all these fields down here manually which is easy to get wrong we can just merge it with the previous type the default one which is called default session then we make a pair of angle brackets and write user as a string in here and now we have the best of both words we have all the default values in here that we had previously with the same types and this additional rooll field so now our error here is gone we have this rooll available let's open the app on Local Host and in our menu here there is this new admin option which is a link to/ admin because I'm logged in in with an account that has the admin role let's try logging in with a different account that's a normal user so this one here is the admin and this one is a normal user we can still view the admin page because we haven't blocked access for non-admin users yet but in our user button drop-down menu the admin link is gone which is what we want okay then let's block access for non admin users on this page so we go back into our project and to the admin page in the admin folder and we already know how this works right we retrieve the current session VR weight off we get the user out of the session via session. user and we have to make this server component async yeah and then if we are not logged in at all so if user is undefined then we want to redirect to the login screen again so/ API SL off/ signin and let's add the Callback URL again to/ admin so that we get redirected to this page after we loged in but the cool thing about fetching the session here on the page is that we also have flexibility on what we do if the user data is not what we expect so if the user is undefined so if they are not Lo logged in at all we redirect to the lockin screen but if they are logged in and they are not in admin we want to render a different UI instead just to see how this works but of course how you handle this in your app is up to you you can also redirect the user if they are not an admin or do whatever you want here I check below if user. roll is not equal to admin then I want to return a different UI so we return a main tag I want to set this to MX Auto and my10 which just adds some margin and then I simply want to add a paragraph tag in here with text Center that says you are not authorized to view this page and since I added prettier to this project when we press the formatting shortcut everything gets formatted nicely with parentheses and the correct class order okay so now when we open our non-admin account we see this text you're not authorized to view this page let's log out with this account which brings us to the login screen here is the Callback URL to/ admin that's URL encoded let's log in with the admin account instead and we get to the admin page and now we have access so as you can see adding roads with next off is pretty simple but there's one problem with our code and that is we are curing a weight off unnecessarily often two times per page load once on the page for example on the admin page but also in the nafar which is shown on the same page right and it seems a bit wasteful to call a weit off which makes a database request to get the current session two times to open one page so let's fix that next okay I think this is a problem that is overlooked often we should D duplicate these off requests if we make them in multiple components on the same page otherwise we have unnecessary duplicate database requests and react provides a simple function that does this for us we just have to put it somewhere outside of this component let's put it into the lip folder create a new file in here and the name is up to you I'm going to call it get session and what we do is in here we simply export default then we call this cach function which is an import from react and in here we call our off function and that's it this cache function is provided by react itself and what it does is it duplicates whatever we put in here so if we fatch the session in here it duplicates this request but only within a single server request and this is very important because the name can be a bit misleading when we refresh the page this cache is actually clear CED and we fetch the session again which is very important because we always need the latest session data we can't fetch it Beyond one request but this cache function again only D duplicates it within one server request so in other words when we refresh the page we fetch the session it gets put into this cache and then our nabar and our page both get the session from this cache but when we refresh the page the cache is cleared and the new session is fetched but of course we also have to use this cached function in all places where we called a weight off before so let's open the search here on the Side Bar this one control shift F search for a weight off and let's replace them for our new cached function since it's the default export we have to import this manually and give it a name again I'm going to call this get session from at/ lip SLG get session let's also copy this and then instead of await off we call await get session which gives us the D duplicated session we do the same on the other Pages we don't have to do it in the server action because this is not part of the server request when you open the page this happens later only when we click a button so here we don't want to use our cached version we only want to get our cach session when we open a page so here as well on the settings page and in our nafar that's the important part because the nafar is what is shown together with our pages and now this should be duplicated and we should only make a single request to fetch the session when we open a page now we can't see it directly but this works under the hood basically this is just something I wanted to show you because I think it's important it's a bit wasteful to make two a database request when we only need one one more thing I want to clarify nextjs also provides this unstable cache function but this one is different because this one actually caches a request Beyond multiple server requests so we don't want to use this one to get our session because we would get an out ofate session the naming is a bit unfortunate because they called it cash as well but we want to use the cache function from react not this one just to make this clear and next we will learn how to handle sessions client side instead of server side which is also very important so as I mentioned before the cool thing about fetching a session server site is that when we refresh the page there is no loading time the session data is there as soon as we get the page and we know if we are logged in or not the problem with the server side fetching is that when we fetch the user on a page we can't statically cach this page which makes sense if you think about it because the user is something that's very Dynamic we don't know who is logged into the app before we load the page so next off under the hood accesses The Cookie of the browser which in turn CES nextjs to render a page dynamically Dynamic rendering means every time we open the page we render it from scratch by loading the data from the database if we need any data and then showing it in the UI this is why I've set up these profile Pages because here we load user profile data and theoretically we could cache these pages when we compil the project we could fetch all this data from the database and then cach these pages statically so that at a runtime when the user opens the page we just serve the cached version instead of making a database request every single time but again when we fetch the currently locked in user we out of dynamic caching and the problem is we fatch the user in our nafar which is shown on all pages so this disables steady caching for all our Pages even when we don't need the locked in user on this page itself so in other words if we would remove the user button from the enough bar we could statically cash this page and this way make it much faster and have less requests to our database and this is also why I added this artificial delay in here to show you that this page is not actually cached so let's try compiling the project with npm run build which caches every page that can be cached and we get a little error here but I know why this is cost let's go into the off the s file once again and because we made changes to our user type I think we have to cast this to this adapter type but we have to import this menu this should be coming from the next off adaptor package this should get us rid of our error and then we should be able to compile our project after this is done rerun npm start and open open our page again and now we run our project in production mode and if this page could be cach nextjs would go ahead and cach it at build time but when we refresh the page every time we see our loading spinner because this page is not cached because we fetch the current session every time we open this page even if we are not logged in again we can fix this by fetching the session client site instead of server site now one thing I want to mention is that nextjs is currently working on a new feature called partial pre-rendering this should in theory also solve this problem with partial pre-rendering what we can do is we can go into our enough bar we can move the session fetching into a sub component so we would remove it here and we would put it into something called I don't know user menu for example and in here we've hatched the session then with partial pre-rendering enabled we could wrap this into a suspense bone the re like this and this would also cause our page to be served immediately and only the part that fetches the session would be loaded completely separately so this would look very similar to client side loading because then our user would pop up after a short delay when we refresh the page like we can do it right now we wouldn't have the current user data visible immediately instead it would show up with a little delay this is what the suspense boundary does it defers loading of whatever we put between it after we already got our initial page back so this should have the same effect as loading the session client side just that we can still use our await to get session which might be more convenient than creating a client component if this is all confusing to you don't worry we will start writing code in a moment and then you will get it the problem is this partial pre-rendering didn't work for me I tried it out I enabled it and I wrapped the session fetching into suspense boundary but the pages were still dynamically rendered so this feature is still experimental so it might just not work yet in this case I don't know but we will skip it here I will try to cover it in my upcoming next JS tutorial I hope until then it's stable but here we will focus on fetching decis client side now so for this what we have to do is we go into the layout TSX file the root layout and we have to wrap everything inside the body including the knar and the page just into a session provider which we have to import manually again import curly braces session Provider from and we can find it in next off/ react this is a context provider that fetches the session internally and provides it client side to all the children now we could fetch the session here in this layout as a server component and pass it to this provider VI had the session prop but then all our Pages would be dynamically rendered because you would fetch the session in the root layout and this way access the cookies on every single page but we can also skip this session prop and what will happen then is this session provider internally fetches the session by client site after the page has already loaded this will happen after a short delay because it will take a few hundred milliseconds to fetch the session okay and now in our enough barar we want to fetch the user client side instead of server side so we make this whole component a client component with use client which means that we can't make it async anymore and we can't fetch our session like this with a weit get session instead we use the use session hook and this hook gets the session from from this session provider and then we get the user out of the session similar to before just that now we also have this status field because this can be loading for a while and we get the user from session. dat. user the difference is that there is now a moment when this session is still loading after we already get the initial page back so we have to handle this loading State as well so what we do is if the user is defined then we are logged in and we want to render the user button but if the user is not defined we don't want to render design-in button immediately because we could already be logged in but the session hasn't loaded yet instead we want to show nothing until the session has loaded or a placeholder and many big websites like YouTube or medium actually do it like this when you pay attention to This n Bar up here this is where the current session is shown when we refresh the page there is a placeholder for quite a while because I assume they fetch the session client side or at least with some delay after the initial page has already loaded which makes the initial page load faster of course and this is similar to what we will do here you can create a placeholder if you want I just want to show nothing so below we check if the user is undefined and session. status is not equal to loading only then we want to render design in button right and we also want to change the code of design in button component because on the client this form is not necessary we can just render a normal button and use the onclick function instead which is much simpler so we remove the type submit and add an onclick Handler to which we pass an arrow function and by the way in the repository to this project which you can find in the video description you can find different branches for the different parts of this tutorial so if you want to take a look at the old code again with the Z side approach just go to the corresponding Branch okay and client side this is much simpler we don't need a form we simply call sign in but pay Attention our import here is wrong because this only works on the server we want to use a different sign and function which is an import from next off react this is the client side one and recall it like this so make sure this import here is correct and we can remove the get session import okay then we go into the user button TSX file again where we also want to update our button here because now again this is running client side and we don't need the form so let's remove the form tags remove the on submit and add an onclick listener here as well this time we call sign out again we have to replace the import this one here is wrong we need the react one sign out from next off react and we can actually configure this we can set a callback URL here as well and when we sign out I want to get redirected to the front page not to the page where we came from but this is up to personal preference okay let's save this and let's rebuild our project to see if caching works now and by the way we will fix this error here later so let's run npm run build followed by npm start and then open our page and refresh it and you can already see we don't have a loading spinner here anymore because now this page is rendered at compile time and then cached on the zdn so that we don't get our delay let's also try logging in yeah this is the error that we just saw in the console let's fix this quickly this is a bug in the next off Beta library at the moment but there is a simple fix to this we go into our RTS file again and we have to add another configuration here we have to set trust host to true this shouldn't be necessary this is a bug but there are open issues on GitHub about this already so let's add this compile our project once again and then try logging in so this time we didn't get this error let's run npm run start go back refresh the page and we are logged in great and as you can see the page is still statically cached perfect and the user pops up after a very short delay it's very brief but now the session is fetched client side and it doesn't affect all our Pages anymore another benefit of Hing the session client side is that this is automatic synchronized between Pages which isn't possible Ser side because it requires JavaScript but when I sign out here then I'm signed out on the other page as well which is just nice to have let me look in again as the admin user because you might have already noticed that our admin button isn't here anymore because these additional fields that we added to our schema are not available on the client by default this is for security reasons because by default next off only adds the absolutely necessary fields to the user object that we receive on the client when we call use session because the difference is what we receive on the client is visible to the user in the browser so we could accidentally expose data that we don't want to expose whereas when we render a server component the data that we fetch is first and foremost only available in the server component and only what we render on the screen is actually visible to the user but client side this works differently long story short we have to tell next off that we want to expose this role we have to do this in our RTS file and somewhere in here I want to put it between the adapter and the providers but the order doesn't matter it's just personal preference here we can overwrite this cbex field to which we pass a JavaScript object and in here we have a bunch of different callbacks where we can basically hook into the authentication process and do something we want to hook into the session callback because then we can do something every time a session is retrieved here we get pass the params we want to destructure them and from here we need the session and the user so the session that we get from the database and the user that we return to the front end and then we simply want to tell next off to put this rle into the session that we receive on the front end we do this by setting session. user. roll which is a valid field because we configured this in our DTS file right otherwise this wouldn't be available for autoc completion here we want to assign this to the user role which is the user that we fetch from the database and then important we have to return the session so that we actually get it yeah and then let's stop the execution and run it in development mode again which will not cach any pages but this is not important for now I just want to see if our role is there again so let's open Local Host and our admin role is there perfect so we have to expose this to the client explicitly via the session callback one more thing now that we fetch the session here in the nabar client side when we update a username I think it will not be updated up here automatically that's right this out Florent W submit profile updated but it's not updated up here why because we only refresh the router which ref fetches server components but we don't fetch the session server side anymore we fetch it client side so we have to refetch it explicitly this works the following way we go into the settings page this is already a client component in here we also want to access the current session re const session equals use session and by the way use session is automatically duplicated so you can call this as often as you want in as many components as you want you will always get the same session from the session provider but here we don't actually want to fetch the user we just need a session object because down here after we updated the profile we want to call session. update we don't pass anything to it and this will cause the session provider to refetch the session so that we see the updated username in the user button so let's try this out let's refresh the page just to make sure so we see floran W here I changed the name back and it's updated here in the user Button as well perfect so now we are mixing server side session fetching and Cent side session fetching a little bit because we still protect our page server site by fetching the session in a server component and redirecting if we don't get the user but on the page we update the client side fetched user via the update function I think this is fine we could also remove the server s side fetched session completely and handle everything client side so instead of redirecting here we could have a use effect or something else in here that checks the session from use session and then decides if this page should be shown or not the benefit is we would only have a single request to the session table client site instead of server site and client site the down is again we have to handle a loading state so I prefer to just block the page server side because it's more convenient in my opinion because we can redirect like this but still handle some parts of the user client side because again we want to render our pages and cach them statically which isn't possible if we've hatch the session on the server so this is why we used use session here in the nafar in the first place right what combination you use exactly servers side or client side depends on your project and what exactly you need if you don't need any static caching on your pages then I would just fetch the session server side all the time but if you need static caching then you have to use our workaround or partial pre-rendering once it becomes available okay next let's add email login because right now we only have o off providers Google and GitHub but having email login as an additional option for someone who doesn't want to Lo in with their social accounts is always nice if you want to enable login with password and email then this is also possible it's described in the documentation under credentials but it's actually discouraged there is a warning message down here because passwords are just inherently insecure it's better to use something like an orof provider or magic links like we will use here but again if you want to learn how to use password login you can find more information in the docs for email Lo in we actually have to send emails for this we need some kind of email service for this we will use resent but you need an actual domain to make this work so you need your own website basically where you can change the DNS settings if you don't have this you have to skip this section and go to the next part of the tutorial which is the deployment part because here we need a domain so we want to create an account on resent and then in the dashboard you go to domains and we have to set up a domain here this can be a z domain but you have to own the root domain so coding andf flow.com is my domain and I set it up so that I can send emails from tutorial. coding andf flow.com so click up here on ADD domain and add a domain you own and then you get these different DNS records that you have to add to the DNS settings of your domain provider how exactly to do this depends on your domain provider if you don't know how this works please Google it it's not that difficult but those are some records that you have to add there and then you have to click up here somewhere on verify I have already done this and mine are already verified this means I'm now authorized to send emails from this domain coding andf flow.com or tutorial. coding andf flow.com then we need an API key here under API Keys create API key next off tutorial I will delete this later full access all domains add then we copy it into our project into the N file the name of the variable is off uncore resent uncore key make sure to spell this correctly we insert this API key here save this and then we go into the RTS file and we want to add a newer provider so Google GitHub and then we also want to add resent which again we have to import manually from next off providers resent then we want to C this here but this time we have to add a little bit of configuration we want to set the from email this has to be the email that we authorized via our DNS settings in recent before now the first part of the email address can be anything for example no reply but the part after the add has to match otherwise resent will not allow us to send this email and we will get an error I authorized tutorial. coding andf flow.com and now the login emails will be sent from this email address and now it should just work so let's open our project again refresh this page in development mode and boom there's our email login button now this button text is actually a bug that should say sign in with email and not sign in with resent because most users won't know what resent is right and again there are already issues about this so this will be fixed in the future just so that you don't get confused this will eventually say sign in with email but this will already work let's try this out with my recording email address which is the same email address that the admin Google account has as well sign in with resent this looks good if you get an error here then you probably haven't authorized the domain yet you can look into the console of V es code to see what eror you're getting and now I received an actual email to this email inbox from no reply at tutorial coding andf fl.com and we can click here to sign in but before we click this let's take a look into Prisma Studio because now we should see a verification token here because this is what makes this email magic links possible and this token expires after after a while I think this is one day by default you can change this so this email magic link will be valid for one day and when we click it this token will be deleted and we get logged in to the same account let's refresh this and the token should beun okay super cool and now the user should have an email address associated with them it already had an email address before that it got from Google but email ver ified was null before right because Google doesn't tell us if this email has been verified or not but now that we logged in with the same user and the same email address we know that this email is valid which can be important information okay and you can actually customize the emails you receive again this is described in the documentation here under resent under providers and down here you can customize these emails if you want to do this but I'm fine with with the default text okay and then the last step for this tutorial is to deploy our project and make some changes so that everything still works make sure to not miss this last part because it's very important okay we will deploy our project to V zil there's one step we have to do before we have to go into the package. Jone and add this post install script that runs Prisma generate this is necessary whenever you use Prisma in nextjs this will take care that the Prisma client is generated after the project has compiled or whatever not 100% sure I only know that we get an error if we don't add this okay then we want to push this project to GitHub which you can do it directly in vode here via Source control push everything into a GitHub repository to the main branch then we go to the Vel dashboard where we created our storage before and again this should be connected to your GitHub account if it isn't you can connect it in the settings and then we add a new project and this automatically shows our guub repositories we can just import this project it automatically recognizes that this is a nextjs project but we need to provide the environment variables right so we can just copy this whole file paste it in here and it adds all of them and click on deploy after this has finished compiling we should be able to open this website and we get this free Vel domain so we can still navigate to our Pages which are statically cached which is good I think email login should work right because we don't need to change anything here let's try this out sign in with resent now this says sign in to our URL and not Local Host anymore so this automatically picks up the correct URL and we can sign in in awesome so this still works but OA won't work because our carback URLs Still Point to Local Host and then we get this error here to fix this we go into the Google Cloud console into our project here and then again to apis and services credentials we modify this one and we want to add another authorized redirect Ur we need our production domain which is this one here with the https we copy this in here but the off callback is at the same relative URL so we add this one with htps we save this and now Google login should work so fingers crossed let's refresh the page just to make sure but shouldn't be necessary sign in sign in with Google and it works just like that amazing and since we didn't add the logo here we also don't have to wait for verification to deploy our project we can go to the or of content screen and we can just click publish app and then this will work for any user with a Google account confirm and that's it and now you have Google login available in production next we go to our GitHub settings again and do the same here in our GitHub app o off apps next off 35 tutorial here you can only add one redirect URL so if you need one for development and one for production then you have to create two separate apps I will just reuse the one that we already created just for convenience so again we need the root URL this part here we want to replace Local Host with this and yeah https like this there should only be one slash okay this looks correct update application and now GitHub login should also work sign in with GitHub and since I'm already logged into my GitHub account it just works immediately all right friends I hope this tutorial was helpful if it was please leave a like on this video remember I'm working on a more advanced next JS course if you want to get updates about it join my newsletter under coding andf fl.com newsletter or even even better get my free react best practices email course which automatically puts you into my newsletter you can find it under coding and.com react bestest practices and then I hope we see us in the next video Happy coding take care
Info
Channel: Coding in Flow
Views: 29,107
Rating: undefined out of 5
Keywords: auth.js, auth.js next js, auth.js v5, auth.js tutorial, auth.js next, auth.js google, auth.js 5, nextjs auth, auth js next js 13, auth js prisma, auth.js react, auth.js middleware, auth.js app router, next-auth, next-auth google, next-auth middleware, next-auth tutorial, next-auth/next js 13, next-auth v5, next-auth app router, next-auth next js 13, next-auth email provider, next-auth prisma, next-auth next js 14, next-auth callbacks, next js authentication, nextjs 14
Id: bMYZSi_LZ2w
Channel Id: undefined
Length: 105min 28sec (6328 seconds)
Published: Mon Apr 22 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.