Comprehensive Authentication Tutorial in Next.js 14

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome to the full authentication tutorial in nextjs version 14 in this comprehensive tutorial you will learn everything you need to know about authentication in the latest version of the nextjs we will use the latest features of the nexj version 14 to set up a real world authentication project we will start by setting up the Prisma for keeping the user data in our database then we will configure the latest version of the next AR and I will teach you every detail of the next AR that you might need in your project including next off callbacks we will create a sign up or register user page and go through every detail of creating a nice signup form including form validation password strength Checker and then we're going to create a s action for inserting the new user into our database and then I will show you how we can create a nice custom login page or signin page for your application and then how to integrate it with next off we will also set up an email sending system and create Dynamic email layouts and send activation email to users up on their sign up with an activation link for activating their account and also we will create a forgot password and reset password pages in this tutorial I will show you how we can check whether a user is signed in or not in client components and also in sver components and finally I will show you how to protect your pages from unauthenticated users in several ways and then I will tell you which one is the best welcome to S Channel and without extra explanation let's get into it okay let's begin in the first step in our tutorial we need to create a brand new nexs version 14 project so here I'm going to use bond for creating our nexs project so here I'm going to say BN X and then create next app and then add latest I'm going to name it next is 14 full authentication and I'm going to go with the default options here so as you can see the B created our next Chas project with just 3 seconds this is really fast and actually this is one of the reason that I use bond for my project the other reason is that it is completely compatible with npm it means that throughout our project we can use npm or bond interchangeably without any problem so it's up to you to choose between BN or npm in this project the result is all the same okay so now let's go to the project directory and let's open it up in vs code okay so let's make it a little bigger okay so that's it for this step and in the next step we need to install and configure the Prisma for this [Music] project okay so in this section we're going to install and configure Prisma for our application so here I open up the terminal and here I'm going to sa BN add Prisma you can do it with npm install Prisma this is the same okay it is installed and now we need to initialize the Prisma so here we can use burn for that or npx interchangeably I'm going to say b x Prisma in it and then I'm going to set the data source provider and for Simplicity of our tutorial we're going to use SQL light in this project so I'm going to use SQL light for this project so here I'm going to set it to SQL light so here as you can see it creates a Prisma directory for us and if I open it you can see we have the schema. Prisma file inside it and here you can see the provider is set to SQL light and the database URL is being read from a database URL variable inside our en file so if I go to the EnV file you can see it creates a database URL variable and set it to file then SL D.B so it means that we're going to create a d. DB file a SQL light database file in the same path of the schema. Prisma file okay and now let's get back to our schema. Prisma file and now we can create our [Music] models okay so in order to create our models let's go to the ar.js web we site and let's go to the documentation and let's click on the get started and go to the database adapters I'm going to choose the Prisma adapter here and then here I can grab the models from this script here and then here in the schema. Prisma example we can grab the models here so let's copy them and let's get back to our schema. Prisma file and just paste them here okay so as you can see we have some error here and that's because this annotation here only works with the post SQL and since we are using sqlite we just need to remove them okay and just remove this one and we're good to go so as you can see we have a account model a session model a user model and a verification token model so keep in mind that for most section of this tutorial we just need the user model but you will see at the end of this tutorial usage of the icons and session and verification token models in this tutorial so we're going to focus on the user model our user model has an ID name email email verified image and some relationship with the accounts and session model so let's customize the user model for now we're going to split the name to first name and last name so let's change it to first name okay and then remove the question mark here the question mark makes this field to accept null values we don't want that okay so I remove that and then let's add another field here last name name and set its type to string okay and we also need a password field okay and let's set its type to string as well okay and let's just add a phone and let's remove the question mark from email here we don't want it to accept now values and let's just add a phone field into the user model and set its type two string okay so that's it for the user model as I said just focus on the user model we don't need the other models until the end of this tutorial now we're done with the user model and in order to create our database from this schema file we need to run a migration so I open up my terminal again let's clear this up okay so in order to run a migration let's just use npx this time okay I'm going to say npx you can use b x as well the rest is all the same so here I'm going to say npx Prisma migrate Dev and then set a name for this migration want to set it to just first migration okay so let's run that and you can see it creates the dev. DB file inside the Prisma directory and it also install the Prisma client for us and now we are ready to use Prisma clients in order to access and Rod crowd operation with our database every time we need to run a crowd operation with our database with Prisma we need to instantiate a new instance of Prisma client class obviously this is not a good idea particularly when we fre ly do crowd operation in our database so the better idea is to create one Global Prisma client instance and then every time anywhere inside our project we need to access to our database we can use that Global Prisma client so now let's create Global Prisma client so here inside the SRC directory and side by side of our app directory I'm going to create a directory called lip and then inside it we're going to create a typescript file Prisma Dot s okay and to speed up the process let's just paste some code that I've got from the Prisma documentation so as you can see here we're going to create an object for keeping the global Prisma client and here when we are going to instantiate a new Prisma Client First we're going to check inside that Global for Prisma object if there is not a Prisma client instance inside it we're going to create a new one and set it to Prisma here and here we're going to check if we are not in the production environment we just keep that Prisma instance inside our Global for Prisma object and then just export that Global Prisma client from this file so now let's save this and now anywhere anytime throughout this application when we are going to do a crowd operation with Prisma we can use this Global Prisma client from this file okay so now we're done with the Prisma section and in the next section of this tutorial we're going to install and configure the next Au in our next just version 14 project okay in this section of this tutorial we're going to install and configure the next off in our next just version 14 project okay so in the first step we need to install the next off I'm going to say p add next off okay it is install pretty fast and now we need to create a catch all API route for the next off so let's close the Prisma directory and then inside the app directory I'm going to create a directory called API and then inside it we're going to create off directory and then we need to create a catch all rra so inside the square brackets I'm going to put three dots here and then next off so pay attention to the spelling it should be next off and then inside this directory I'm going to create the route 100 route. TS file okay so this catch all rout Handler will handle all API requests to the/ API SLO and then slash whatever just like this and this so now let's create the route Handler for this catch all rout so if you are familiar with how we can create a catch all route Handler for next o it can skip to the next section but if you're not familiar with that watch this section till the end so in the first step we need to create an off options object so here I'm going to export const o options and set its type to the O options that comes from the next o and then set it to an object here and then here the first thing we should specify is the provider list so here I'm going to specify the providers list and set it to a list here and inside this list we can Define our providers so the providers are the particular ways of authentication in next off for example we have the credentials provider which means that we are going to authenticate our user with a credentials and these credentials could be a username and password or an email and password the other popular providers of the next o are Google provider in which we can authenticate our users with their Google account and in this tutorial we're going to define the credentials provider which is the most basic one and also we're going to use the Google and GitHub provider So In This Very section we're just going to define the credentials provider and in the upcoming section of this tutorial we're going to implement the Google and gar provider as well so now let's define the credentials provider first we need to import the credentials Provider from the next of/ providers SL credentials and now here we can use this credentials provider so I'm want to put it here credentials provider and then pass an object to it and in this object first we're going to define the name for this provider I'm going to set it to credentials credentials and next we need to define a credentials object so here I'm going to specify the credentials and then set it to an object here defining this credentials object has two purposes the first one is that it describes what are our credentials so usually credentials consist of a username and password or an email email and password so we need to Define them in this credentials object and the second purpose of this credentials object is that next off can create a auto built signin form from this credentials object so with that in mind let's define our credentials object let's say that our credentials consist of a username and password so the first one is a username okay now we can set it to an object and we can Define the input type in the next o signin page and now in the username object here we can Define the input type for the username in the auto built signin page that next o can create for us so here we can set a label to it and for example set it to username it would be the label of the username in the signin page and let's define a type for the username input I'm going to set it to text and we can also Define a place order for that and let's just set it to your for example email okay so we can just rename the username to email here but it is more standard to use username as the username of the user and let's just set it to your username okay and now let's define the password for our credentials so here I'm going to say password and then set it to an object Define a label for it going to be password okay and then let's define the type of the password input let's set it to password okay and now we're done with this credentials object so as you can see we have an error here and that is not because the credentials object it's because we need to define a authorized function after the credentials object so I put a comma here and Define the authorized function so I'm going to say async authorize and then it takes the credentials object okay and as you can see after defining the authorized function the error is gone so what is this authorized function so when a user in the signing page clicks on the signing button the username and password are packed into to a credentials object and will be passed to this authorized function so in this function we need to actually authenticate our user in other words we need to check the username and password inside the credentials object and decide if they are correct or not so if they are correct we just need to return a user object from this function and if there are not correct it means that the user is not authenticated and in order to declare that we just need to return a null value from this authorized function or we can just throw an error from this function so since we are keeping the user data in our sqlite database we can access them with the Prisma client so first we need to search into our database to find a user that its username is in match with the credentials. username so here I'm going to say const user and set it to A8 so let's import the Prisma from the liap directory and then Prisma file our Global Prisma file that we have created in the previous section okay and then access to the US user model and then call the find Uni function okay then put an object here specify the we API and inside that actually we are saying that we are going to find our user based on its email so in the where object we're going to set the email to the credentials the username okay so we are actually using the email of the user as its username and here as you can see our credentials has the username and password inside it so next o and typescript are smart enough to infer the type of the credentials from this object that we have to find earlier so for example let's rename the username to email and let's open up the credentials object here and as you can see now it has an email and password so let's change it back to username because it's more standard in the authentication systems so here let's set the email with the credentials the username okay and then after the find unique function we're going to check if the user is existed or not so here I'm going to say if not user which means that the user is not found we can just return a now which means that the user is not authenticated or we can just throw a new error here and set its message to username or password is not correct and now if the user is existed we need to check the provided password inside the credentials object which is actually is the provided password by the user in the signin page with the actual password of the user inside the user table in our database so here we can say const is password correct and here we can just naively check the credentials. password with the user. password but as I said this is a naive way of checking the user password in our database so in the real world applications the user password is not directly saved into our database before saving the user password we need to Hash it and then save the hashed form of the user password in our database so here actually the user. password is the hashed version of the user password so in order to compare the credentials. password first we need to Hash provided password and then compare it to the user. password so now let's combine this out and let's put a comment here this is naive way of comparing the passwords okay so let's do it in the right way first we need to install a package called bcrypt so here let's clear this up first and then I'm going to use Bon for installing it Bon at bcrypt and then since we are using the typescript here we need to install the types of the bitp so here I'm going to say BN add and then dasd because it will be a d dependency and then add types SLB Crypt okay is installed and now we need to import the B Crypts here so here I'm going to say import Star as bcrypt from bcrypt module okay and let's go back here and first we need to check if the credentials. password is existed so actually we are checking if not credentials. password we can just throw an error that says Please provide your password okay and now we can say const is password correct and set it to await bcrypt compare function and now we can pass the credentials. password and the user. password so it is really important here to provide the credentials. password first so here I'm going to say credentials. password and then pass the user. password the first argument need to be hashed and the second argument is already hashed so as I said it really important to first pass the credentials. password okay and here we can check if not is correct password which means that the password was not correct again we can throw a new error here and set its message to username or password is not correct and if the the password is correct we can reach to the next line here and here we just need to return a user object from this authorized function which means that the authorization was successful so now let's extract the password of the user from the user object and just return the user without its password it's not safe to include the password in the returning user object from this authorized function so here I'm going to say const and Define a object here and set it to user okay and let's extract the password and put the rest to an object called user without pass okay and we can just return the user with path from this function okay so we're done with the authorized function and in this way we can authenticate our users with a credentials including a username and password so the returning object of this user with that path will be sent to the next off session and will be kept inside it so every time we need to check if the user is authenticated or not we can just check the next Au session to see if the user is inside it or not if the user is inside it it means that the user is already authenticated and if it's not there it means that the user is not authenticated so we need to redirect the user into the signin page okay so that's it for the authorized function and the credentials provider and now we need to create a Handler from these off options that we have created here so here I'm going to say con Handler and set it to next off function that comes from the next off/ nextt and then pass the off options inside it okay so here note that we don't need to export directly the Handler from this file instead we're going to rename it to the get add post function so here in order to do that I'm going to say export Handler as get function and also Handler as the post function okay so that's it for exporting the Handler and as I said don't export the Handler directly and also we need to export the off options here so later in this video you will see that when we are going to retrieve the session of the next off from the server we need these off options we can use the get server session function and we need to path the off options here to that function so we need to export the O options as well as the renamed version of the next o Handler from this file okay so for now that's it for the next off Route Handler but we will get back to this file in the op comment section but for now it is enough with this [Music] file in this section first we're going to create an app bar and then we're going to create the sign up or register user form for our application and we're going to use the next UI as the UI library for this project it is suggested by some of my subscribers and it's just awesome for next J so I'm going to use it throughout this project and here the next UI web page and here I'm going to go to the get started and click on the nextjs so we need to install these two packages okay open up my terminal here let's clear the sof first and let's paste it here I'm going to use the bond for installing that but you can use the npm if you want the BN is just faster B add and then add next UI and also frameware motion okay and then we need to go back to the next UI documentation and here as you know the next UI is based on the tailin CSS so we need to do some changes to the tail. config file so let's copy this here okay and get back to our project go to detailing. [Music] config.yml provider here so I go back to my app directory and here I'm going to create a provider. TS6 okay and let's go back to the next UI documentation and just copy that providers code here and put it here in the provider. TSX okay and let's just rename it to Providers okay and then we need to go to the root layout of our application and here just wrap the children with the providers component so I'm going to use the providers and wrap the children inside the providers components so if I go back to the providers component you can see the children's are wrapped inside the next UI provider it actually might be a context provider and that's why we use the use client here but the reason why we don't directly wrap the children of the root layout with the next UI provider is that if you are going to do that we need to Mark the root layout of our applic with used client and this is not a good idea because it will turn the whole application to client components and that is not desirable so we just keep this root layout as a server component and just wrap the children of this root layout with a providers component which is actually a use client but this will not turn these children to client components for more information just check out this video okay so let's get back to our project and now let's create our navbar component so in the app directory I'm going to create a directory called component and then inside it we're going to create our appar which is actually the Navar of our application app bar. TSX okay so let's create a component here and it will return a navbar component which comes from the next UI and then just go to the next VI are here and copy the code inside the nav bar the example code okay and let's put it here and we don't want the brand here okay let's import the component the Navar content and Navar items okay let's import all of them and here let's first create a home link here which return to the slome which is going to be our homepage and let's remove the other items here for now we don't want them okay and then we're going to create another content and set the justify to end so it will push it all the way to the right of our nav bar and then here we don't want the login link here for now let's just add the sign up button and set its Ed to the slash off and then slash sign up okay so let's save this and now this is actually our Navar a really simple one so now let's go to the root layout of our application and above the children let's put our app bar which is actually the nav bar okay so let's save this and let's run the application for running the dev server you can use Bond Dev or just npm brev so let's just go with the npm bronev to show you that it's compatible with the Bon okay and let's open it up in our browser okay so let's enable the dark mode here so I go to the T.C config.txt layout and here in the HTML let's set the class name to dark okay so let's get back to our browser and as you can see we have the dark mode mode enabled in the nav bar and let's get back to our vs code and go to the appar component and set is board R to the Navar component and let's get back to our browser and you can see now we have a border at the bottom of the Navar okay so that's it for creating our app bar and now let's create the sign up form or register user form for our [Music] application in this section we're going to create our sign up form for registering a new user so here inside the app directory I'm going to create a page here first we need to create an off directory okay don't confuse that with the off directory inside the API directory okay and then inside it we're going to create our signup route and then inside it we're going to create our page. TSX file so let's create a component here let's rename it to sign up page okay so in the first deep we need to create a two column grid so here in the class name I'm use GD and then grid calls one in case of mobile view and on medium screen and grer you're going to set the grid calls to two and then set the justify to cender and also the items items cender okay so now we have a responsive two column grid now let's get back to our browser and if I click on this sign up here you can see now we are headed to the SL off. signup okay get back to our project and first we need to create a P tag here and insert it we're going to say already signed up and then put a nexs link here okay and redirect the user to the sign in page let's set the edra to the off and then SL sign in the wrap that we haven't created so we're going to create it in the next section of this video okay so let's add some T and CSS classes here or we can just use the link component that comes from the next UI so it is already styled and we don't need to style it manually with tailn CSS classes so let's import the link here and let's get back to the sign up form and if I click on this sign in here you can see it will redirect us to the 404 error page and that's because as I said we haven't created the signin page so let's get back to our sign up let's put this P tag and signing link together so we need to put them inside the div here okay then let's wrap them inside that de and let's set the class name to an MD medium screen or greater let's set the cold span to two so it will span through two column on the medium screen or greater and then just set the class name of the P tag to the text Center and just put a padding here P2 okay let's put a flex here and justify Center and also item Center as well okay so here as you can see now we have the nice positioned message here so now let's create our form here I'm going to create a separate component for our form so here inside the components directory I'm going to create a signup form. TSX let's create a functional component here for now let's return a sign up for message and now let's get back to the sign up page and just render it into the main div sign up for okay and now let's put a image element so I'm going to use the image component that comes from the next UI okay and set its src2 SL login.png file so we need to put the login.png file inside our public folder so obviously that's not there so we're going to put it here in a second and set a alt to login form for example and let's define the width to 500 and also height to 500 and then let's close the tag here and let's put the login. PNG file inside this directory okay so let's open it up in our File Explorer and put it here okay let's close this up and let's go to our browser and as you can see we have the image on the right column of our grid and the sign up form in the left column so now let's design the sign up [Music] form I get back to the vs code here and go to the sign up form component and here let's design our form so in the first step let's change the root DF to a form element okay and then let's add some taable CSS classes we're going to need a GD here with two columns so I'm going to set the GD cools to two and a gap of three between the columns a P2 for its padding and we're going to add some Shadow to it okay add a border and a rounded MD for its border radius okay so here let's define an input so we're going to use the input component from the next UI so going to import it and let's set a label for it the first one is going to be first name and you can add an icon to this input for example let's say we want to add a user icon to it so we can add the start content W and now we can just render our desirable icon here the start content will set it to the left side of our input so for the icon Library I'm going to use a icon library that is completely compatible with tan CSS the hero icons okay in the hero icons.com go to the documentation and copy the script for installing the hero icon okay let's create another terminal and let's paste this script here let's change it to the B ad but you can go with the npm install as well okay it is installed so let's close this up and now let's go back to the hero icon and search for a user icon user icon so it will be the user so here let's render a user icon that comes from the hero icons okay and let's put a class name here and w44 with as you can see we have used tail one CSS class and as I said the hero icons is compatible with tail1 CSS so we can use tail one CSS classes to style the icons here okay so let's go back to our browser and as you can see we have a first name input here so let's just make some gap between these two column here so I go back to the sign up page and here in the root de here let's put a gap three okay so here as you can see now we have some space between the image column and the form column okay so let's get back to our signup form again and put our second input which is going to be the last name okay can see we have the last name then we're going to put the email let's change the label of the input to email and let's go back to her icon and search for the email okay let's search the mail and we have the envelope here so let's get back to our vs code and set the email to envelop icon okay okay get to our nextjs app in the browser so let's span it through two columns here going to add a class name to our input and set it cool span to two Okay so as you can see it spans through two columns here okay so I'm getting back to our vs code and let's copy the last input and just change the label to phone okay now we have the phone so let's find a proper icon for it search for the phone here and it is the phone so let's change the icon to phone icon here and let's get back to the browser okay the phone icon here and now let's put the password input okay so let's copy the last one change the label to password and set its type to password okay so now let's get back to our browser and as you can see we have the password input here and the type of the password is password so let's get back to our project let's change the icon to key icon okay and then let's just copy that that and set its label to confirm password okay so as you can see here now we have the confirm password and the icon is changed to a key icon so now let's define a toggle password into our password input okay so here we need to define a state here I'm going to say const is visible pass and set is visible pass okay use the use State here and for the initial value I'm going to set it to false so since we are using the use State here we need to set it to a use client okay and also we need to define a toggle function so here I'm going say con toggle visible pass and set it to a function and then just call the set is visible pass and use the prep value and set it to not of the prep value okay and then here in the password input we need to set the end content we're going to use the conditional rendering here going to check if the is visible pass is true then we're going to return a i icon Okay just set its class to W4 and just cursor pointer okay so let's remove the ending tag and let's actually import it from the hero icons and on the unclick event of this I icon which just call the toggle visible pass function that we have just created and then if the is visible pass is not true we just return a i SL icon okay and then just copy the class name and unclick function from the I icon to this I SL icon so let's save this and here let's go to the Ty prop of the password input and here let's set its type conditionally we're going to check the is visible pass if it's true set its type to text and if it's not true let's set its type to password let's save this and let's go back to our browser okay so as you can see we have the I SL icon here so you just need to change the order of the icons when the is visible pass is true we just need to render the I SL icon and when the visible is false we just need to render the I icon so let's get back here as you can see if I click on the I icon here we can see the password is visible okay so now we can just conditionally set the type of the confirm password so let's just copy the type of the password input and paste it here inside the confirm password and here as you can see when click on the IE icon here you can see the type of both password and confirmed password is turned to a text input okay so now let's continue designing our signup form we need to add a checkbox that user must accept the terms so here I'm going to use checkbox components that comes from the next UI and then inside it here I'm going to say I accept the terms and let's put the terms inside the link here so the links comes from the next UI and put the terms here set its ATF to for example slash terms okay let's get back to our browser and as you can see now we can check the accept terms here so as you can see this is a nice checkbox from the next UI okay so now we just need to add a submit button into our form so let's get back to the vs code and here after the checkback we're going to render a button here and the button element comes from the next UI so here I'm going to say submit as the caption of the button and let's set its type to submit okay so as you can see the submit is on the right side of the checkbox so let's put it under the checkbox so I get back to vs code and so the class name for the checkbox and set the cool span to two column and let's set the color of the button to primary okay so let's get back to browser let's move it to the center so let's just put it inside a div here okay I wrap the button inside a div and set a class name to the parent the I'm going to set the flex and justify Center and also let's set the cool span to two let's get back to our browser and you can see the button is now on the center of our form so let's make it a little wider here in the button set its WID to the w48 for example and as you can see now it is a little wider okay so as a last step in this section let's put this image element into the center of its column so in order to do that let's get back to vs code and I go to the sign up page okay in the parent de let's replace the justify center with a place items Center class okay so if I go back to the browser you can see that the image element is now in the center of its form and we just need to stretch the form component so I go back to vs code and go to the sign up form and here let's add a class Place self stretch let's save this and as you can see now the form element fills up all the width of its parent column so yeah that's it for this section we have designed our sign up form and in the next section we're going to implement the form validation with Zod so now let's get into [Music] it okay so now let's go back to our vs code and here let's open up the terminal and install the react hook form so I'm going to use BN for that BN at react hook form and also zot okay and as you can see these two packages are installed so now let's close this off and here outside the signup form for the form validation we need to create our form schema with zot so here I'm going to say const form schema and set it to zed which is come from the zot package so let's import it and then put the object here z. object and inside it we can Define the elements of our schema the first one is first name so we have the first name which is going to be z. string okay and then we can change a mean function so the mean length our first name would be two and now we can define a mass message if this criteria would not be satisfied so we can put a message here first name must be at least two characters okay and also we can change the max function for example set maximum length of the first name let's set it to 45 and we can define a message for it so let's save this to break it down into multiple lines and I'm going to set the message to the first name must be less than 45 characters okay and also we can chck a reg X we're defining a regular expression for the first name and inside it we can pass a new reg X class and then inside it Define our regular expression so let's break it down into a new line and here I'm going to say our first name must start with a letter A to Z and also uppercase A to Z and put a plus here because we need to at least one letter and then with a downar sign to signify this is the end of our bre X and also so we need to put a message here so after that we can say no special character allowed okay so now this is the pattern for the first name we're going to copy that and paste it here as the last name okay just need to change the first to last here and here okay then we're going to define the pattern for our email so I set a email key here and set it to Z that string okay then change the email function and we can just pass a message here here and say please enter a valid email address okay the next one is going to be phone and we use phone and set it to z. string and then change the regx function to put a new regular expression for our phone Define a new r x and put our regular expression only numbers are allowed so here and to put zero to 9 and let's just put a length for it for example let's allow eight number so I I think this is not a good idea to validate our phone number let's just go with a universal pattern so let's save this and open up our terminal and install a new package called validator so here I'm going to say BN add validator it is installed so we're going to remove the regex function and instead we're going to use the refine function so refine actually take a callback function text the value and then here we can return true or false if we return true from this call back it means that the pattern is satisfied and if it returns false it means that the pattern is not satisfied and we can return error massage so here instead of passing this call back we're going to pass the validator the package that we have just installed so let's just import validator from validator okay so we have an error here and that's because it's not compatible with the typescript in order to fix the problem we need to install the types of validator so here I'm going to say Bon add- d add types validator okay so the error should come now so now we can use the validator here validator that is mobile phone okay so in order to show you what is the validator that is mobile phone it's a function validator that is mobile phone and it takes a string here that should be a phone number and if it's actually a phone number it returns true and if it's not it returns false so we pass this validator do is mobile phone as the Callback function to the refine function so if the value of the phone is actually a phone number it returns true and the refin function will be happy with that and if it's not a for number it returns false and the refine function is not happy with that so in case of it's not a phone we're going to return an error message please enter a valid phone number okay and then we're going to define the password it is going to be a z. string then the minan length should be six character and let's put error message for that password must be at least six character and we can just put a Max function okay let's say the max length is going to be 50 and let's break it down the multiple line here and with the error message here password must be less than 50 characters okay and the next one is going to be confirm password okay and let's set it to the pattern of the password with main length Okay so now let's add the last one which is going to be accepted and it is going to be a z. leral because we want it to be exactly true with literals we can't directly set the error message we need to put an object here and specify an error map function which is going to return object and this object should have a message inside it and now this is the error message in case of accepted is any literal accept and true so we're going to say please accept all terms okay and here this is the form schema and as a last step in order to check if the password and the confirmed password are the same here at the end of the z. object we need to change the refund function okay it takes the whole data of the object and here we're going to check if the data that password equals to data. confirm password so if these two are the same we just return true and the refine function would be happy with that and if they are not the same we can return a object here that contains the error message so we're going to say password and confirm password doesn't match okay and here we need to specify on which element we should put this error so we have to define the path here okay put a arror here we're going to set it to password and confirm password okay so in case of the password and confirm password are not the same we're going to return this message and we're going to put the error on the password and confirm password so yeah that's it for the form schema and in the next subsection setion we're going to integrate the react H form with the signup form and use this schema in the form validating so let's get into [Music] it okay so in this section we're going to integrate the react hook form with our sign up form so here in the sign up form I'm going to use the use form so I'm going to say const and here set this object to use form which comes from the react hook form and now we should pass the input type as the generic type to this use form so how we can get the input type we're going to get it from the form schema object that we have created here with Zod so let's get back here and outside the form we're going to say input type and set it to z. infer and then set the generic type to the type of form schema object that we have created with z now we can use this input type in the use form okay for now we don't need to path anything more to the use form hook we need to set the Zod resolver for form validation but before doing that let's extract the register function and handle submit and also the reset function for resetting the form after the submit okay so now let's go to the inputs of the form so let's spread the register function here okay and then pass the first name let's copy that and go to the last name and just change the first name to last name go to the email put it here specify email to this register function go to the phone paste it here and put the phone number here set it to password okay and then do it with the confirm password and as a last item let's specify it inside the checkbox and specify the accepted to okay and now let's go to the form and specify unsubmit and set it to handle submit function that we have extracted from the use form and then pass a function so I'm going to set it to save user function which we haven't defined yet so let's define the save user function I'm going to say const save user and set its type to submit Handler that comes from the react hook form so let's import it and now let's set it to an async function okay specify the input type in the generics so this is the type of the save user function and let's set async function to the save user it takes the data we don't need to define the type of data because we have set its type here in the submit Handler and then Define the body of this function so for now let's just plog the data into the console okay so now let's save this and now let's go to our browser here we have an error on the rec X function so let's get back to the form schema so here as you can see we have passed the error message to the Constructor of the regex we shouldn't do that we should close the regx function here and then pass the error message here and let's remove these parenthesis Here and Now we shouldn't have any error so let's fix this reg X again okay let's save this and get back to our browser and as you can see the error is gone so let's put some damy data here okay as you can see we don't have to follow the form validation because we haven't yet enable the form validation and let's submit let's open up the console we have an object here okay and let's make it a little bigger we have a problem here and that's it accept it is undefined it should return false okay so let's get back to vs code here so it seems that the checkbox component of the next UI doesn't work with the register function of the react hook form so now let's do it another way let's use a controller component that comes from the react hook form okay so now let's set the name and you can see it doesn't have the AR complete of the name so it is not aware of what is the input type in order to fix that let's go to the use form here and extract the control from the use form and let's let's get back to the controller component and let's set the control to control that comes from the use form and now if I open up the name you can see we have our completion so I select the accepted field we're going to have a render function in which actually we need to render our checkbox so we need to pass an call back and then cut the checkbox here and pass it here into the render function we should remove the register function from the checkbox and here let's extract the field from the the call back function and here let's just spread the field okay so got a problem here and that's because some of the field member is not supported with the checkback so let's do it manually going to set the unchange to field that unchange and let's set onblur to field. onblur and now let's get back to our browser and let's set the accepted here and click on the submit here and now we have the accepted value so let's uncheck the accepted let's cck clear this up click on the submit and you can see now we have accepted two fils so now we are integrated the react hook form with our signup form and in the next subsection we're going to enable the Zod validation in this sign up [Music] form okay in order to do that we need to install the resolver of the react hook form so I open up the terminal and here let's clear this up install the hook form SL resolver so this time I'm going to install it with npm okay it is installed and let's close this up and now we can go to the use form H here and pass an object to it and set the resolver to the Zod resolver which is come from the hook form SL resolver and then Zod okay and then pass the form schema to it so now let's get back to our browser so let's clear this up and now if I click on the submit you can see we don't have the data into our console and that's because the Z resolver prevents the running of the onsubmit function function so all we need to do is to render the error message under each input so in order to do that I go back to vs code and in the use form hook here extract the form State and then from the form State we're going to extract the errors okay and here let's go to the first input and specify the error message Dr that is from the next UI input and set it to errors that first name the message okay so this error object is come from the form state of the use form H so let's save this and get back to our browser and let's submit to form and you can see now the error message is under the first name so we can specify another props of the inputs and that is invalid we can set is invalid the next UI input to the errors that first name okay so we need to set it to a Boolean we just add double exclamation mark and that will turn the error. first name to a Boolean so let's save this again and go back to our browser now if I click on the submit you can see not only the error message is shown below the input but the background and the label also shows an error on the input so now let's do this with other inputs okay go to the last name and put them here we just need to change the errors to the error. last name and here last name okay go to the next input it's email going to change it to errors. email okay I'm going to do it with the next input which is phone change it to errors. phone and here let's go to the next input which is password and set it to error that password and here next input which is the confirm password errors that confirm password and also change it here and in the next one let's put it into the checkbox here but here the checkbox doesn't have an error message prop so we need to manually put the error here so after the controller we can render a P tag here and we can conditionally say that if errors there that accepted is there turn it to a Boolean value and then put a and operator and render a P tag say this class name to text red 500 for example and put the errors that accepted that message okay so now let's get back to our browser and click on the submit and you can see now we have the error on the accept checkback so yeah in this way we can actually enable the Zod validation in our use form hook so now let's put some valid data here for example let's put my name here okay as you can see when the pattern is satisfied the error is automatically gone put my email okay put a phone number here and put a password for example 1 2 3 4 5 six 7 so let's put a different password and the confirm password and click on the submit so we don't have the error message here so let's get back to vs code I go to the refin function of the form schema where we check the equality of the password and confirm password and here let's just remove the password and set the error and the confirm password click on the submit and as you can see here we have the error message looks like that we can set the error message only on one field okay so now let's fix that let's remove the last character and now both password and confirm password are the same so here let's add another character and as you can see it shows us the error again so let's remove that and the is gone and let's open up the console here and I click on the submit and you can see we get the data with all its filed so yeah in this way we can create a beautiful form and enable the form validation with Zod so in the next subsection we're going to create a password strength component to visualize the strength of the password that user is putting in the password [Music] field so we need to do it in two steps in the first step we need to to retrieve the value of the password that is entering to the password field and calculate its strength and then we're going to create a component that takes the calculated password strength as its prop and then visualize it in the signup form so without any explanation let's do it okay so we are in the signup form and here we should retrieve the password that the user has entered in the password field with the watch API of the use form and then calculate the strength of the password with a package called check password strength this is the package that we're going to use to calculate the strength of the password its name is check password strength and this package gives us a function called password strength and it takes the password and it returns an object that has an ID zero for two week one for week two for medium and three for strong the returning object also has string value like two week week medium and strong so we're going to install this package and use it to calculate the strength of the password so I go back to the vs code and open up a new terminal here and here we can install the check password strength with npmi or Bon add check password strength okay as you can see it is installed and now we can use it in our project so let's close the terminal here and let's extract the watch API from the use form okay and I'm going to create a state here con call it pass strength and set pass strength and we create it with u State and the initial value is going to be zero which means two we and then we're going to create a use effect here and inside this use effect we're going to retrieve the password value from watch function and pass it to the password strength function from check password strength so here let's define the dependency area first we're going to use watch the password okay and then here we're going to use the set password stren strength okay this is our state and here we're going to call the password strength that comes from the check password strength package okay let's import that and then we're going to pass the value of the password with watch function and then password watch. password it gives us an error here because the returning value of the password strength function is an object but the set password strength expects a number so here we can pass the ID of the password strength function so as you can see it has the value length ID and contains so we're going to pass the ID here and that would be okay so the pass strength State here is actually the calculated strength of the password so now that we have the value of the strength of the password we need to create a component that takes that value and visualize it so here in the components directory I'm going to create a new component and let's call it password strength okay let's create a functional component here okay and let's create an interface for defining the props of the component I'm going to call it props it is going to have an pass strength that is going to be a number okay and let's take the props here so set the type of the props to props and let's extract the pass strength from out of it so actually in this component we're going to create one two four boxes here based on the value of the pass strength so if the pass strength is zero we're going to create one box if it is one we're going to create two if it's two we're going to create three box and if it's three which means that it's too strong we're going to create four boxes here to visualize the strength of the password okay something like this so here I'm going to set a class name here going to use flex and we're going to set the Gap to two for example okay so here inside div we're going to create an AR based on the P strength and then map through that aray and then create our boxes so first we need to create the aray based on on the P strength so here I'm going to use the aray class and then from okay then pass an object here specify the length of AR it is going to be P strength plus one okay so if it's zero we're going to create one element and if it's three we're going to create Four Element okay and now we have the array which its length is based on the past strength and then we can map through this array okay we're going to use the I and also index okay so let's put another parenthesis here because we have two parameter for the call back okay and then return a div here so let's set the key to index I believe it is safe to use the index as the key for this div here because we're not going to manually delete or add to this aray so it is safe to use the index as the key and then let's save this to break it down to multiple line here and let's pass the class name okay so let's use the CLS X function so it is not installed it is used for passing the conditional classes as you know so let's install the clsx so here I'm going to say BN add and then clsx tail W merge okay so we can use this clsx or we can just use the CN function which is a combination of the clsx function and Tailwind merge function so the clsx is used for conditional class objects that you will see in a second but Tailwind merge is used to merge conflicting Tailwind CSS classes for example if we pass two class for padding for example P1 and p 0 the tail1 CSS merge will pick up the second padding class and remove the first one so it is used when we want to make sure that we don't have conflicting tail and CSS classes in the class name list so I use the CN class it is really a good utility that we can use when we are using ton CSS in our project so for example let's say we want to pass the edge2 for the height of our boxes and then we're going to pass H3 so these are actually conflicting T and CSS classes the CN function just pick up the second one and remove the first one so if I import the CN function here we can make sure that second Edge class will be pick up by the CN function so now let's remove the second one because we want them to be edge2 and then w32 for the width of each box and let's use the rounded MD for the Border radius of each box okay and then we're going to pass an conditional object here for the background of each box so we're going to use BG red 500 if the password strength is zero so we're going to say if password strength is zero just pick up this background color class so let's save this to break it into the multiple line and then we're going to use another conditional class we're going to use BG orange 500 if the pass strength is one and BG yellow 500 if the pass strength is equal to two and then we're going to use BG green 500 if the pass strength is equal to three okay so let's save this and now we can use this password strength component in the sign up for so here I'm going to use it after the password fied so let's find it here okay it is here and then after the input of the password we're going to use the password strength component that we have just created okay we need to pass the pass strength proper with the pass strength state that we have defined and set its value with the check password strength package okay so let's save this so if I go to my browser you can see now the password strength here visualize the strength of the password so let's put a random password here let's toggle the show password here and as you can see it is really a simple password so let's add some special character to it as you can see the strength of the password is now changing let's add another one use numbers okay and then use some other capital letters and you can see now the strength of the password says that it's a really strong password so as you can see the password strength is spanning through one grid column here so let's span it on two grid column in order to do that I go back to the password strength component here and here in the class name of the parent de I'm going to use the cool span Tu okay so let's save this and as you can see it now uses two column here so here if I say justify around okay you can see it takes all the space of two columns so now let's put a weak password now the password strength on the center but we want it to be on the left side so here we need to use the conditional object classes okay here we're going to use the CN function again and first pass these three classes and then pass an object here and say justify around when the password strength equals to three and then pass the justify start when the pass strength is less than three okay so let's save this we got an error here and we need to add a parenthesis here okay we're good to go I get back to the browser as you can see now the password strength is on the left side so let's put a strong password okay now as you can see the strength of the password is positioned well in the sign up form so that's it for this section we have created our sign up form with the next UI library and we use the react to form and enable the format validation with the Z package so that's it for this section and in the next section we're going to create a server action for inserting a new user into our database so let's get into [Music] it okay so I go back to the vs code and here I'm going to go to the leap directory and inside it I'm going to create another directory called actions and then inside it we're going to create a typescript file of actions. TS okay okay in this file we're going to create the server action that related to the authentication so the first step is to mark it with the use server so now every function inside it is actually a server action so now I'm going to create a register user function that actually takes a user and insert that user into our database using Prisma client so here I'm going to say export async function and we call it register user and then it takes an user so here we can set the type of the user to the user that comes from the Prisma client okay but if I hover this user type you can see it has an ID inside it and it is not an optional value so going to use the typescript utility types the omit okay and then pass the user as its generic type and here we're going to specify that we want to remove the ID from the user type so now the type of this user parameter is the user without its ID so now we can Define the body of the function I'm going to say H result and set it to await and now we can use Prisma client our Global Prisma client that we have created in the lip / Prisma file okay and then going to call the user and then call the create function okay and inside it we're going to pass an object it should has the data inside it and we're going to set it to user parameter that we have created so now let's test the function and it has a drawback and I will tell you in a second so in to test it we need to go back to our sign up form and here I'm going to go to the unsubmit function okay here it is the our save User it's not unsubmit it's save user function that we call when the form is submitting and the unsubmit props of our main form so I go to the save user function it's a submit Handler of the use form okay and here instead of the logging the data we're going to create a user object from the data so here I'm going to say con so if I hover on the data you can see it has a first name last name email phone password confirm password and accepted so we don't need the last two the confirm password and accept it so we need to extract the confirm password and accept it from our data object so here I'm going to say const and then set an object set it to the data okay and then here we're going to extract the accepted and also confirm password and then put the rest to the user object okay so let's remove this back text here and now we can call the register user server action so here I'm going to use a try catch block okay and let's put the cat block first let's back it to the tri section and here I'm going to say const result and set it to await and now we can call the server action await and then register user server action as you can see it comes from the LI directory action and the off actions okay and then we can pass the user object into it we got an error here and that's because our user object now just has first name last name email phone and password but the user object that register user takes has first name last name password email email verified phone and image so we need to remove the email verified and also image in the omit utility class so I go back to the register user and here let's put a or here and specify the email verified and also specify the image okay now let's save this and get back to the sign up form and as you can see the error is gone now we can just allow the proper message to user we can use the allert function or we can use some toast Library like react toastify so in order to do that let's install the react toasttify here so I'm going to open up the terminal and here let's clear this up I'm going say BN add react toastify you can use npmi react toasttify okay it's done and let's go here and in order to use the react to defier We need to go to the root layout and below the children we need to use a component from react toastify it's the toast container components that comes from the react toastify so now let's go back to the sign up form and now we can use the react toastify so I'm going to use the toast function toast that comes from the react toasttify and then call the success function and put a proper message to it for example I'm going to say the user registered successfully okay in case of any error let's catch the error okay here I'm going to use the error here and then inside the catch plug we can call the toast that error and put a message to it for example we can say something went wrong okay and then we can log the error into our console so here I'm going to say console that error and put the error inside it okay so now let's go to our browser and test the result here so for example example I'm to put my name okay my last name my email for example let's say Sakura 23@gmail.com put a phone here put a password Here For example 1 2 3 4 5 6 as you can see it's a weak password okay and accepted terms here and click on the submit so the toast function doesn't work properly and that's because I forgot something but the proper message is shown into the screen and it shows that user has been successfully inserted into our datab so now let's quickly fix the toast problem here I think I I should import the CSS file of the toast library that the description of that is on the documentation of the react toasttify so I go to the root layout and here just import the react toasttify CSS file that I've got from the react toasttify documentation so let's save this as you can see now the user registered successfully message is shown onto the screen okay so now let's go back to the PS code and here let's open up the Prisma Studio B X Prisma Studio okay go to the user model and as you can see we have a user inside it and the password is plainly saved into our database so as you can see the password is saved as 1 2 3 4 5 6 no hashing so this is a naive way of the saving the passwords into our database so I go back to the server action the register user server action and here first we're going to have the password of the user and then save it to the database so here in the data section of the create function of the Prisma we're going to pass an object here spread the user and just set the password to the hash function of the bcrypt library so we need to import the bcrypt here import everything as bcrypt you can just import the hash function only but for readability I just import all of them as bcrypt and then I'm going to say from bcrypt module okay and here I'm going to set password to await and then then bcrypt that hash function put the user. password inside it and determine the number of salt ramp so the number of salt round determine the complexity of the hash okay so you might remember that in the next off API route in the authorized function when we are going to compare the password with its hash form we don't need to specify the number of salr the number of salr is kind of hashed into the hashed password and when we are using the compare function of the bcrypt library it's going to extract the number of salt rant from the hash password so we don't need to specify and worry about the number of salt round when we are going to use the compare function of the B RP we just need to specify the number of salt round when we are going to Hash a password so now let's save this and I go back to the Prisma studio and let's just remove the user okay so I go back to the sign up form let's zoom out so now again let's add the user okay put my name here my email a phone number here A 1 2 3 4 5 6 password confirm that and click accept the terms it complains about the email so now fix that as you can see the user is registered so let's go back to the Prisma studio and although our password was 1 2 3 4 5 6 you can see now the password is hashed and then saved into our database so in this way with the help of the bigri library we can hash the pass password of the user before saving the user into our database okay so that's it for the register user server action it's not completed yet in the upcoming section of this video we will go back to this function and we're going to send an activation email to the email address of the user and send an activation link for activating the user account but now we are going to test the sign up form of the next app and try to sign in with the user that we have just created in our database [Music] but first let's go to the Apper component and add a signin Link in the nav bars so in order to do that let's create a separate component for the signin button and then put it in the nav bar so I go to the components directory and create a component and call it sign in button. TSX okay let's create a functional component here so in this component first we're going to check if the user is already signed in into our application we're going to show the name of the user and a sign out button and if the user is not signed in we're going to show a signin button so here first we need to determine whether the user is signed in or not so in order to do that we can use the use session hook that comes from the next off or we can use the get server session function that is also comes from the next off and since we are going to create this component dynamically we're going to use it as the client component and we're going to use the use session hook so first I'm going to mark it with the use client okay and then here inside the component we're going to use the use session hook so here I'm going to say const and extract the data and rename it to session for example and set it to use session hook that come from the next off/ react okay so the use session Hook is actually a react context that keep the session inside it and we can use it only inside the client components so as I said it's a react context under the hood so so in order to use that we need to wrap the children of the root lout with the session provider of the next out which is actually a context provider we haven't done that yet so we're going to do that in a second after creating this component so in the main div of the component we're going to say if this session is existed and session has a user inside it but remember that in the authorized function we return the user object and that user object will be kept inside the session. user so here I'm going to say if the session has the user inside it we're going to render a P tag here that contains the name of the user so here going to say session. user first name plus last name so as you can see the user inside the session doesn't have a first name or last name so we need to fix that type inside the user session we're going to do that in a minute but for now let's just put the user. email and then we're going to put a link here which comes from the next link and set its red to the slash API slash off and then slash sign out so this API request will be handled by the catch all route of the next off so as I said everything that start with the SL API and then slash off and then slash whatever will be handled by this API WRA that we have created in the beginning of this video and then let's put a caption inside the link sign out okay and here let's put a react fragment here to get rid of of this error and then if the user is not in the session it means that the user is not authenticated we're going to put a signin button so here I'm going to put another link here okay set its h2/ API slash off and then slash sign in you can also call the sign in function that comes from the next off or you can just call the API inside the link here and then with a caption inside the link I'll it the sign in and that will do the job for you and let's put some table and CSS classes here in the par div we're going to put them side by side so I use flex here item Center okay I'm going to use the Gap two for space between the children items okay and then here in the link we going to put some tail CIS classes text Sky 500 and on Hover let's set its color to text Sky 600 okay and let's put a transition color on this link and let's called the second link here let's turn it to a button the button component that comes from the next UI okay let import that and let's specify the app and pass the link component from the nextjs okay and it will act as a link here so now let's go back to the app bar component and now we can put the sign up andon instead of this sign up link that we have created earlier so let's remove that and put this sign in button here okay and let's just remove the second one and fix that just like this okay so now let's go back to the browser and here as you can see we have an error here and that's because the use session must be wrapped inside the session provider that was the error that I talked about it earlier in this section so we need to go to the root layout of our application actually we already have a providers component that is a client component so we just go to the providers here and here here let's just wrap all of them inside a session provider that comes from the next o okay let's put a parenthesis here okay so now let's go to the browser we have the signin button and we just remove the sign up so let's add the sign up button into our sign in button okay here if the user is not logged in here let's put a react fragment here and wrap the first button and just copy the first button here paste it here let's call it sign up up okay and just call the signning form that we have created so we're going to send it to the off and then sign off path okay so don't confuse this off path with the API SL off it is a page but it's a API route it doesn't start with the API these two are different directories it's in the API directory but this AR directory is in the Ruth pass of the app directory so now let's save this and get back to our browser okay we have the signing in and sign up let's click on the sign in here and you can see we have a really simple signin form that is Created from the next off you can see that the username and password here these labels these placeholder and input boxes are created from the credentials object that we have created in the rout tler of the next off so here as you can see we have the credentials object so for example let's change the username to username to okay and let's refresh the page you can see now the user is changed to the username too so let's fix that and keep in mind that we can change the labels and inputs of the next off signin page from this credentials object although we can have a completely custom signin page that we are going to create in the next section of this video so we don't need to worry about the labels and type of the input boxes in the credentials object in the credentials provider but if you're using the next o rebuilt signin form you can customize them inside the credentials object so let's refresh and now let's put our email it was Sakura de23 at gmail.com okay and put our password 1 2 3 4 5 6 and click on this sign in with credentials okay it gives us an error and here as you can see in the address bar you can see that it gives us an error you can grab it from the URL it says that username or password is not correct so let's go back to the Prisma Studio oh the email is Sakura 23 not Sakura D2 three okay so let's get back here and fix that okay with our password and here as you can see now we are signning into our application and the email of the user is now on the app bar so now let's try to put the name of the user instead of its email in the app [Music] bar so I go back to the vs code and in the signin button component you can see first we check if the user is inside the session object we're going to render the user. email so now if I open up the user object you can see it only has an email image and name but if I go to the Prisma schema here we can see that the user model has an ID first name last name password email verified and a phone other than the email and also you can see that the name is splitted into last name and first name but why inside the signin button the user has only email image and name that's because the next off use its own user type so in order to fix this problem we need to change the type of the user inside the next off so in order to do that I need to create a type file so here in the lip directory I'm going to create a file called types. D.S you can create a next off. D.S but I'm going to go ahead with the types. D.S the name of the file is really doesn't matter and here first we need to declare the module next off so I'm going to say declare module and then next off okay and then here inside it we're going to create an interface and name it session just pay attention to the spelling it will actually Define the shape of the next o session and here inside this session we have an user object and its type is going to be the type that is created by the Prisma client so let's import the user type from the at Prisma client but if you can't find the user from the Prisma client make sure to run a npx or Bon X Prisma generate it creates all the model types from the Prisma do schema file so let's get back to our next AR module here we are actually redefining the shape of this session we are saying that the type of the user inside this session is going to be the type user that comes directly from the Prisma client so now if I save this and go back to the signin button and now if I open up the user app object you can see we have all the types that we have defined in the Prisma schema so in order to render the name of the user we can have a back text here and then inside it we're going to have the session that user that name and then a space and then we're going render the session. user. lasting okay so now let's go back to browser to see if it is working or not as you can see it Returns the undefined and undefined because it's not enough to just redefine the type of the user inside this session we're going to handle this problem inside the catch all routes of the next off with the help of the next off [Music] callbox so I go back to the vs code and I go back to the next o catch all API routes and here in the a options we're going to create a callbox object so after the providers list here we're going to have a callbox so here we need to use two callbacks the jbt Callback and session callback but before defining these two callbacks let me show you what they are and when they are called so now let me explain the jbt and session call back in a diagram here when the user sign in into application successfully the jbt Callback is called and it receives an object that contains the token and user inside it the user object is the returning object of the authorized function in the credentials providers in the other providers like Google and GitHub the user is the returning object of these providers then the jbt call back returns the token and then the session call back is called and receives the token that jbt call back has returned and then the session call back return the next off session so these two call backs are called whenever user sign in into application or when we check the session of the next off in the client side but keep in mind that the user object is only available when the user signning into application for the first time after that whenever we check the session of the next off these two call back is called but the user object is on defined so the user object is only available when the user sign in into application so we need to check if the user is not undefined it means that the user is signing into application so in order to keep all the properties of the user object in this session of the next off we need to put the properties of the user object into the token and then send the token to the session callbacks so now let's go back to the vs code and do that in action okay we are in the off options of the next off catch all route and let's scroll down to the callox object here and let's first Define the JWT call back so here I'm going to say async JWT and it takes the token okay and also the user here we need to return the token from this jbt call back and now let's define the session call back async session it takes the token that comes from the jwbt Callback and then it takes the session okay and we need to return this session from this call back so the first time the user signing into our application the user object is available and after that every time we are accessing the session with use session hook or get session or get server session first the JWT call back is called but the user object is undefined this time Returns the token decision call back is called and the token that comes from the JWT callback as well as decision is received by decision and it Returns the session object actually the session that we've got from the use session hook get session or get server session function is this object that returns by the session callback so when the user signing into our application we need to put the user object into the token object and send it to the session call back here and here inside the session call back we need to get user object from the token object and put it inside this session so in this way in the sign in button we can access the user object inside the next off session so here first we need to check if the user is available if user it means that the jbt Callback is called upon the signing of the user we need to say that token that user as you can see the token doesn't have a user inside it we need to change the type of the token just like in the way we have changed the type of the session inside the next o here we're going to declare a module called Next off/ JWT and inside it we're going to Define an interface we call it JWT why JWT because it's the type of the token so here we going to say that it has an user inside it and its type is going to be user object that comes from the Prisma client okay so if I get back to the rap Handler of the next St and here you can see now the user is inside the token so we're going to set the token. user to the user object that we've got in the parameter okay and we have an error here and that's because the type of the user that we are receiving from the JWT call back is going to be a adapter user or user so we just need to set the user as the user type of the Prisma client okay and the error is gone and then we return the token and here in the session call back we receive this token and here we just need to say that session. user equals to token. user and let's save this and now let's go to the browser click on the sign in put our username here password okay let's sign in and now you can see that the name of the user is shown in the nav bar okay so now let's go to the signin button and here when we are reading the session from the use session let's log the session to see what's going on in the session object let's save this and let's open up the console okay here as you can see we have the session object it has a user inside it and you can see it has all the properties that we have defined in the Prisma schema file so yeah in this way we can modify the type of the user inside the next session and fill up the session with the user object that its type is compatible with our our Prisma client user type so yeah that's it for this section and in the next section we're going to create a custom signin page for our [Music] application okay so in the first step we need to create a page in the app directory so here in the app directory and then in the off directory side by side of the sign up directory I'm going to create another directory called sign in and then inside it we're going to create our page. TSX let's create a component here and I'm going to call it sign in page and then here first we are going to create a component a sign in form which we haven't created yet okay sign in form and then after that we're going to create a link here and let's import it from the next link and say for example forgot your password and then set its HF to SL off SL forgot pass we haven't created the forgot pass page yet we're going to create created it in the next section of this video but for now let's focus on our signin form component so I go to the components directory and now create a sign in for. TSX and then let's create a component here okay let's save this and get back to our signin page and now we can import the signin form okay so now let's get back to the signin form and work on this component so the first step is to create an interface for the props of this comp component it is going to have a call back URL which is going to be string and let's make it optional so we can set the call back URL to this component and when the user signing into our application successfully we can redirect the user to the Callback URL so I think we have a typo here let's fix that and we're good to go and let's have the props in the component okay and now we can create our form but before doing that let's first create the form schema with the for form validation so here I'm going to say const form schema and set it to z. object okay and here the first property inside this form is email I'm going to set it to z. string and then that email and let's put a error message here in case of input text inside it is not a valid email so we're going to say please enter a valid email address okay and then we're going to have the password set it to z. string and let's have a custom error message we're going to pass an object to this string function and here specify the required error okay and then here I'm going to say please enter your password okay so this is the form schema let's infert the input type from the form schema so here I'm going to say type input type and set it to z. infer and pass the type of the form schema so now we have the input type now we can use it inside the react hook form so inside the component let's use the react hook form so here I'm going to say const an empty object for now and set it to use form which comes from the react hook form and inside it Define the generic type which is going to be input type that we have inferred from the form schema and then here pass an object and specify the resolver to that resolver and then pass the form schema okay now we can extract the register function and handle submit from the use fir hook okay so now let's define the form in the jsx here let's turn the main div to a form elements and let's add some T in CSS classes flex and let's set the direction of the flex to column so I'm going to use the flex Coe and GAP two that's enough for now and then inside it we're going to create a input component that comes from the next UI okay let's define the label it is going to be username or let's set it to an email okay and let's register it in the hook form okay specify the email I think we have a tripo here so let's go back and here fix the email spell email let's save this and come back here okay and we should spread the register and put the email inside it okay and then we're going to have an error message and set it to error. email. message we didn't extract the error errors here from the use form so first we need to extract the form State and then from form State we're going to have the errors okay so now we can use the errors here that email that message okay copy the first input and paste it here for the password set the label to password and here register it with the password and also here set the error message to errors. password we need to set its type to a password but before doing that let me create a visible password button so here I'm going to define a show Pass State with use state so I'm going to say const show pass or let's name it visible visible pass and set visible pass set it to use State and initial value is file here inside the password input let's define the end content and let's render a button a plain button okay and then inside it first we check if the visible password is true it means that the password is showing so we need to render a I slash icon okay and let's set it's with to W4 okay and else if the visible password is false let's show a i icon Also let's set the class name to W4 for its width and here in the button on the unclick event of the button we're going to create a toggle function I'm say set visible pass take the pre and toggle the the prev prev value okay then we're going to have a button element after the password input we're going to have a button which comes from the next UI okay and let's set its type to submit and here for the caption we can render a signin caption here and also a loader when the user click on the sign in so first in order to know if the form is submitting here we can extract the a submitting from the form State and here here in the button elements we can set the disable to is submitting and then here inside button elements use conditional rendering here we're going to say if is submitting is true just render signing in with three dots okay and then if it's not true just render the sign in okay and the button from the next UI has the props for showing a loader inside the button and this is the is loading so here I'm going to set the E loading to the is submitting okay and let's also have a link component for sign up or registering a new user if the user haven't signed up yet so let's wrap it in a div element okay and let's set it class to flex and item Center also justify Center okay and here after the button we're going to have another button here and let's set the as component to a link which is come from the next link okay so actually the button is going to be a link but with the shape of a button and here I'm going to say sign up okay and here in the first sign in button we're going to have the color to primary okay and now we can go to the form elements and specify the unsubmit function so here I'm going to say unsubmit and call the handle submit that comes from the use for of the react hook form and pass our unsubmit function unsubmit so we haven't created the unsubmit function and now let's create it okay so here I'm going to say const on submit and set its type to submit Handler as you can see it comes from the react hook form and then we're going to specify the input type here in the generic type of the submit Handler so we're going to pass the input type here then we can set it to an arrow function here it is going to be an async and now we can Define the body of the unsubmit function so in this function we're going to call the sign in function that comes from the next off so here I'm going to say con result and set it to await and now we can call the sign in function that comes from the next off/ react so here we need to specify the provider that we are going to sign in with so I'm going to choose the credentials here and then we're going to pass an object and within that we're going to set the redirect to fils okay if we set it to true it will we direct the user to a call by URL that we can specify here but it will refresh the page but we don't want the page to be refreshed so we're going to set it to false here and then in order to redirect the user to the Callback URL we're going to use the use router hook and redirect the user manually in this function okay then we need to specify the username here we're going to set it to data the email and then we're going to specify the password and set it to dat data. password so here we have another options that is call back URL but we're not going to specify that here because we have set the redirect to false so we don't need to set it up okay and then we can check if the result is not okay you can show an error message to user so here I'm going to say if not result. okay we can send a toast to user and call the error function and pass the result. error message okay okay and then we can just return the function otherwise we can redirect the user to the Callback URL with the use rouer hook so we need to create an instance from the use router hook here in the component I'm going to say const router and set it to use rou hook okay and here as you can see we have a type for the props of the component and as you can see this props interface has a call back URL inside it so here at the end of this unsubmit function we can redirect the user with the router that we have just created and call the push function and here we can check if the props the call back Ur is existed we can pass it to the push function otherwise we can specify the address of our homepage okay so now let's go to the browser first we need to sign out here and then I click on the sign in as you can see again we are headed to the preview sign in page so in order to fix that I go back to vs code and I'm going to go to the catch all routes of the next off okay and here in the off options we can specify the pages okay and specify the signing and now we can put the address of our signning page so it is going to be on the slash off and then sign in okay put a comma here let's save this I go back to browser and let's go back to the homepage first refresh and now if I click on the sign in you can see it will head as to the signin page but we have an error here and that's because we are using hooks inside the react server component so I just go back to the sign in form and Mark it with the use client directive let's save that okay we've got another error and we have a link that we forgot to set its a so I get back to vs code and inside the sign in form here I scrol down you can see we have a button that we set it as link but we didn't find the EDF of the sign up button so here I'm going to specify the EDF to the slash off and then slash sign up okay let's save this and get back to browser now we are in the custom signin form so now let's get it back and make some changes in these Styles here to make it looks better first we need to remove this semicolon here in it's not in the signin form so I go to the signin page it's not in the signin page it's should be on the root layout so I'm going to go to the root layout of our application okay it's not there it might be on the providers component and yeah here we have a semicon let's remove that and as you can see the semic col is now removed I get back to designing form component and here on the form we need to specify some padding okay and let's put a border here and some rounded class let's go with rounded MD and let's put a shadow okay let's put a form caption here so I go to the form and before the first input we're going to specify a div here and we're going to set it to sign and for let's add some tail and CSS classes here we're going to set its background to gradient so I'm going to say BG gradient to B okay and specify the from white to slate 200 okay as you can see we have the sign in cap option here so this color is proper for the light theme so here we can say if we are on the Dark theme we can set the from Slate 700 to slate 900 okay so we have an conflict here let's specify the dark with the second color here okay get back here as you can see we have the form caption here let's put some padding inside it P2 okay now it looks better so in order to fill this area ask first we need to set the padding of the form to zero let's remove the padding and then let's create another div and wrap the contents of the form inside it okay I put it all the way down the form here and let's save this I go back here now we can put some padding here so I set the class name to P2 okay now as you can see we have a better form but here you can see the caption goes out from the rounded corner so get back to the form element and add overflow hidden class here okay now as you can see the form is in a better shape let's give a text Center to the caption here text Center okay get back here now it looks better we need to specify some space between the email and password so I set the flex here and flex cool for the direction of the Flex now we can specify a gap between the element inside the flex box okay I go to the this div here that contains these two button we need to put some Gap here as well Gap two for example and you can see now the form is lo better and also we need to put this forgot your password Link in the center of the screen so I get back to the PS code and go to the signning page and here on the pive let's specify the class name and set it to FL Flex items Center also justify Center okay and we need to set the flex direction to call so as you can see this is our sign up form we can also set the width of the signning form to W full here so I go to the sign in form and here in the form element we're going to set the W to full okay now as you can see it fills up all the withd of its parent container so now let's test the functionality of the custom sign form I'm going to put my email and specify the password so as you can see the type of the password input is not set to password so let's fix that I go to the password and here we need to specify the type of the password input we're going to set it conditionally we can check if the visible pass is true we're going to pass the text here to the type of the password input otherwise we're going to pass the password okay and as you can see we have a button here so let's set its type to this button in order to prevent the form from submitting okay now if I enter my password it doesn't show that and if I click on that you can see it toggles between the text input and password input so I put my email here and put my password here okay so first let me put a wrong password this is a wrong password if I click on the sign in you can see we have the error message and the toast component and the error message is this error message message inside the credentials provider in the O options of the next o r Handler so here as you can see in the authorized function as we set it up in the beginning of this video you can see that if the password was not correct we throw an error here and we put this error message inside that error so you can see the error is the same so when we click on the sign button here we call the UN submit function from the sign in form here and inside this unsubmit we call the sign in function that comes from the next off when we call this sign in function and specify the type of the provider as credentials it will actually pack this username and password and then call the authorized function inside the next off R tler and put the username password in this object in the parameter of the authorized function so in other words when we call the signing function from the next a with the credentials provider we are actually calling the authorized function from the credentials provider so now let's go back to the sign in for and put the right password here and click on the sign in as you can see we are headed to the homepage and now we are signing and you can see my name and the nav bar we can also send a welcome message to the user when the sign in is successful so let's get back to the signin for and here in the unsubmit function before pushing to the Callback URL we can toast a success message here so I'm going to put a toast here but this time I'll call the success function and with a welcome message here so I'm going to say welcome to Sakura Dev channel so if you have come to this point of this tutorial please subscribe to my channel and hit the like button okay let's save this and get back to the browser first let's sign out here and again put my email and put my password Here click on the sign in you can see the welcome message here on the screen and as a last thing in the custom signing page we need to catch the call back URL from the signin page and then pass it to the signin form component so now let's get back to the signin page here in order to access to the search Brams we need to Define an interface here I'm want to call it props just like a regular react component but here we're going to have a search prams and inside this search prams we're going to have a call back URL and it is optional and we're going to set it to string yeah okay and now here we can access to the props of the component so I'm going to set its type to props interface that we have just created okay and now we can extract these search proms here so now let's just lock the search proms in the signin page to see what's going on in the search proms I save this and here I go back to the browser and let's sign out first okay as you can see here we have the next off automatically puts the call back URL search prams in the URL and if I go back to the vs code and open up the terminal you can see now the search prams has a callback URL inside it and it is set to the homepage of our application it is okay and if I go back to browser click on the home and let's click on the sign in again now as you can see here we have two c URL and that is kind of conflicting it means that the next uh put the call back URL in the URL in two times so if I go back to the vs code and here you can see the Callback URL in the search BRS has the base URL and then it has another call back inside it so in order to fix that let's go to the signin button okay and here in the signin button instead of linking to the/ API sl/ signin which is handled by the catch all routes of the next off we can just call the sign in function of the next off so I remove this here okay and just on the unclick event of this button we're going to call the sign in function from the next off sign in okay and here we don't need to pass anything inside it the sign in function without any parameter it just send us to the signin page that we have specified in the next off rout Handler here in the pages object so it will actually redirect us to the/ off/ signning so if I save this and go go back to the home again okay and then if I click on the sign in you can see now we have one call back URL in the URL and if I go back to the vs code here you can see the Callback URL is now without any extra callback URL search Bram inside it so now we can catch this call by URL from the search Brams in the signin page and we can pass it to the siging form so here as you can see we have a callback URL props and let's set it to to search prms the call back Ur and if I go back to the signning form you can see here in the props of the component we take this callback URL and if the signin process was successful we send the user to the props do callback URL so now let's go back to vs code here let's go to the homepage click on the sign in let's put my email okay my password and click on the signning you can see now automatically we've been sent to the homepage okay later in this video when we create other pages in this application you will see that when we click on the signing the call back URL will be set to the address of the current page okay that's it for the custom signin page but before moving to the next section let me show you that we have a bug here so let's fix that if I click on this homepage you can see the page will be refreshed so I go to the Apper component okay and here you can see we have a link here that is sent us to the homepage but the type of this link component is not from the next link it's a link that comes from the NEX UI which is actually a anchor tag so let's remove the link here and let's import it from the next link okay and we don't need the color okay and if I save this now if I click on the home you can see the page doesn't refresh but the default style of the link component is now now gone so we need to manually put some T and CSS classes in the next link component here I specify the class name here and set the hover studo class and say when hover set the text color to Sky 500 okay and then add a transition class to the colors of this link component so now we can see that the link has some style inside okay that's it for the custom signing page and in the next section of this tutorial we're going to go back to to the signup form which is actually for registering a new user and upon saving a new user into our database we're going to send a activation account email to the email address of the user with a activation link inside it so the user can click on that link and activate its account on our application so don't go anywhere we're going to learn something new in this section let's get into [Music] it so here I'm in this sign up form and here as you can see on the submit Handler of the form we call the register user server action so actually we don't need to do anything in the sign up form we just go to the register user server action and here after inserting the new user into our database we need to send an activation email to the email address of the user so now in this section in the first step our goal is to create a function for sending email to users so in order to send email to users in nexs or any other nodejs project we can use node mailer so I open up the terminal and here we can install it with BN at node mailer again you can install it with npmi node mailer and since we are using typescript here we need to install the types of the node mailer so let's clear this up first and here I'm going to say BN at dasd because it say Dev dependency and then at types SL node Miller okay now we can use node Miller in our next application so here in the LI directory first I'm going to create another file called mail. TS okay so in this file we're going to create the functions that are related to mailing so now let's create a function called sand mail so here I'm going to say export async function sound mail okay and then here we're going to take an object here and first let's Define the shape of the object so we're going to define a type for it it is going to have a tube property which is actually is the email address of the recipient so we're going to set it to a string and then we're going to have a subject which is actually the subject of the email so again we're going to set its type to string and as a last property we need to define a buddy which is actually the body of the email again we're going to set its type to string okay and now we can extract ex ract the properties of this object so we're going to extract two subject and also body from the object parameter and now we can Define the body of the function okay so this is our send mail function we need to specify the email address of the recipient the subject and also the body of the email and in this function we're going to use node mailer to send an email but before doing that we need to set up a SMTP server we can do this in two ways either we can set up a SMTP server with our Gmail account or we can set it up with a third party Services there are lots of these services to set up a SMTP server first we are going to set up a SMTP server with my Gmail account and then I'm going to show you how we can create a SMTP server with other thirdparty services so as I said now let's create our SMTP server with my Gmail account and in order to do that I go to my Gmail account and here I go to to my account okay and click on the security Tab and here make sure that you have enabled the twostep verification because if you don't make it enable you can't set up your SMTP I click on the twostep verification and here I scroll down to the bottom of the page and click on the app password Here I choose the name for my app I want to go with the Sakura Dev off tutorial okay and then I click on the create here in and here you need to copy your password Here make sure you copy that because if you click on the done here you cannot see your password again okay and then I go back to the vs code and here I go to the EnV file and let's create a section here I'm going to call it email setting okay and then here I'm going to create an SMTP email and set it to my Gmail account so I'm going to use my Gmail account okay and then I'm going to create another variable called SMTP Gmail pass okay and then set it to the password that I've got from my Google account okay let's save this and now we can go to the mail. TS file and our sand mail function okay so first we need to extract the variables from the EnV file here I'm going to say const and then an object here and then set it to process. EnV okay now we can extract them here from process that EnV now let's save this okay and now we are going to create a transport so here I'm going to say con transport and set it to node mailer do create transport so first let me import the node mailer here okay so now we can use that no mailer do create a transport and now we should pass an object here first we need to define the service which is going to be Gmail okay and then we're going to put the a object here and then then within that we should specify the user and set it to SMTP email EnV variable that we've got here and then we're going to specify the pass and set it to SMTP Gmail pass okay that's it we have created our transport so now we are going to test this transport okay so here I'm going to put a TR cat block here in the try section I'm going to say con test result and set it to wait transport. verify okay and now we can log the test result here here I'm going to log it into the console okay here I'm put a key here test result of Transport okay and now we're going to put our test result here and in case of any error we can catch the error and just log the error into our console okay so let's save this for now and let's go to the homepage of our application and test this send mail function so here I go to the homepage here and here as you can see it's an Asing function so here I just want to call the sound mail function I going to say await sound mail okay and then the parameter object and here specify the2 for example let's just specify the same email for the recipient okay and put the subject here I'm going to set it to test and put the buddy I'm going to set it to just hello world okay so now let's go to our browser okay let's refresh the page and let's go back to our vs code open up the console here as you can see we have the test result of the transport and the value is true it means that our node Miller transport is connecting to our Gmail SMTP server without any ER so now let's go back to the send mail function and actually send the mail here so here just like testing I'm going to put another try catch block okay and then here in the try block I'm going to say const this time soon s result and set it to await transport. sand mail okay and here we should pass an object here first specify the from okay and set it to SMTP email that actually are em variable and then specify the two which is going to be the two parameter specify the subject we are getting that from the parameter of the function then we're going to specify the HTML here and send it to the body parameter okay and just like the testing we're going to lock the result to the console so here I'm going to say send result and in the catch section just in case of any error going to catch the error and just log it to the console okay so now let's get back to our homepage we are going to send an email to our email address the subject is test the body is hello word so let's get back to our browser just refresh the page okay get back to vs code open up the console as you can see here oh we just conso the sand mail we need to clog the send result oops that was a mistake now as you can see on the console of the server you can see that we have the S result object without any error it means that the email is sent without any problem and now let's go to my browser and I go to my inbox you can see we have already two email that this subject is test and The Bu is just hello word okay so as you can see the sender and the receiver of the email is the same for the Simplicity we didn't use two different email address but you can just send email to any email address that you want we just need to change the two parameter here to your desired email address so that's it for sending an email with the Gmail SMTP server and now we are going to set up a SMTP server server with a third party SMTP [Music] server okay so in this section we're going to set up a SMTP server with a third party service so one of the services that I want to use here is the mail trap it gives us an email testing endpoint as well as a real email sending endpoint so here I just logged in with my Google account click here on my username as I said you can set up a email testing it's a kind of fake SMTP server and here we can have real SMTP server so if you want to use the real SMTP server you should have a email address other than free email account like Gmail you should have your own email address that is belong to your company's domain so in this tutorial let's create a fake SMTP server it just simulate the real email sending process but it's just not real but the process process is the same so here I click on the start testing okay and let's add a project for a project name I'm going to go ahead with the sakra dev off tutorial Okay click on the ad and here I'm going to create an inbox okay just a name here I'm going to go ahead with the inbox as the name just keep it simple and here if I click on the setting here I can use the username and password for our SMTP trans Port so here in the integration section I'm going to choose the nodejs and node Miller okay just create transport with the credentials inside it I just copy that okay and then I get back to my send email function and here I just comment the first transport that works with Gmail API and then here I just paste the code that I've got from the mail trap you can see we have the username and password so for the safety purposes let's move these values to our EnV file I'm going to create a variable for SMTP user yeah okay and set it to value that we have here let's copy that put it here again I'm going to create SMTP just pass okay so the Gmail pass is SMTP Gmail pass but the mail trap path just SMTP pass so let's go and copy the password here and put it here okay so I go back to the mail. TS file and in the send function here we're going to extract the SMTP user here and also s MTP pass okay from the process. EnV file so here just replace the user with the SM SMTP user okay and replace the pass with the SMTP pass okay and the rest is the same so let's save this and go back to our browser and here let's refresh okay and go go to the mail trap and you click on the inbox you can see we have already two email and the body of the email is hello word and the sender is Sakura de Tri so yeah in this way we can create a s MTP server with a third party service in the next subsection of this tutorial I'm going to create a HTML template for the body of our email and then dynamically put the name of the user and the activation link inside that HTML body of the email so let's do [Music] that okay in the first step we need to find a service that offers free HTML templates for the email one of the nice and easy ones that I have found is the B free.io so here I go to the B free.io and log in with my email account and here I'm going to click on the create new and choose the create create new email here and here you can choose a template from the available templates or we can create a blank template and design your own HTML so here in the categories I'm going to choose the activation and here I just choose this one okay click on the start designing okay and here we can change the content in the way we want so here for example let's say welcome to my course okay my authentication course okay and here let's just duplicate that so here I'm going to say I and then here we want to dynamically put the name of the user we're going to put something like a variable in order to do that I'm going to put two col braces here okay and then inside it we're going to put our variable for example I'm going to call it name so this name inside two col braces would be something like a variable or parameter for this template and and later on in our project we can initialize this parameter or variable so this is a kind of activation account for example let's say here please activate your account with the link below okay and here let's change the caption of this link I'm going to set it to activate your account okay and here as you can see we have a url url here so let's remove that and let me make it a little bigger to see it better and here just like the name variable that we have put here we're going to put two color braces and then put the name of our variable so here I'm going to just go ahead with the URL this email template has two parameter or variable that we can initialize when we are going to send email the name and URL so now let's finish our design I'm going to click on the exit here and here I'm going to click on the export and just copy the HTML okay so I copy the HTML code and I go back to the vs code and here in the lip directory I'm going to create another directory called email templates okay and then inside it we're going to create the activation. TS okay and here we're going to export a string constant so I'm going to say export const activation template and then set it to a back text here and then put our HTML template that we have just copied okay so as you can see the HTML code is now here and if I find the name variable you can see here we have the name in two col braces and also let's find the url variable okay you can see the URL variable inside two color braces is here okay now we need a tool for initializing these variables in our HTML template this tool is hand handle [Music] bars so handlebars is kind of like a template engine that can compile and render HTML templates and initialize the variable inside them okay so with that in mind let's install The Handlebar so I open up the terminal and here I'm going to say B add handlebars okay so let's close this off and I go to the mail. TS file and here I'm going to create an export function let's name it comp pile activation template okay it is going to take the name which is going to be string and URL which is going to be string as well and then here first we're going to create a template con template and set it to handlebars which comes from the handlebars package okay and then call the compile function and here we need to pass the activation template that we have created in the activation. TS file so here I'm going to put the activation template that comes from the activation. TS file okay now this template is a function that we can call them and pass the value of our variables and get back a rendered HTML and have our variable initialize in that so here I'm going to say const HTML body okay this is going to be our final HTML body of our email and set it to template and then pass an object and ided we're going to specify the name which is going to be name parameter and then we're going to specify the URL which is going to be our URL okay and then we just need to return the HTML body okay we're good to go now we can compile the HTML body and we have the send mail function so I go to the off server actions file and inside the register user after inserting a user with Prisma into our database first we're going to create our but body HTML with compile activation template so here I'm going to say const body and set it to compile activation template which is pass the first name so remember this user is the user object that here we have inserted into our database and then for the URL we need to create a dynamic route that takes the ID of the user so here in the app directory I'm going to go to the off directory here and create create a activation page I'm going to say activation okay and then it is going to have an ID inside it is going to be ID of the user it is not safe to put the ID in the activation link we're going to fix that in the next section but for now let's keep it simple and see how we can handle this and then we're going to create our page. TSX file we're going to create a component here we're going to name it activation page we're going to create the interface for the props okay it is going to have a prams and inside that prams we're going to have the ID which is going to be string okay and here let's just grab the prms object from the props and here let's just render the prams doid okay that simple just for now I go back to the off actions and here we're going to specify the ID something like this we're going to use the back text here or we can just create a variable for URL here so I'm going to say const activation URL we're going to set it to process that EnV that next URL because it will be the base URL of our application whether we are in the production or development server so we're going to set it in the EM file in a second but for now let's put the activation URL here let's put it inside a back text and here use the templates okay and here after the Bas URL we're going to put the Slash and then off and then activation it's the page that we have just created then we're going to put the ID of the user again it is not safe to put the ID of the user directly in the activation link I'm going to fix that in the next section so for now just put the result the ID so the result actually is the returning user object that is come from the Prisma that user. create function it is the user object we its ID inside our database okay so that's it for the activation link and then we can put the activation link in the compile activation template but before moving forward and forgetting this here let's just first copy the next URL here and go to the EnV file and create our next off URL and set it to Local Host 3000 for now because it's the Base address of our application so let's put it a HTTP here and and later in the production environment we're going to change the url to the actual web address of our application okay so let's save this and go back to our register user function so here we have the body of our email and now we can just call the send mail function so here I'm going just say await send mail and put the two to the user. email and Define the subject as something like this activate your account okay and then put the body here with this body HTML that we have created with the compile activation template and interplate user. first and activation URL inside it okay and then we can just return the result from this server action so now let's go back to our application and click on this sign up here and let's zoom out and here let's just create another user okay for example Sakura and here let's put the email Sakura Dev 23@gmail.com it will gives us an error obviously because the email address should be unique inside our database so let's just first remove the previous user from our database so I'm going to use the Prisma Studio here b x Prisma Studio okay here we just remove the user from our database and here now we can put the email of the user okay put the phone here a password just 1 2 3 4 5 6 Rel weak password confirm that accept term click on the submit so as you can see the user registered successfully okay so get back here into the terminal you can see the email has been sent so I go to the mail trap here you can see we have a email so let's open that you can see temp plate the name of the user here and also we have the activate your account so if I click on that we are go aheed to our page here and this is the ID of the user inside our activation page so we have the ID of the user and now in this page we can get this ID and update the user inside our database but before doing that let me emphasis that it is not safe to put the user ID directly in the activation link for the safety sake we need to kind of encrypt this ID of the user and then put the encrypted version of the ID inside our activation URL so in order to do that we're going to use the Json web token or JWT to actually encrypt the ID of the user and then put the encrypted ID in the activation [Music] link so let's go and install the Json web token going use B ad Json web token okay and then we're going to need to install the types of the Json web token so here I'm going to say B add and then slash d add types slash Json web token okay so let's close this off and then I go to the lib directory and here I'm going to create a JWT TTS file the TS okay so in this file we're going to create two functions one for signing JWT and the other for verifying and retrieving the data from a JWT so first I'm going to export a function for signing a jbt I'm going to say export function and let's call it sign jbt okay and here we're going to need two parameter here the first one is going to be payload which its type is going to be jbt payload the ad comes from the Json web token and we're going to have a signning option which determines the expires time of the jbt and then we need to have an option object that contains the expire time of our jbt so first we need to create an interface for the option so here I'm going to say sign option okay and let's have a expires in which is going to be a string or a number and then let's create a default sign option so I'm going to say con default sign sign option and set its type to sign option interface that we have just created and let's set it to an object specify the expires in and set it to just one day so our JWT is valid for just one day okay so here I get back to the sign JWT function and let's have an option parameter and set its type to sign option and let's set its default value to the default sign option that we have just just created inside it first we need a secret key so here I'm going to say const secret key and let's get it from the process. env. JWT user ID secret okay so let's create this variable inside our EnV file let's put it here and let's create a random key with open SSL so if you're on a Linux machine you can use open SSL and then Rand Das base 64 and then put the length of your key for example let's say 32 okay so here it create a key with length of 32 for us okay so if you're not on a Linux machine and op SSL is not installed on your machine you can just go with a random key so let's paste it here okay and let's go back to our sign jbt function and now that we have the secret key we can create create the token so here I'm going to say const token and set it to JWT that comes from the Json web token first let's import the jbt here okay and we can say jbt do sign and pass the payload and also the secret key okay so the secret key might be undefined here let's put a exclamation mark here to emphasiz that it is not going to be undefined okay and now we can return the token okay this is the sign jwbt and now we are going to create another function for verifying and decoding the jwbt so here I'm going to export another function called verify jwbt it is going to take a token which is going to be a string and here we're going to first get the key from our EnV file okay so I copied that from the previous function and here I'm going to say const decoded equals to JWT package. verify pass the token inside it okay and put the secret key okay so we need to put the whole thing to a try catch block because if the secret key is not valid or the token has been expired it will throw an error so here we need to catch that error okay first log the error let's get the error here in the catch okay let's call it e and then here log the E which is error and then just return null returning null from this function means that the token was not valid and here if the error is not occur which means that the token was valid we can return the decoded as and convert it to JWT payload okay so here we are signing a jwbt or encrypt our payload with the secret key here and then here we can verify and decode that token with this secret key so don't forget to put this secret key in your EnV file and just keep it secret okay so now let's go back to the a server action and here in the activation URL first we need to create a JWT with the user. ID so here I'm going to say const JWT user ID okay and set it to sign JWT that comes from the .ts file and just pass the user. ID which is result. ID okay and here let's put a object here let's specify an ID and then set it to result. ID which is the ID of the inserted user into our database okay and here instead of putting the plain user ID in the activation link we're going to put the jwbt user ID okay so now let's test it but before doing that let's remove the user from our database okay I run the Prisma Studio here just remove the user okay and here let's click on the sign up and let's quickly fill first name last name put the email the phone password so this is now your valid phone let's add some number okay now the user inserted to our database so I go to the mail trap here and you can see we have another email okay I open it and click on the activate your account and as you can see now we have the JWT token instead of the user ID in the activation page so in this page we need to First decode the jbt and then update the user in our database and set its email verify to True okay so let's go to the activation page in the app directory and then off directory we have here the activation so let's rename the ID here to JWT okay it is not necessary but let's just do that okay we have the activation and then the dynamic route is the JWT so I go to the page inside that and here let's change the ID to jbt okay and here let's change this as well so first let's set the activation page to a async function okay and now here we need to create another server action for activate the user and then we can call that activate user here and pass the JWT So This Server action takes the JWT decodes that and then activate the user inside our database and just return a proper message and then we can show a proper message based on the result of the activation function to the user in this page now let's create the activate user server action so now let's go to the off actions and Define the activate user server action so first let me create a type for this function so here I'm going to say type activate user fun for example so let's say it is going to be a function that takes the JWT user ID which is going to be a string and it returns a promise of a string which is going to be either user not exist or already activated okay or success so this is the type of the activate user function it is going to be an async one that's because we use promise here which returns a string that is either user not exist already activated or success so let's fix the typo here and we're good to go now I'm going to create the actual activate user function here I'm going to say export const activate user and let's set its type to activate user Funk now we can set it to a async function okay here we're going to have the JWT user ID we don't need to specify the type of this parameter because we have declared that here in the activate user function and now let's define the body of this function you can see we have an error here and that's because it needs to have a return value of this type here so when we return that the error will be gone so first we need to extract the payload from the JWT here I'm going to say const payload and set it to verify my JWT function that we have created in the JWT file okay and pass the JWT user ID it is actually the jbt that we will get from the activation page URL and since the payload is going to be an object that contains ID so if I go to the register user function you can see that here when we are going to create a jbt we're going to create an object and then inside that we're going to put the ID of the user so the decoded payload will be an object like this so here we can extract the user ID just like this I'm want to say const user ID and then set it to payload which is going to be payload do ID so now we can find the user in our database first we're going to say const user and set it to await Prisma let's use our Global Prisma client that comes from the ellip Prisma dots file so let's set it to weight using our Global Prisma client okay and user and then find unic okay here we're going to find the user based on its ID we're going to specify the we API and here specify the ID and set it to user ID okay so first we need to check if the user is not existed we need to return a proper message so here I'm going to say if not user which means the user is undefined we just return user not exist so as you can see we have a aut completion for returning value and that's because we have created a type for this function this is the beauty of the typescript okay so let's move on and now we're going to check if the user. email verified field is not undefined which means that it doesn't have a null value we can return already activated so if the email verifi field has a value it means that the user already activated its account okay so if now of these two condition is not the case we can update the email verified field inside our user table in the database so here we're going to use the Prisma for updating the user we're going to say const result and set it to await and then use the Prisma again our Global Prisma client user. update okay and then pass the object first specify a wear API to say which user we want to update okay in the we API we're going to specify the ID and send it to user ID okay and then we're going to specify the data object in which we're going to determine the field that we are going to update so here we're going to update the email verified it's a datetime fi and we're going to set it to the daytime in which user activate its account so here we're going to set it to a new date okay this will be the daytime of the user activation okay we're done with the update function and after that we just return the success okay so this is going to be activate user function or so to call server action okay so now let's get back to the activation page and here let's call the activate user function so I'm going to say const result and set it to await and call the activate user function from the off actions and then pass the prams J okay okay so now inside the main div of the page instead of showing the jbt we're going to render a proper message so first let me put some tail when CSS classes here let's set the height to the edge screen actually we are setting the height of this page the height of screen and let's use flex Flex cool and in order to put the items in the center we're going to set items Center and justify Center okay so inside that for first we're going to check if the result is user not exist and check that result equals to user not exist okay we're going to render a P tag and inside that we're going to say the user does not exist okay and otherwise we're going to check if the result equals to already activated again we're going to put the ternary operator here and if the result is already activated we're going to render a P tag again and and you can say the user is already activated and let's put some tail and CSS classes here let's set the text color to Red 500 okay and let's set the font size to a big one for example text 2 XL so let's put this class name in the first P tag and then we can check if the result equals to success we can we can again render a P tag and here let's say success the user is now activated and let's set the class name here just change the text color to Green 500 and the font size will be 2 XL and if none of these condition is the case we can just return a P tag again and say for example oops something went wrong okay and let's put the lcss classes here and just change the text color to Yellow 500 okay I saved that and now we can test it in our browser okay so let's go to the browser and here in the Prisma Studio you can see that we have a user here but the email verified is null so I go to the mail trap here and here click on the activate your account link in the email so here as you can see it says that success the user is now activated so if I get back to the Prisma Studio here and just refresh the page you can see that now email verified as a daytime values which actually is the daytime of the user Activation so now let's close the activation page and for second time let's click on the activate your account in our email you can see that the user is already activated message in activation page okay so that's it for the activation page but one thing we should do here is to go to the rout hler of the next off and here in the authorized function of the credentials provider we can add a condition to check if the user has not activated its account we're going to send a proper message to user so here after the last condition we check the correctness of the password we can check if user. email verified doesn't have a value so I put a exclamation mark before that we can throw an error here just like this and just change the message to please verify your email first okay let's save this and let's go to the browser here in the Prisma Studio let's put a null value inside our email verified and then save the changes okay now it means that the user has not activated its account so let's go back to our application and click on the signing here I put my email and put my password okay let's click on the sign in you can see it returns an error message which says please verify your email first so in this way in the authorized function we're going to check if the user has not verified its email we're going to send a proper message to user so yeah that's it for the user activation functionality in our application and in the next section we're going to implement the forgot user password and password reset functionalities in our [Music] application for reset password functionality we actually need two pages the first one is forgot password and the second is reset password in the forgot password user submits his or her email and then we check if such email is existed in our database we send an email to the user's email which contains a reset password link this is actually a link to the reset password page we extract the JWT inside the reset password Link in the reset password page from the URL and then verify if it's valid we're going to show a reset password for to user Us in which he or she can reset the password so in this section first we're going to create the forgot password page so in order to do that I go to the app directory and then in the off directory I'm going to create a directory called forgot password and then inside it we're going to create our page. TSX okay let's create a react component here I'm going to name it forgot password page okay so in this page we're going to create a single field form which only contains the email field inside it so first we're going to create a form schema with Z okay I'm going to say const form schema and set it to z. object okay it is going to have an email inside it which is going to be a string and then change the email function and let's put a error message in case of any error so here I'm going to say please enter a valid email okay this is our form schema very simple and now we need to infer the input type from the form schema so here I'm going to say type input type and set it to z. infer and pass the type of form schema as the generic types here okay so now we're going to go to our components and set up the reactor form so here I'm going to say const now an empty object set it to use for pass the input type as generic okay and then here pass an object into the use for and specify the resolver with the Zod resolver okay and then pass the form schema to the zot resolver okay so this is for our form validation and here from the use form we're going to extract the register and handle submit okay and also reset function then I go to the jsx of the page and we're going to create our form inside the main div we're going to split the page into two grid so I use the grid here and also grid equs one and I'm medium screens and above that we're going to use three columns create code three we're going to dedicate one column to our form and two columns to a image for the beauty of our form so here let's define our form okay and inside it first we're going to put a input element which is coming from the nexi okay and then specify a label which is going to be email and then spread the register function it only has email inside it okay and then we I'm going to use start content here for sending a email icon so I'm going to use envelop icon which comes from the hero icons and put a class name here W4 for its width so let's save this to break it into multiple lines and then we're going to pass a error message here and let's set it to errors. email. message but first we need to extract it from the use form so first I'm going to extract the form State and from form State we're going to get the errors okay let's get get back to our input element and here we're going to send errors that email that message okay so I think that's it for the input and now we're going to create our button element for submitting first from the form State here in the use for let's extract the E submitting okay and let's get back here and after the input element we're going to render a button okay so here I'm going to set the ease loading to ease submitting that comes from the use form and we're going to use the disabled if the form is submitting okay and then here in the content we're going to conditionally render if his submitting is true we're going to render please wait okay and otherwise we're going to render just a submit text okay and here in the bottom let's set its color to primary so this is our form and here in the unsubmit here we're going to use the handle submits and then pass a function for example on submit or let's call it submit request okay so we haven't created this submit request function we're going to create it in a minute but for now let's put our image elements into our form but before doing that let's set the type of this button to submit okay save this and here after the form we're going to use an image so I use the image of the next image okay and we're going to set the SRC which is a picture from our public directory here forgot pass okay forgot pass I've already put that inside the public directory so slash means public directory forgot pass that JP okay and then we need to specify the width we're going to set it to 500 and also the height to 500 okay and then put a class name here we're going to set the cool span to two because we wanted to take two columns of our grid layout and also we're going to put a alt props here after the SRC we're going to set the alt and set it to for example forgot password let's save this and we have a error here and that's because we haven't created the submit request yet so now let's define this function I'm going to say const submit request and set its type to submit Handler which comes from the react hook form and pass the input type now we can create our function it's is going to be an async one and it takes the data which its type is input type and then we're going to define the body of this function so now we need to create a server action for example forgot password and then send the email of the user into this server action but before doing that let's just log the data and then test our form so here I put the data here and also we need to mark this page with use client because we are using the hooks here let's save this and keep in mind that the client components are not that bad that you might think okay so before going to the browser and see the result let's go to the signin page and here you can see we have a link and it's ETF is set to off and forgot pass so let's change it to password okay and let's save this okay so I go to the browser and click on the sign in and then click on the forgot password as you can see we have the form here background of the image is not transparent so let's go back to our forgot password firm and change it to forgot pass. PNG okay as you can see now the background are transparent so here as you can see this is our form we need to put some Gap here okay so in the form let's put a class name here and we're going to set it to flex and flex cool and then put a gap of two okay and then a padding P2 and also we need to add a border and a rounded MD for Border radius and and also a shadow okay so let's save this and let's put a items start let's save this and now the form is in a better shape let's add a form header inside it here in the form I want to put a div here it says enter your email okay and let's set a text Center for this div and also a P2 okay let's save this now this is better let's put some margin into the form okay M2 and now think it is better okay and now let's just change the item start to item Center to put the form in the center of our page and let's just put the image on the center so here in the image element and it's class name let's say Place self cender okay let's save this and now this looking better okay so now let's write the forgot password saver [Music] action so I go back to to vs code and here in the submit request function instead of just logging the data we need to call the forgot password server action and then pass the data. email to it so I go to the off actions in the lip directory okay and here we're going to create a forgot password function or so to call S action I'm going to say export async function and I'm going to call it forgot password and then it is going to take an email just going going to be a string okay and here first we need to check if such user with this email is existed in our database or not so we're going to do that with Prisma I'm going to say const user set to await Prisma user find unique and then here specify the where and set the email to email parameter okay and then here we're going to check if the user is not existed so if not user we're going to throw an error here throw new error with a custom message for example the user does not exist okay and then here we're going to send the email so here I'm going to put a to-do comment here send email with password reset link so in order to send an email we have already set up a send mail function but first we need to create a template for the reset password email so to create the template I go to the B free doio and just click on the last email that we have created open up the template and here just change the message here okay we've send this email because you have forgotten your password okay and then here let's change the message please or you can reset your password your password through the link below okay and change the caption of this link for example let's say reset your password and then change the url to let's make it a little bigger okay so actually let's don't change the url parameter here let's keep it URL and we have to set the name and URL in this email template we just change the message inside the template so we have a typo here let's fix that okay and let's save this and now we can copy the template so here I'm going export and copy the HTM M okay and get back to the vs code and I go to the email template and here I'm going to create another file called for example reset pass. TS okay and here I just export a string so I'm going to say export con and let's call it reset password template and set it to a back text here and just put the email HTML that we've got from the template so let's close this off and here I go to the mail that that TS you can see we have a compile activation template so just rename it to compile template for example let's remove the activation template it will rename this functions across all the project we don't need to worry about that now it's a generate compile function and I go back to the off actions here and here first we need to create a reset password link I'm going to use the JWT for creating a reset password say const JWT user ID first okay and set it to sign JWT function which comes from the JWT TTS file and then pass an object here which contains the ID which is going to be user. ID so remember that we retrieve the user here from the Prisma based on its email okay so now we encrypt the user ID we can create the reset password URL so here I'm going to say const reset pass URL and set it to back text here I'm going to use process. env. next off URL and then slash off slash reset pass and then put the jbt user ID okay so this is our reset pass URL we need to create this page reset pass we're going to create it in the next subsection but for now let's compile the HTML template of the email I'm going to say const body is going to be the body of our email and call the compile template pass the name as the user.name for example first name and then put the reset pass URL okay so this will compile the template with the custom name and custom URL you know what we can't use this compile template function because it uses a activation email template so here if I go to the mail. TS you can see here it is going to have the activation template so either we can create an another function or we can have a third parameter here that determines the template so we don't want to do that we just create another function here so first let's change it back to compile activation template okay I stand corrected and change it back to compile activation template okay and then we're going to create another function and let's name it compile reset pass template so here we can pass the reset password template template okay and I go to the off actions and here instead of calling the compile activation template we're going to call the reset pass template so now we have the body of our email we can send the email with the sand mail function I'm going to say con send result and set it to await send mail function and pass the object here it's specify to to user. email okay and is subject to reset password and Buddy to the buddy that we've got from the compile reset pass template okay we have a typo here so let's fix that okay and then here we can return the sound result so let's save this and now let's just remove the to-do here and then go back to the forgot password page and instead of logging the data we can call the forgot password server action here so let's remove move that and here I'm going to use a try catch block okay so I get back to the try section and I'm going to say const result and set it to await call the forgot password function from off actions and then pass the data. email and then here we can check if the result is not undefined you can use toast to send a success message to user okay and here we can say the reset password link was sent to your email and then call the reset function from the react hook form which actually reset the form fields and here in the catch section we can take the error as e and then just log the error first okay and then use a toast that error to show error message to user for example let's say something went wrong okay so that's it for the form and now we can test it in the browser so let's go to the browser and here I paste my email and and let's send it so it says that the recent password link was sent to my email so I go to the mail trap here and here click on the reset password email and this is the reset password email and if I click on the link here you can see it sent me to the SL offret path and then the JWT so now we need to create the/ offret path so I go back to the vs code and here in the off directory I'm going to create a reset pass and then inside it we're going to create a dynamic route let's call it JWT okay and then inside it let's create the page. TSX okay so here let's create a react component and let's call it reset password page okay let's create an interface for the props I'm going to call it props it is going to have a prms and inside it we're going to have a JWT which is going to be string okay now we can access to the prems here and set its type to props interface that we have created here we have a typo so let's fix that and here we can create a form for password reset so let's create a separate component for the form here I'm going to go to the components directory and create a new component let's call it reset password for the TSX and here let's create a component and then let's create an interface for the props okay is going to have a jwbt user ID which is going to be a string here we're going to access to the jbt user ID let's extract it from the props and set the type of the props to props interface that we have just created so here let's return a form and inside it we're going to create two input password and then a submit button so before doing that let's create a form schema here with Z so I'm going to say con form schema and let's import the Z first and set it to z. object okay we're going to have a password which is going to be a z. string okay let's change the mean function and set mean length to six and put the error message for that password must be at least six characters okay and then change the max function and put 52 for its max length and let's save this to break it to next line and put a error message here say password must be less than 52 characters okay and then we're going to have a confirm password which is going to be Z that that string so we don't need to change the mean and Max function but instead we are going to change the refine function with the z. object the whole object and here we're going to pass a call back which takes the data so the data contains the password and confirm password and here we're going to return true if the data. password equals to data. confirm password okay otherwise we're going to set a error so here I'm going to put an object and specif ify the error message and here let's say password doesn't match and we're going to put it on the confirm password okay and here let's infer the input type and set it to z. infer and pass the type of the form schema and now we can go to our component and set up the react hook form with this form schema and input type okay so I go to the component and here let's set up the use for I'm going to say const and an empty object and set it to use for pass the input type and inside the use for we're going to pass an object and here specify the resolver and set it to Z resolver and then here pass the form schema okay so now we can extract the register and handle submit reset function and form State and inside the form State we're going to extract the errors and is submitting okay let's save this and let's go to the form and and create the input elements so we need to create two elements here the first one is going to be password so the input comes from the next UI so label for it set it to password and spread the register function okay and register with the password and put the error message here to the errors. password. message okay we also need to set the type to password but we need to set it conditionally based on the state visible pass password we're going to do that in a second but now let's create the other input for the confirm password so here I paste it here and set the label to confirm password and register it with the confirm password and update the error message here set it to error. confirm password. message okay so now let's go to the sign in for and copy the code for the show password here first we need to create a visible Pass State so let's copy that and I go to the reset password for paste the state here okay and let's import the use State okay and get back to the sign in for and here let's copy this line for setting the type of the input to password or text based on the visible pass so here I go to the inputs and paste it here on both inputs password and confirm password again I go back to the sign in for and here copy the end content for this input which toggles the visible password and I get back here and let's paste it on the first input the password input okay and just import the icons here and paste the functionality for showing the password strength the password strength is in the sign up form so I go to the signup form and first we need to create a state for the P strength so just copy that and paste it in the reset password for I get back to sign up form copy this use effect okay and get back to the reset password form and let's just paste the use effect for calculating the password strength import the use effect and import the password strength function and just extract the watch from the use form yeah okay and let's just move the use effect below the use form Hub yeah okay and here put a comma here so that fix the error okay we just need to copy the password strength components from the sign up form so here I copy that and get back to the reset form just put the password strength component in the first password input okay so let's save this and now we can go to the reset password page and here inside the main div we just render the reset password for okay and we need to pass the jdb to user ID to the prams JP so let's get back to the reset password firm and just mark it with the use client directive okay so now let's get back to the browser and here click on the reset password link so this is our form we need to put a submit button here so I get back to the reset password form and here after the second input let's just add a div here and set the class name to flex and justify Center yeah okay and then inside we're going to paste a button so let's just go to the forgot password passw page okay and just copy this submit button get back here and paste it here okay so we have a button here that based on the E submitting of the form State render a please wait or a submit button and let's go back to the form itself and let's put some basic T CSS classes I'm going to put a flex and flex cool Direction put a gap here Gap two and a P2 for padding M2 for margin and also a border okay and rounded MD and also a shadow and let's save this and go back to our reset password form and as you can see we have a password and a confirm password so now let's put it on the center of the screen so I go to the reset path page and here put a class name flex and justify Center okay so as you can see now the password and confirm password are in the center of the screen so now let's put a caption for the for I go to the reset password form here and inside the form let's put a div let's put a reset your password okay and let's put some T CSS classes text Center and a P2 okay so let's save this and here we have the caption but here we just need to put a dash between the text and Center so as you can see the text is now on the center of the D so this is our reset password for but before showing this reset password form in the reset path page we need to verify the jbt and then if the jbt is okay then we're going to show the submit reset password form okay so in order to do that I go back to the vs code and here in the reset password page first we're going to verify the jbt so here I'm going to say const payload and set it to verify jbt function okay and pass the prams jbt and here we can check if payload is null so I'm going to say if not payload which means that the payload is null we can return a error message to user so here I'm going to return a div here and let's set the class name we'll set it to flex item Center and also justify Center Okay add screen for the height of the page and text red 500 okay and also let's set the text size to text XL or 2 XL okay and here inside the D we're going to say for example the URL is not valid okay so let's save this and let's go to the browser and let's just tamper with the jbt and put some random string to it and let's refresh the page and you can see the URL is not valid error message on the screen okay so now we just need to go to the reset password form okay and just write a unsubmit function for the form so here in the form first let me set the unsubmit props to the handle submit function that comes from the hook form and pass a reset pass function so now let's define the reset pass function here I'm going to say const reset pass and set it to submit Handler type which comes from the react hook for and then pass the input type here in the generics and now we can set it to a async function and take the data here and now we can Define the body of the function so we have a typo here so let's fix that reset pass and you can see the error is gone so in this function we're going to call a server action for resetting the password into our database so now let's go to the off actions here and here we're going to create a reset password server action but before doing that let me create a type for that here I'm going to say type reset password Funk okay and then set it to a function which takes the jbt user ID which is going to be a string and we're going to take a password which is also going to be string okay and then it returns a promise of this type so it will return either user not exist or it returns success okay so let's save this and now we can create our function so here I'm going to say const reset password this is going to be our server action for reset password and let's set its type to reset password fun now we can set it to an async function okay it takes the JWT user ID and the password so we don't need to define the type of the arguments now we can Define the body of the function so first we need to verify the jbt user ID so here I'm going to say const payload and set it to verify jbt function and pass the jbt user ID here first we're going to check if the payload is undefined or now we can just return user not exist okay and then we're going to extract the user ID out of it here I'm going to say const user ID and set it to payload that ID and then we're going to use the Prisma to find user so here I'm going to say const user and set it to await Prisma user. find unique okay and then pass an object here specify youw and inside it we're going to find the user based on the ID pass the user ID that we've got from the jbt payload now okay and again here we're going to check if the user is not not existed we can return a user not exist message okay so we need to remove this semicolon here and otherwise we can run a Prisma update so here I'm going to say const result and set it towait Prisma user. update and pass whereare object here which user we want to update we're going to pass the user ID here and set it to ID of the user and then here we're going to specify the data so in the data object we're going to say that we want to update the password and now we can we need to Hash the password so here let's import the bcrypt function I've already imported it so let's get back to the reset password function and here just set it to wait bcrypt do has and then pass the password okay and put the number of salt R and then here we can check if the result is not null we can return a success message otherwise we can throw an error for example let's say something went wrong so that's it for the reset password server action and now we can go to the reset password function and here in the reset path which is a submit Handler we're going to call the reset password function that we have just created so here I'm going to use a try catch block okay then a catch here in the tri block we're going to say const result and set it to await reset password function that we have created in the off actions so I I think I forgot to export that so here we need to export the reset password function okay so now let's get back to the reset password firm and call the reset password function and then pass the jbt user ID and the data. password okay and here we're going to say if result equals to success then we're going to toast a success message to user toasted success and let say your password has been reset success and in the catch block we're going to take the error and here we're going to tost a error message to user going to say something went wrong and just log the error into the console and yeah that's it for the reset pass submit Handler so now let's get back to our browser and let's go first to the email here and click on the reset password again so here my password was 1 2 3 4 5 6 now we are going to put it something like like 987 654 and here let's put it again 987 654 click on the submit and you can see your password has been reset successfully okay so I go to the sign in and here I'm going to put my email okay and now let's put our old password 1 2 3 4 5 6 click on this sign in you can see your username password are not correct now let's put our new password 9 87654 click on the sign in you can see it says that verify your email first so we didn't verify our email so let's get back here and can the activate your account link and now the user is activated so here let's click on the sign in and you can see welcome to sakur channel and here we are headed to the call back URL which was the reset password so we need to put some check if that we are on the reset password page we just need to redirect the user to the home homepage okay so that's it for the forgot and reset password and in the next section I'm going to create a user profile page and then we're going to talk about how we can protect our pages with the next off middleware and also I'm going to talk about what's the difference between the use session hook and get server session function so let's get right into [Music] it in this section we're going to create a profile page and then we're going to protect it from the unauthenticated users so I go to the app directory here and then create a profile route okay profile and then inside we're going to create our page. TSX here we're going to create a component here name it profile page and then in the first step here we need to retrieve the authenticated user from the session of the next off we can do this in two ways the first way is using use session hook as we have seen in the signin button so if I go to the signin button here you can see we have used the use session hook and then grab the session from the returning object of this use session hook but we can access to the use session hook only in client components but we are going to create this profile page as a server component so we need to resort to the second way of retrieving this session which is using the get server session function from the next off so what is the get server session function it's a function that retrieves the session of the next off in server side so so here in the profile page I'm going to call the get server session function so here I'm going to call the get server session and it can see it comes from the next off and here we need to pass the off options that we have created in the next off API rout Handler so here as you can see we have an object called off options and then export it from the rout Handler so we need to pass these off options to the get server session function to retrieve this session on the server side so here I just pass the a options here and then here we can grab the session that is returned by the get server session but this is a async function so we need to use a wait here and then turn the profile page to a aing component so we can use the await here and now we can get the session from the get server session function so here I'm going to say const session and then set it to returning object of the get server session so here we can grab the user from the session I'm going to say const user and set it to session. user okay and then here in the profile page first we're going to create an image here I'm going to use the next image okay and set the height 300 pixel and also the width of the image to 300 and we're going to set the SRC so let's close this off to have more space here and set the SRC user the image so since the user might be null here we're going to use the double question mark here and pass a empty string in case of the user is undefined and then here we need to specify the alt keyword here we're going to set it to user do first name for example and again use the double question mark here pass the empty string in case of the user is undefined okay so let's save this and this is going to be the image of the user in the profile page we're going to make it a circle shape so I'm going to pass the class name here and use the rounded full class from the T CSS okay and then we're going to have a kind of table here which shows the users data here I'm going to create a div here and let's set the class name to grid and then GD go 4 and also a gap of y4 then inside it we're going to create a P tag let's say first name and then here we're going to use an another P tag and here render the user. first name okay now a class name here and set the coold span three so we have a one coold span here then three cool span here which are four column all together okay now let's go for the another row we're going to have the last name then let's pass the user that last name next we're going to have the phone of the user pass the phone here and here let's render the user. phone lastly we're going to have the user. email so use the email here as the label and then here in the second P we're going to render the user. email okay so let's keep it simple here we have a profile page that has the image of the user and also in first name last name phone and the email of the user let's save this and now let's go to the sign in button and here if the user is signed in we are checking if the session is existed and there is user object inside this session which means that the user is authenticated and here we're going to render a P tag with the first name and last name of the user so here we're going to change it to a link here a link component that comes from the next CH okay and we're going to set a h here and set it to slash profile okay so let's save this and now let's run our application so here I'm going to say npm run div and let's open it up in our browser okay so let's sign in here and here let's put our email address and put our password now if I click on the name of the user here we are headed to the user profile page so obviously we don't have the information about the user which means that we're not getting this session from the get server session correctly back to vs code here we have an error here which says that it decryption failed so here we need to go to the route Handler of the next off and let's close this off here and here we need to specify the strategy of the keeping session of the next off so here inside the off option object we're going to specify the session and here inside the session object we're going to set the strategy of the keeping the session here we're going to set the strategy to JWT okay so the session of the next a will be turned to a JWT and saved inside a HTTP only cookie and then we can access to the session of the next off with the get server session function we can also save these sessions inside the database but let's just go ahead with the jwbt strategy okay so let's save this and here let's refresh the page here okay we still don't have the data back to vscode here let's open up the browser we still have the decryption filled and that's because we need to Define a variable inside the Envy file so here we're going to define the next off secret okay so pay attention to the spelling here and here we need to set it to a secret key I'm going to go ahead with the random key here okay and let's get back to the browser and now refresh the page and as you can see we still don't have the data here and that's because we changed the strategy of the keeping decision for that reason we now signed out from our application so let's get back to vs code and check out the terminal here you can see we don't have the decryption fail error in the terminal but the session is undefined and as I said that's because we're signed out so let's click on the sign in here and let's put our email our password okay so as you can see here inside the profile page we can see the data of the user we didn't say set the image of the user inside our database so we don't have the image here but we have the basic data about the user name last name phone and also the email of the user here in the profile page so in this way we can access to the session of the next off in our server component so let's back to vsod let's make a recap here I go back to the profile page here and here as you can see we call the get server session function and pass the off option so it's really important to pass the off options to the G server session function otherwise you get a null session so if I go to the API R Handler of the next off you can see we just create an off option object and then export it from this file and here after the off option we have created the Handler with the next off function and then pass the off options object to this next off function one of the mistakes I've seen a lot of times is that some developers don't create the O options separately they just create the O options inside the next OD function here and then try to export the Handler from this file and then here inside the profile page they try to send the Handler as the off options to this get server session function and if you do that you get the null session so make sure that you have created the off options separately and exported from the AP rout huner of the next off and then anywhere that you are going to use the get server session you need to pass it to this get server session okay so that's it for the profile page and in the next section we're going to see how we can protect the profile page from unauthenticated [Music] users okay so in order to protect the profile page one of the first way that came to mind is to get the session from the next off if this is a sever component you can use the get server session function to get this session but if this is a client component we can use the use session hook to get the session and then we check if the user is inside this session it means that the user is authenticated and then we can render the page to the user otherwise we can just redirect the user to the login page so let's see how we can protect the page with this approach and next we're going to see how we can protect the pages with the next off middle L which is really handy and easy okay so here we can check if the session is not existed okay or session is existed but the session doesn't have a user inside it so I use a not here then session. user okay so this means that the user is not authenticated so here we just need to redirect user to the sign in page so I use the redirect function which comes from the next SL navigation and then pass the slash off SL sign in okay so now let's save this and get back to our browser let's sign out here okay and here let's go to the homepage and let's manually put the profile address on the browser so as you can see we are headed to the/ off/ signin but this page is not existed so here let's go to the off page obviously we have the sign in oh yeah we misspell the signin page here okay so I fixed that and and let's get back to our browser go to the homepage and then as you can see we are not signed in okay so let's manually go to the profile page here you can see we are headed to the signin page automatically so in this way we can protect the profile page from the unauthenticated user although this approach Works without any problem but if we have many pages that we are going to protect them we need to manually put this condition in every page that we are going to protect from the unauthenticated user but there's a better and easier way to protect the pages in the Nexus with next off and that's the using the next off [Music] middleware so in order to protect our pages with the next off middleware we need to create a middleware file so here inside the SRC directory and side by side of the app directory we're going to create a file called middleware TS okay so in this file we just need to export default from the next o/ middleware so actually we are exporting the next o middleware as the middle ver of our nexj application so in this way each page of our application is protected from the unauthenticated user but that's not desirable because we don't want to protect the homepage of our application from the unauthenticated users only certain pages so in order to say on which Pages we need to apply this metalware we're going to export a config object so I'm going to say export con config and then inside it we're going to specify the match list okay and set it to a list here and inside this list we're going to specify on which Pages we're going to apply this middle word so here we're going to say slash profile so now our profile page is protected with the next AR middleware also we can use the regex so for example let's say we have an admin panel which contains multiple pages so we are going to protect all of the pages of the admin panel from the unauthenticated user so in order to do that we don't need to specify all of the pages here in this list we just need to say for example admin okay and then col path star so in this way every pages that start with the slash admin will be protected by the next off middleware so let's save this and go back to the profile page okay here we just comment this out this condition for checking if the user is authenticated or not so let's comment this out and now let's go to the browser to test it okay so here in the homepage if I go to the SL profile here you can see we are headed to the signning page because we're not signed in and the profile page is now protected with the next a middleware so let's sign in here with my username and my password here okay and now if I click on the profile page we can see now we are allowed to go ahead to the profile page so yeah that's it for this section I explained two ways for protecting your pages in a nexs application you can use use session hook or get server session function to retrieve this session and then check if the user is authenticated or not or in the second way which I recommend to use it you can just create a middleware file and then export the next off middleware from that file and then export a config object and specify on which path you're going to apply the next off middleware that's it and if you want to know how we can implement the role based authorization in our nextus application with next o I have two videos for that the first one is using just the credentials provider and implement the role based authorization with that and in the second one I have used the Google provider and implement the role based authorization inside it you can also find the links of these two videos in the description below this brings us to the end of this tutorial I also Al wanted to create a section for integrating the Google provider for the next a but since I've already have a separate video for this topic just put a link in the description below so you can watch it if you want to integrate the Google provider for the next op in your next year application so if this video is useful for you please hit the like button and if you haven't subscribed to my channel you can support me and subscribe to my channel and if you have any suggestion about the next video you can tell me in the comment section Below have a nice time bye-bye
Info
Channel: Sakura Dev
Views: 3,248
Rating: undefined out of 5
Keywords: next.js tutorial, next.js, nextjs authentication, next.js authentication, nextjs tutorial, authentication in nextjs, next.js 14, next.js 14 tutorial, next.js 14 tutorial for beginners, authentication, next.js 13 tutorial, next js tutorial, nextjs, next.js 13 authentication tutorial, next.js tutorial on server-side authentication, next.js 13, authentication in next.js 13, authentication in next.js, server-side authentication in next.js, next.js tutorials, sakuradev, vahid nejad
Id: Xa73Xr8PM2k
Channel Id: undefined
Length: 205min 42sec (12342 seconds)
Published: Mon Jan 01 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.