Authentication in Next.js 14 is easy...

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
authentication with next off in a next project is easy right well it's not always easy but after this video you'll Master the fundamentals of creating authentication in a NEX Shar project in this video you learn two types of authentication first of all owe off using GitHub and also email off using magic links so the user will sign in with his email then he will get a magic link and with the magic link he will then sign in into our application also we will style our application using T CSS and shatan UI to make it look a bit nicer and then at the end we'll of course deploy to Rell check out how the deployment version works and then we are finally done so now let's check out the demo behind me and let's go so on my screen you now see what you build today so currently I'm on the index page and I'm currently not logged in that's why it tells me please log in to see something special I can now click on log in which will redirect me to the off page right here you can now sign in there are two options either with GitHub or with email let's first of all check out GitHub I'll click on the button you will now see I will get redirected back to the index page and now tells me you're logged in I can now log out so let me click on log out and I will get redirected to the off page I can now uh log in with email so I will type my email right now then I can click on the button and now you'll see on the bottom right corner a toast which tells me check your email so now let me open my email real quick so now you see I got a magic link and once I click on sign in I will get redirected again to the index page and as you see I now have a session I can also now try to reach the off Route so let me do that slash off you will see I will get redirected back to the index page since when I have a session I don't want to authenticate again so that's what we'll build today so now strap in and let's go so to get started I will CD into my desktop directory CD into my YouTube directory and I run npx create-- app at latest to install the latest package of next shares the CLI will now ask me a few things so we'll name our application let's see um next of YouTube then we'll use typescript we will use eslin we will use tand we won't use the source directory since we'll use the app router and we won't customize the default import Alias and now the C will take a bit and install all of the packages needed for a new NEX sh project so this CI has now finally installed next sh has 14 so I can now go to visual Studio code and open a project as you see I already opened it and if you want to do the same you can click on top click on file and click on new open folder but now we have a default template so what you see on the right is just the default template which comes when I run the command to install next shares so the first thing I want to do is clean up a bit so if we go inside of the app folder inside of the global. CSS file we have a bit of default Styles let me just delete that since I won't need that then the next thing I want to do is now actually um install shetsen UI so let's go to the website so now I'm at shetsen UI and shetsen UI is just an basic component Library which is um styled and accessible which Builds on RX UI and we'll just use it to uh get some default Styles since I don't want to write many CSS Styles we want just to make an basic demo of authentication and that's why we'll use shatan UI for that so let's click on documentation installation next S as a framework and then let me run the CLI so I will copy the command for npm let's head back let's open the terminal for that you can use either command J or go on top and click on Terminal and new terminal inside of here let me now paste the command to initialize shet and UI this will now ask me a few things so let's use typescript um let's use the default Styles as some base color we'll use slate then our Global CSS file is correct then real use CSS variables our t .c config.js is not located in this file since if you open your Explorer right now we have in T.C config.js we'll have a T.C config.sys is also correct we use server components and yes let's write a configuration file so now you see it initializes or uh it installs all dependencies and now shetsen UI is actually set up you see now our CSF uh CSS variables and if I go to the T.C config.txt our theme right here so that looks nice let's now install the uh a bit of components which we'll need so let me search right here for a button since I want to use a button of course to sign in so let me just copy the C command let's open my terminal and let's paste that then let me install a few more components let's also get a input so let's install that let me copy the command with npm let's open the terminal let's paste that then let's search for a label let me um click on that let's copy the CLI command with npm let's paste it our terminal and install that then I also want to get a card component so let me find that let's copy the installation command with npm and let me paste that also inside of here the last thing I want is to get a toast so let's search for toast this will just be used later on to show a success message so let me also copy the command right here let's go back and let's install that um I think this should be all for now but if there will be anything else we'll install it at a later stage so now I think it's time to test out if everything works so let me close everything let's again open my terminal let's clear everything and let's run npm1 def to start our def server this will now open on local 3000 as you see so let's head over and open that so I'm now on Locos 3000 let me zoom in a bit for you guys and as you see that's the default template by next shares um we don't want that so let's actually delete that and uh create our own UI so let me open my Explorer again let's go in the app folder inside of the page. TSX and here you see the default template let me just delete everything inside of the return statement we don't need it and let's just say for now H1 uh or an H1 tag and let's say hello from the index page let's save that let's go back and yeah you see that so that works so now since the fundamentals are set for next shares so we have installed next shares we have created or we have installed a component liary and we have deleted the default Styles and we see everything works so now I think we can start with the fun stuff which is authentication with next off so let's head over to next off JS so I'm now on the next off sh website and as you probably know next off shares is a um open source authentication provider you can use it to make authentication work you have multiple providers for example Google Facebook Twitter whatever you want actually and you have multiple um adapters so for example Prisma super base um I don't know drizzle or whatever you want to use for this project we'll use Prisma as our um query layer so with Prisma we will query our database at superbase and store our session and user data and then we'll use as some provider GitHub and email so magic links through email so yeah let's get started so now let me click right here on documentation to get started and right here you now have an introduction so if you want to I would highly suggest you guys to through it you will learn a bit about next off JS and how it's actually built what the fundamentals are etc etc I won't cover that because I think um we can actually get started and you'll learn enough when we do it so let me click right here on getting started and then we have right here a new project or an existing project so now we have already created a project so so we have an existing project so the first step is to install next off so let me call uh copy the install command which is npm install next off let's head back let me stop my def server clear everything and let me paste the installation command this will now install next off for us and now let's go back so now the next step as you see right here is to add an API route but if you look at the code example right here this is for the pages folder or for the pages router so for the old NEX shares router but since we use next shares 14 and since we have chosen to use the app router so nested routing in that sense we can't um use the pages router or we can do it but it's not very recommended so right here you have in text right here it says if you're using asress 13 .2 or above with the new app router so we do that we use SN Shar 14 with the app router you can initialize the configuration using the new route handlers by following our guide so let me click on this right here and now you will see we will get redirected to a new route and now you see how you can initialize an API W and that's exactly what we'll do so to get started what we'll do is again open our Explorer let me uh close my terminal and then in the app folder we want to create a new API folder then inside of the API folder we want to create an off folder if you then go back you see the next folder is in Brackets right here dot dot. next off so let me just copy that and then paste it inside of here just to be sure that I have not misspelled anything and then inside of here inside of this next off folder I want to create a new file called W.S now the important thing is you have to um name it route. TS you can't name it anything else since we're right here we create an API route and next sh only sees it as an API route if it's named routts so be sure that you um name it R.S and not uh something different but now we have created our own API route for next off and now we have to create a bit of configuration so let's head over to the documentation again so now if you look right here they tell us internally next off the text that it's being initialized in a rout Handler uh by understanding that it's passed a web request instance and will return a Handler that returns a response instance a route Handler um file expects you to export named Handler functions that handle a request and return response next off uh needs a get and post Handler to function properly so that's what you do right here you initialize next off you pass your off uh your options so what providers you use what adapters you use and then at the last step you export your Handler as a get request and as a post request since that's um since that's what next off needs to work properly so we will actually initialize our next off a bit different since we'll later on want to get our session through the server and not through the client so to make that work we'll actually have to initialize our um next off a bit differently but again let's go back and I will uh show it to you so we start actually the same as right here in this example we'll first have to import next off and next off is imported from next off and then under that what we have to do now is create a constant Handler or you can actually name it whatever you want but I will name it Handler then this will be equal to next off so now we have to pass an argument to next off so an argument what I mean with that we have to pass the options so what providers do we want to use what adapter what do we want to use now there are two ways you could do that you could either do it right here as they show it in the example but then the problem would uh be that you couldn't that you can't use the server uh get server session um hook to get the session through the server and we of course want to get our session through the server so how would you achieve this well what I would do is actually create a separate file then create all of the configuration in the separate file and then just pass this file or the function that sends as an argument to this next off function so let's actually do that so how do I do that I go inside of the app folder let's create a new folder called utils and now inside of this utils let's me create a new file called off. TS now as I already said inside of this file I now want to create the configuration so the providers and the adapter so how do you do that let's first of all export a constant let's name it off options and this will be equal now to a empty object for now but now there's one thing if I click for example on control space bar I don't get any specific types to off options that's not exactly what I want since I use typescript I want to get types now how do I achieve it that I get types well there's a very handy keyword actually uh from um typescript which is satisfies so what I want to do is that this object satisfies the next off options so right here we can do a satisfies and this should satisfy the next off options this is imported from next off and actually let's import that as in type now right here we get an error but that's not a problem since if I now go inside of this object and click control space bar you see we now get actually types which are based on the um off options so now what's the first thing we want to do well we want to get the providers now providers is in a way with uh individual objects of the provider I want to use so for example the GU provider Google provider email provider credentials provider whatever you want each provider an object inside of this providers away so what we can do now is go back to the docs and if you go right here on providers so above the adapters you can see the individual adapters that next off uh offers and you see there are multiple ones so Google Dropbox Discord credentials I don't know GitHub whatever you want there are very many and it's very easy to set them up so in this project we'll use GitHub since it's very simple let's click on GitHub actually and then right here you see how to get started right here you already have an example so as I already said we have the providers array if we go back you see we have created that array and then inside this providers away we then have to initialize our providers so the guub provider in that sense so let's actually do that so what I will use on top again copy this import statement let's go back let me paste that inside of here and now we can use this GitHub provider inside of our array so let's get right here our GitHub provider and now we have to pass again two arguments to this GitHub provider so we first of all have to get the client ID which is in string and we have to get a client secret which is also a string now of course you don't want to pass them as strings you want to uh pass them as secrets and how do you do that well use an EnV so an environment variable so what I will do right now is open my Explorer then let's create a new file which is called EnV again right here I store the environment variables and before I do anything with that let's be um safe let's go to the git ignore and right here let me just add EnV I do that to not um push my environment variables to my GitHub repository because that's not safe and now inside of this EnV file I can store my environment variables so let's first of all get the GitHub um let's do it uppercase GitHub ID and this will be equal for now just some gibbish I will change it later and then we'll also have an um GitHub undor secret uncore let's say ID and let's also do some jush for now so what I can do now is actually get the data right here through my environment variables so let's do a process. EnV do how did I name it let's check GitHub ID so I will copy that and then paste that also you see right now we get an error so if I hover over um client ID it tells me typ string or undefined is not assignable to type string so what does the error actually say in basic terms well it does not really know if GitHub ID is defined or not so for now it could be undefined or it could be defined but we know that uh it's defined so we can just say as string and we don't get any errors anymore now let's do the same for client secret so process. EnV do let's check how it's called right here GitHub secret ID let's paste it and let's do an S string so now in theory we have already set up our G provider and it's already almost works of course the um environment variables are not correct uh for now but in theory now our off uh provider works so what I can do now is go back to my uh W.S where I have my Handler and now I can actually pass my off options as an argument so I can now import the off options and as you see I don't get any errors anymore now if you can also remember I have to import uh export my Handler as and get in post request to make next off work so let uh let us do that right now so under this Handler let's do a export and I want to export a object and let's say Handler as a get and let's do also Handler as a post request so now our API route so the API route for next off fully works and we don't get any errors anymore also one important thing right here you see next off is imported from next- off/ next and not from next- off so let me delete this old import statement and that looks very nice so now our API route is done and we can actually continue with our M off options so what's the next step uh which I want to use I think the next step we want to do is the email provider so the magic links let's go back to our dos and let's search for email where is it email email email right here we have email so what exactly is the email provider well the email provider uses magic links to send a person a link s a magic link with which the user can then sign in and you probably also already saw them a bunch of times for example notion or slack um it's very easy to use and it's actually way more safe than credentials so I see many people always use credentials right here and I would not suggest you guys to use credentials why it's not safe people often uh forget the passwords or use the same p uh passwords which makes the user much more vulnerable against attacks or hacker attacks and that's why I would always use the email provider so now let's scroll down and let's see how to make it work so right here we have configuration um next off let's you uh send emails either via HTTP or or SMTP now I would always highly suggest you guys to use SMTP now why would I do that well that's because it's very easy to change your providers since with SMTP all you need is the host the um email server Etc and with HTTP it always works a bit different with every provider that's why I will use SMTP and right here you see already one thing you have to do is install not mailer and we will need note mailer to make SMTP sending work so right here what we have to do is npm install node mailer so let me copy that let's open the terminal and let's paste that since now node mailer is installed we can go back and let's scr down a bit so there are now two steps that we can use or uh there are two steps to make SMTP work the first one is to use a connection string I won't do that what I will actually use is a configuration object so let me just copy all of this environment Secrets we'll need them let's go to our environment variable file and let me paste them right here also I can right here add in description and let's just say I don't know um uh envs for email service so now we have created this environment variables of course we'll change the uh data for that later once we actually go to our email service and sign in and do that but for now let's just skip that let's scroll down and you see now you can add the provider settings to next off CH options object in the email provider that's exactly what we'll do so let me copy right here this import command let's go to off. TS so off configuration file let me paste that and now under the G provider I can use the email provider now inside of here I again have to add a few things so if I go back to the docs right here we again have to add our host our Port our um user our password and from which email we sent so I will just copy that actually since it's much simpler so let's copy that and paste it inside of here and now we have created our configuration for email so magic links now also work so now we have created our providers which is nice right yeah it's cool but now there's one problem if you think about it you create a user or in that sense you right here authenticate as a user now you have to store the data somewhere how do you do that well you use an adapter so if we go right here let me close the providers Tab and let me click on adapters now again what are adapters well these are used to store the data somewhere in a database and since we'll use Prisma to query our database we'll also right here use Prisma as an adapter so right here you can click on Prisma and then what you will see is we'll get redirected to this off JS website I know it's a bit confusing but next off and off CHS are almost like the same project I guess next off was the original project then off CHS became a global project for multiple Frameworks and now we have two docks which are I don't I know not per perfect but I guess it is what it is but now we have the prism adapter right here which we want to use and right here we already have an installation command which is to install pisma and also install the adapter so let me just copy that let's open my terminal and let's just paste it inside of here so Prisma and the adapter have now been finally installed so if I now go back you see now the next step is to add our adapter to our off options so let's do that if I now go back again to our off file buff the providers array I can again click on control space bar and you see I get the property adapter and I will also use that so now we actually also have to get our uh Prisma adapter so let's go back let me import the Prisma adapter right here so copy that paste that and now right here I can use my Prisma adapter so now let me also add an comma right here and now you see we get an error so what's the eror well we have to pass an argument and what do we have to pass well we have to pass the Prisma client but how do we do that if we go back to the docs they show us just to create a new Prisma client but this is not the correct way since that will work in a production environment but this won't work in a development environment since we use HMR so hot module reloading the application reloads when we save our application and every time we save our application and it rebuilds it will create a new connection to our database we don't want to do that so to fix that you can go to Google right now and search next JS um Prisma best practices and then the first link right here will show you how to fix that so right here tells you the problem again so if you're in a Dev environment it creates uh way too many instances and then you get errors so how do you fix that well you create a new file where you initialize Prisma and you check if you're in the development environment you make a global Prisma file and if you're in a production environment you just create a new nor uh the normal new Prisma client so let me just copy that right here let's go back to visual studio code let's go inside of our app folder utils folder and let's create a db. TS file I can now paste that inside of here and again to summarize what we do right here is just we check if we are in a development environment if we are in a development environment we create a global file and if we are in a normal production environment we just create the new uh the normal new Prisma Cent so that looks good so we can now go back and now just import our pisma file and now it's now important that you don't import that from at Prisma client but on top what we'll use a import Prisma from and this should be do/ DB and now we can pass it right here and we don't get any errors anymore so that looks very nice we can now go back actually again to the docs and scroll down a bit and it tells us right here to create this uh Prisma schema from scratch or actually it gives us the models so first of all to paste them we have to create a schema so let me open my terminal and let's do npx Prisma in it to initialize a new Prisma project so what we have to do now is actually if I open my Explorer you will see that two things have been created so first of all in the environment variable file we have now created a database URL which is right now just a default value which won't work and we have also created a Prisma folder with a schema file now inside of the schema file what we have to do is copy all of these models so model account up to this model very ification token let me do that right now I will copy that and then I will just paste it inside of here so now we have actually set a Prisma to work with next off and what it will do is actually when the user authenticates with next off all of the data will be stored inside of this models so the user data the ID name email then also the session so if the user is currently um active so if the user currently has an session and then for example also account data with an access token with FR token Etc so all of this will be stored in our database and for that of course we have to also create an actual database since again if I go to the environment variable file you see we have a default database URL which doesn't work so what we'll do is actually go to superbase and create a post database so now I'm at superb.com and if you didn't know superbase is actually an open source alternative to Firebase and they also offer a post database and since that's free uh up to a certain limit we'll actually use that so let me right here click on dashboard and if you don't have an account create one then let me click on new project let me choose my organization let me zoom out a bit so I see something then for the project name let's do a next of um I don't know production then for the password I will generate a password and I will copy that then let me go back and just paste it inside of here since I needed in a second then for the region I would choose Frankfurt since Frankfurt is the nearest to me and then I can click on create new project now this will take a bit about 2 minutes so once that's done I will come back so super base has now finally initialized so what I can do now is Click right here on settings then let me click on database and if I scroll down right here we have a connection string now it's important we don't want to use the psql connection string but the URI so let me copy that let's go back and let me delete this default database URL for our new database URL now you see there's one important thing you have to add your password right here so let me zoom in a bit right here you see your password and we have to add our password which I've just copied right here now the important thing is that you actually only delete this um brackets uh your password enough uh not anything else so let me do that right now and then let me paste my password so this should now work let me zoom out a bit and now what we can do is actually do an npx um Prisma DB push so what that has done is now pushed our schema file right here so our models to super base and now our schema is in sync with our database if you get an error right here that means that your environment variable so your database URL is not correct so probably your password is not correct or you have uh misspelled something again just be sure that you spell it correctly and then you won't get any errors anymore also if we now go to super base to the uh table editor you now see this models right here since now our schemas in sync with our database so since that has now been actually set up if we now go back to our off. TS file we are now actually done with the configuration so our off options have now been configured we have created our two providers so the get provider and the email provider and the last thing we have to do now is actually create the environment variables since if I now go back to myv file you will see that if I scroll uh to the top our GitHub ID GitHub SE secet and all the environment vars for our email are currently empty so let's first of all go to GitHub and create a new uh GitHub ID and GitHub secret so I'm now at github.com so let me now right here click on this let's click on settings then let me scroll down to developer settings right here let me zoom in a bit let's click on o off apps and let me create a new oof app inside of here I have now to give it an application name so let's just say um next off let me spell that correctly tutorial production then for the homepage so since that's currently not um deployed toell our homepage real is actually low 3000 so I will copy that and paste it inside of here then last thing we have to do is add an authorization call back Ur and that's interesting so what we can do is go back to our next off docs and then if we click on the providers and let's just click on Google so let me find that and once you're on Google right here you see an authorization call back URL and that's actually the same for all ooff apps so the only difference is that at the end you just name your o off so right here it's Google and foret will be GitHub so I can copy this authorization call backl go back and paste it inside of here and then instead of Google this should be GitHub so now we have our loc 3000 our homepage SL API SL off/ callback SL up that's our authorization call back so now I can register this application and now what you'll see is you get a client ID right here so let me copy that and if I go back I can now add it right here for our GitHub ID and now we have to generate our client secret so let me generate a new client secret and now the important thing is you only see this client secret once so you can't actually see it again so please copy it or if something happens or something goes wrong you have to regenerate a new client secret so let me just copy it for now let's go back and let's add it for to our GitHub secret ID environment variable so now giup is actually set up so now let's set up email and for that we'll use resent so let's head over to resent so now I'm at rent.com and if you didn't know recent is an email service so with them you can send emails they are very similar for example to sent Grid or MailChimp or whatever you uh used beforehand I just like resent since it's very simple it has an simple API and that's why I use them so what you will do right now is click on sign in or get started if you don't have an account and then let's go to the dashboard so I'm now in the dashboard right here and what I can do now is click on API keys right here and create a new API key then let me give it a name let's name it next um of YouTube next js14 and then full access and let me click on add this takes a second and now we have an API key right here so now let me actually copy that and what we'll do right now is just paste it right here we'll use it in a second and to not lose it anywhere I will just paste it inside of here now let's close that and what we want to do now is actually get the um server user the server password the server host and port and for that recent has a block article let me head over it and if you want to do the same go into my YouTube description and click on the link so now I'm at the blog article from recent and right here they show you what the um values are for each um value I guess so for the host this is smtp.at and let's paste it right here for the host then the next thing we have is the port which is 465 let me copy that and paste it for the port then for the username it's resent so let me copy it and paste it right here then the next step right here the password is my API key so I've already copied it right here so let me again copy it and then for the password let me me paste that and then that's already all the last thing we have is the email from and now the interesting thing is with next uh or with resent is if you're in development which we are since we haven't um verified our personal email you will have to actually use their email to send emails so if you right now click on where's the docs so right here we have the docs then let's click on noj quick start you will see in development we have to use this onboarding at resend. URL or email that sense so let me paste it right here and now the thing is if you actually go to production and verify your email with recent or your domain in that sense you can use your own email but since we're in development environment and we currently don't uh don't verify our domain we have to use their own email but that's fine um there's no problem for us since we uh actually just learn next off and that's fine for this purpose so congrats you finally now initialized next off it's now fully configured as you see we have created an API route we have created a schema file we have created the environment variables we have created the off options file everything has been set up now the last thing we have to do is actually connect our font ad to next off and then authenticate the user so that's exactly what we'll do now so let's do that the first thing I will actually do is now go inside of our index page so inside of the app folder the page. TSX let me uh first of all delete this import image we don't need that and then let me just create a new return statement inside of here let me create a def element let's give it a class name which will be padding of 10 then inside of here let me create an H1 tag and let's say um hello from the index page this is a public route what I mean with a public route is that every user um can access this route you don't have to be authenticated to reach the index page so what do we do now well I think we should now get the actually the session of the user and for that there are two ways you can get either the session for the client or through the server now I would never actually try to get uh the session through the client because it's not safe and also to get the session through the uh server it's a way cleaner ux for the user so because of that I would never uh suggest you guys to try to get the session through the client I would always try to get it through the server if possible so what we'll do right here is create a constant session you can name it whatever you want and this will be equal to await get server session get server session is imported from next off and now inside of here we have to pass an argument and the argument is actually the off options so let me pass my off options imported from the utils now you see we get an error and it tells me right here aate expressions are only allowed with an async functions so to make it work we have to mark our uh export default function s async and that's exactly what we'll do right now export default async function home and also this is safe since this is in server component and because of that nothing will be ever um I guess shown to the client so that's why we use right here this get server session function and that's also why we have to mark our function as a sync since we have to get the data through the server so now we get the session actually and what we can do now is under this H1 is use inter ternary so let's do if session is there let's use question mark and if it's not there let's use some colon and return something else so let's first of all let's say right here H1 you um are locked in and if the user is not logged in let's say right here H1 um please loog in to see something special so if I now save that and go back let's go to our Local Host let me reload the page and you see we get an error and that's because our def server is not running so let me run npm1 def to restart our def server so what do you see now we see right here hello from the index page this is a public route please log in to see something special so since we now get the session through the um server we can now check if we have a session and since we right now don't have a session so since we're not authenticated we get right here hello or please log in to see something special if we would be logged in so if we would have in session it would show you are logged in so what do we do now I think we should create the off route to make the user uh able to authenticate so for that let me go inside of the app folder let's create a new folder called off and let's create a page. TSX inside of here we have to now do an export default um function let's name it um off Route and let me open that function now for the return statement I will actually try to to make it as simple as I can since this tutorial is not a tan CSS tutorial but more a next off tutorial that's why I will try to make it as simple as we can and also at the same time that it looks kind of okayish to present so let's first of all start with the card component and the card component is imported from our components then inside of here let me import the card header and then inside of the card header let me get actually the card um title and then let's just say um please sign in uh yeah I think that's actually quite okay we can also do a card description and right here we can say um to access um the private page you have to be authenticated something like that um let's check out how it looks like so let me go to slash off and let's see please sign in to access the private page you have to be authenticated let me also zoom in right here here now this is currently actually the width is the full screen I don't want that so what I will do now is wrap the whole card um element right now in a diff element then let me paste that back let's style the diff so let me give it a class name of w screen H which will be screen um Flex items which will be Center and justify which will be Center let's see how that looks yeah that looks quite a right in my opinion so now let's create the sign in form and the GitHub sign in button but so for that let's go under the card header let's import card content also imported from our components and then inside of here what do we do let's start off with the input for the email so let's do a div element let's give it a class name which will be flex and flex of call then inside of here let's give it another div element let's give it a class name which will be Flex Flex call and GAP Y which will be two then inside of here I can now import a label again imported from the components inside of here this is actually not a self closing tag but it should be like that then inside of here we can just say email under that let's import the input component from our components this is now a self closing tag we can give it a name which will be email we can give it a type um type not type off which will be also email let's give it a placeholder so the placeholder will just be let's see name at um example I think that's fine um what else do we need I don't think we need anything else let's see how that looks first of all name email okay input yes that looks fine um now we need also of course a submit button so let me go under this div element and let's import the button component the button component is imported from our components and now let's say lock in um with email okay let's go back yeah almost um the padding is not quite correct or the margin in that sense let's fix that real quick so let's give it margin for the button let's do a class name of margin top um let's say I don't know four let's see how that looks yeah I think that's presentable we can leave it like that so now since we have uh created the email form pretty much now I think we should also create a GitHub signin button so under this lock in with email button let me actually create another button let's say lock in with um GitHub and let me use a GitHub icon so we have this Lucid react package and right here we can use the GitHub icon that's a self closing tag let me also give it a class name of with four h of four let's see how that looks okay that looks all right let's also give it a margin left of four and then also for the button let me give it a margin top of let's say five six yeah six let's see okay that looks all right now the one thing I don't like right here is um that the color of the buttons is the same so I want a different color for the lock in with GitHub button so let me give it a variant and for the variant we will do secondary so let's see how that looks yeah that looks quite all right so now I think the time has come to start with our first um authentication provider which is GitHub so let's see how to make the login with G button work and well it's actually quite simple but it won't work right here so what we have to use actually create a onclick Handler and then call a sign in function provided by next off now if you're new to next 14 and don't know the difference quite between server components and client components the fundamental Basics are that in a server component which is rendered on the server and not hydrated anywhere so it's totally server rendered you can't have any client side interaction and since we want to do an onclick Handler that's a client site interaction which needs hydration so what that means simplified is that we have to break this lock in with gab button into a separate component Market as use client which hydrates on the client and then we can use this button so let's do that what I will do now is open my explore go inside of the app folder create a new folder called components then inside of here let's create a sign in with GitHub button so TSX and now inside of here it's again simple we do a export default function let's name it sign in with GitHub that's not spelled correctly let's do it again and now I can just open the function let's do a return statement and for the return statement I will just copy this button that I've created right here so let me copy that let's go back and paste it in the return statement now let me import the button component let me import the GitHub component right here and now that looks good I can now go back and just import the sign in um with GitHub uh component that we just created if I now go back to Chrome reload everything you still see everything works so now let's make the functionality work to sign in with getup for that first of all let's go on top mark this component as use client because I already told you this has to be hydrated on the client what we can do now is on the button create a onclick Handler which will have an inline Arrow function and then inside of here we can actually call a function which is called sign in now sign in is imported from next off as you see right here and now we have to actually provide an argument so which provider do we want to use and we want to use the GitHub provider so let's use that and there's one more thing that I can do now actually and that's add an call back URL what's the call back URL well that's the URL to which um I guess next off or in that sense GitHub uh should redirect once we are done done or once we successfully authenticated so let's do write a call back URL now the call back URL has to be an actual URL path not an absolute path so I can't just give it right here slome or something like that it has to be act an actual URL and now the thing is of course if we're in a development environment the call back URL will be low close 3,000 but if we deploy our application this callback URL would of course change now there's a very easy fix actually to instead of hardcoding it what we can do is right here use these um I guess Optics I don't even know how they are called then we can use this Dynamic value and get the window.location do origin with that we get the current URL so for us it would be Local Host 3,000 and then I can choose to which URL do I want to redirect to and for us this would be now just the normal um home page so low close 3,000 so that's already finished and that looks good now I think we're already done we have now created an onclick Handler we sign in with GitHub we have an callback URL and I think we're done with that so now we can actually test out if it works so let's do that right now let me reload the page just to be sure now I will click on login with GitHub and let's see let's see I get redirected it tells me to authorize my um I guess application so let me click on authorize my uh profile account and now you see I get redirected to the homepage I now also get a notification for my Gmail that I'm now signed in or that I've have granted access and as you see I'm now successfully authenticated since our Turner now States instead of let me see what did we have instead of saying please log in to see something special it now tells us you are logged in so now we have a successful session uh which means that we are authenticated if I of course reload the page you'll still see that the session that the session is still persisted and that's very nice so now you see that works but now of course if we again go back to the slash off website so let's do that you can still reach it that's not quite what we want if the user is signed in we of course don't want him to be allowed to reach the off page because why should you he's already authenticated so again it's a very handy trick what we can do now is we can go to the off Route we can again get our server session why can we do that that's because this route is a server component so I can do a const session let's do get uh do an await get um server session imported from next off and for the argument let's get the off options now we get an error it tells me a expressions are only allowed within async functions so let's make it an export default async function now we don't get any error anymore and now we can say if a session exists let's just do a return redirect now it's important redirect is imported from next navigation and let's say slash just a slash so the homepage so let's save it let's see if that works I will reload the page you see we get redirected and if I now try to reach the off page what you will see is that it won't work so that's perfect it now works and we actually protect our off route from authenticated users but now the question comes how do I sign out out of my application well again for that we have a very handy function so let's go back to our page. TSX right here and what I would do now is create a button do a on click Handler and then just call the lock out function again since this is in server component which renders on the server I can't do that so what we have to do is actually create a separate component which I will do right now let's go into the app folder into the components and let's do a lockout button. TSX then let's create a new export default function let's name it lock out um button and then let me just open that one thing I would do right now is just uh uppercase lock out button and then inside of here I can now do a return statement we can return a button element so let's import button from our components and then let's just say lock out that looks quite all right in my opinion um then what we can do is go back to our page. TSX and then where we have um you are loged in let's wrap this H1 in a diff element let's paste the H1 back and now we can import our lock out button let's see how that looks let's go back yes we have now the lock out button but if I click on it of course nothing happens so let's fix that of course so what we first of all have to do is of course again mark this um component as a client component so let's do a use client and then for the button we have to add an onclick Handler so let's do onclick Handler again with an inline Arrow function and then inside of here I want to call the sign out function provided by next off now inside of here I can again add a call back URL actually and we can again get the window uh location. origin and then redirect to this route so let's do that again let's use these up ticks then let's use this Dynamic value get our window. location. origin and then let's do a slash off to redirect to the off page so that the user can again lock in let's save this right here uh on click sign out call back URL yes I think that should work we have a used client so this is a client component so let's test out if it works so now let's click in on lck out let's see what happens uh sign out are you sure you want to sign out yeah sign out and we get redirect to/ off that works let me again try to log in with GitHub let's see um it loads and now you're logged in let me again click on lock out I get again redirected to/ off and my session is gone if I now try to reach the normal homepage again you see please log in to see something special um let me also go to the page uh. TSX let me wrap this H1 in a div element and underneath let's say a button or not a button but let's say um oh no it's good let's do button um imported from components and then inside of here we can do an as child import the link component from next SL link give it an H which will be um slash off and let's say log in if I now go back we now have this lockin button if I click on it we get redirected to SL off I can click on lock in with GitHub and we load and it works perfectly if I again try to reach the SL off page you see I can't reach it so now let's again click on lock out what I want to do now is make in uh make lock in with email work so let's do that right now there's again one problem right now our form if I go to our um where is it off Route so let me open that you see right here that our form is currently embedded in This Server component which is fine but now the problem is that we actually have um to convert this uh form into a client component so again we open our Explorer go inside of the app folder inside of the components folder and then inside of here let me just create a sign um in form. TSX let's again do a export default function let's name it sign in form and then let me open this right here now inside of here let's do a return statement and for the return statement I will just copy this button up to the stiff right here so let's copy that uh close that then inside of here let me use um a form element actually let me delete the action and then paste what I've just copied now let me import the label first of all so from our components let me import the input from our components and let me import the button from our components who would have thought then for the button let me actually give it an type which will be submit since we want to submit the uh form with this button and then for our off page I can now just import our sign in form so let's save that let's go back and now our login with email button is not stretch the full 100% so let me go back to the signin form let's give it a class name of full let's see if that helps yes that helps and that works now perfectly this looks nice so now let's actually make the functionality work so what I actually want to do is call a Asing function now this will be a normal Asing function not a server compon uh not a server action and then with this I will then sign in with my email so now the first thing I want to do is now actually is create state so what I will do is now right here on top let's do a const email and set um email this this will be equal to use State and use state is imported from react and I will set it to null as an initial State then for our input what I can do is um on change we can get the event and then set our email state to the um event. target. value so everything that we write in our input will just be set to our state now we get an error and it tells me right here type string is not assignable to um type null so what I can do is right here for the use state is ADD and generic and this could be either null or let's say a string so now the error is gone and this looks very nice so now I think we should create the async function actually so what we can do right here is do an async function um let's say how do we want to call it sign in with email and then let me open that right now now what do I want to do right here first of all I want to sign in with my email and then I want to check if this um signing in with email works then I will actually uh create a toast where it says um congrats uh successfully signed in and if not then I want to create a award tost so what I will do first of all is do a const um sign in result this will be equal to AIT sign in now sign in is imported from next off react now with what provider do I want to sign in well I want to sign in with email since that's the EMA uh since that's the provider which I want to use but now I also have to add a bit of configuration so first of all I have to pass the email which I want to use and I want to have to pass the call back URL so what we can do right here is first of all give it an email which will be equal to our email from our state then we can do a callback URL now for the Callback URL I will again just use the Optics and then get a window. location do origin so now that looks nice but now we of course also have to connect this function function somehow with our form and that's also quite easy we give it an action and the action will be equal to sign in with email so that looks very nice we don't get any errors and yeah I think this should almost work I did some jush um let's see react server component error you're importing a component that needs State da da da da so the error is we use right here State and the finger status it has to be marked in a client component so let's do a use client let's save it let's go back let's reload everything and this works so now I think it's time to test it out now there's one important thing before I do that um with resent so our email provider you have to type your email that you have used to create your account at weent since we are currently in a def mode so you can only send emails to yourself so let's do that right now I will send a email to myself with the account that I've created log in with uh email now you see one thing is we got read directed to this verify request um URL we don't really want that I don't really like this ux I guess um so what we can do is actually add a um redirect prop right here and set that to fults so we don't get redirected to anywhere and what I can do now is actually open my email as I said so let me do that real quick and now you see I got the magic link so what I can do now is click on sign in as you see and so now you see I got the magic link so what I can do now is actually click on that so let's click on sign in and as you see I'm now signed in so it tells me you're logged in so now let me click on sign out and see if that works and we get redirected to SL off so you see this also works but now there's currently one ux problem the user does not really know when he should go to the email and check if he got a sign in link so what we can do is actually do a toast so if the um a function was successful we can actually call or we can actually show a toast and if it wasn't successful we can show a fail toast so how do we do that let's go back and right here what we can do now is an if statement so if the sign in result is not okay so if signin result. okay is not okay we can actually return a toast now the toast is imported from our components and then inside of here we can say a title for the title Let's uh let's just say um I guess well this um did not work dot dot dot description and for the description I will just say something went wrong please try again and then I can also do a variant and this will just be let's say destructive so that looks fine and if this is not true so that the function worked what we can do is return a other toast right here and then let's say title um check your email and then for the description let's just say um a magic link has been sent to you so that should work now actually it won't work why won't it work that's because we actually also have to tell the layout that we want to use a toaster so let's go to our layout right now and under the children what I want to do now is import a toaster now the toast that's again imported from our components and now our toast will actually work so let me reload the page let me enter my email right here let me click on login with GitHub and now on the bottom bottom right you see a toast check your email a magic link has been sent to you if I now go back to my email you now see that I get a magic link so I can now click on sign in I will get redirected and this also works perfectly as you see so now authentication actually works I can loog out I can sign in I can sign in with email I can sign in with GitHub we do error handling with email and we show a toast so this works perfectly let's test out again everything just to be sure so let me click on log out we get redirected to/ off that's good let me loog in with GitHub we should get redirected to the homepage yes we are we see also the successful state where I can lock out so let me again lock out right now then let me use my email again let me click on lock in with G uh email we should see a toast yes we see that let me uh let me head over back to my email and what do you see we see the magic link so now authentication fully Works in next shares and what we have to to do now is actually deploy our application so let's do that right now so to deploy our application we first of all have to create a GitHub repository so I'm now at github.com new let's name our repository next of um next js14 I will make it public and click on create repository right here now you see it gives me instructions how to connect my code to this um repository so what we have to do is open the terminal let me stop my def server let me clear everything let's do a git in it to initialize a new git repository let's do a git add dot to add everything let me do a git commit dasm and let's say um finished let's click enter and then let's see what else do we have to do we have to create a branch so let's copy that paste that then the next step is to add in remote origin let's copy that and paste that and the last step is to push our code so let me copy that and paste that now our code will be pushed to GitHub and if I now reload the page you should now see our finished code and that's what you see so this works perfectly so now I'm at ver cell.com /ne to deployer application so let me click on import right here and now for the environment variables we'll just go back to our code I will copy all of the environment variables and just paste them right here now before I click deployment there's one important thing if you go back to the next off dos and click on deployment you will see there's one important thing that we haven't added so if you go to ver cell right here which is our deployment partner you will see one important thing we have to add is the next of secret environment variable so let me first of all copy the name right here create a new environment variable and for the value right here you can click on this link to generate a new secret right here it has now generated a new secret I can use that now paste it right here and now we have created a secret that's actually all we need and what I can do now is actually deploy this application so let me click on deploy and let's see what happens so we now got an errs you see right here it tells me pisma has detected that this project was built on a cell which CES dependencies this leads to an outdated Prisma client because prisma's Auto generation isn't triggered to fix this we can just click on this link right here to learn more so let me click on that let's open this right here and as uh what we can do to prevent that is add in custom post install script so let me copy this post installed script let's go to Studio code let's open my package.json and under this lint let me just paste our post install script I will now open the terminal clear everything then let us do a git add everything with a dot let's do a git commit DM and let's say added um post install script and then let me click enter and let's say get push this will now push the code to GitHub and verell will automatically rebuild our application so let's check it out out so our application has now been finally successfully deployed so let's check how it looks like let me zoom in a bit it tells me hello from the index page this is a public route please log in to see something special let's do that let me click on loog in we'll get redirected to our off page and you will see in a second we'll get an error if I now click with on lockin with GitHub you will see right here it will redirect and it will redirect to low close 3000 so what's the error well if you can remember when we created our GitHub app we have um added a callback URL which was local or 3000 but now this URL has changed to this next off nexs 14. wl. app URL so we have of course to change that so let's go to GitHub right now and now for our o off app I can click on it again and what we can do now is actually change the url so instead of low close 3000 I can go back copied our new URL in uh without the slash off go back paste it inside of here and do the same right here so let me paste that and this will now be an authorization call backl of my domain / API SL off/ callback SL giup I can now click on update application and if I go back to my code now we load everything it should actually work so let me click on login with GitHub and let's see what happens let's see let's see let's see uh it loads it loads and it says you're logged in so that looks nice let me again log out we should get logged out yes we also get redirected to/ off if I now again try to reach our normal route let's see how it looks like please log in so that works let me again click on log in so now let's test out if email works so let me add my email right here let me click on loog in with email we now on the bottom see a to check your email so let's do that you now see I get a magic link so let me click on sign in right here let me right here click on details and visit this unsafe site that's fine and now we should get redirected and we got redirected and it tells us you're logged in so now our production authentication works I can also try to reach the off Route and you'll see this won't work since I will get redirected to the homepage since it's in secured route so now you see it works next or fully Works We Now understand how to make authentication using o off and email work how to deploy it how we store it inside of our database how we create a connection with Prisma and everything like that so I hope you enjoyed this video and I hope I can see you in the next video so now bye
Info
Channel: Jan Marshal
Views: 18,317
Rating: undefined out of 5
Keywords: nextjs 14, next-auth, nextjs authentication, nextjs 14 authentication, learn next-auth, next-auth prisma, next auth supabase, supabase db, learn prisma, prisma nextjs 14
Id: gPQ9SD_qpuk
Channel Id: undefined
Length: 66min 33sec (3993 seconds)
Published: Mon Dec 04 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.