The Right Way to do Auth with the Next.js App Router!

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
I'm going to show you how to add cookie based authentication to an existing app we're going to use this email client example that I've been working on for a couple of videos there's a link to the full playlist in the description but for this video we're going to focus on all things authentication why you need cookies and how you can use the superbas SSR package to handle all the tricky bits let's get into it so here I have our email client it has folders on the left a list of emails in that folder and then if we click on one of these emails we can see its contents but it doesn't really makes sense for us to see anything on this page if the user is not currently signed in so if we click this login button we'll see our authentication page and we have this button to log in with GitHub the code for this page looks something like this we have a form with a submit button and the GitHub logo when we click it that submits this form to this sign-in action which is declared above so this is a server action and right now we're just console logging out signin with GitHub and if we open up the console for our Dev server we can see that message from when we clicked earlier so we can get rid of that console log now and we just need to create a new superbase client so we can do that by saying const superbase is equal to calling the create client function which comes in from do/ utils superbase and if we have a look at that one it's just wrapping a call to the create client function that comes in from superbas JS just so we don't need to copy and paste these environment variables or any other configuration that we might add as part of this video so if we go back to our login page we now have our superbase client and so to sign in with GitHub Hub we can await a call to superbase do. sign in with oo and this takes a configuration object with the key provider set to the string GitHub now I configured GitHub as an authentication provider in between these videos so if you need to do that for your project check out the guide Linked In the description for setting up an oo app with GitHub so when we call this sign in with ooth method it will give us back a couple of things it will give us back an error if something went wrong or the data if everything was all good so if we do get back an error then we probably want to be kind to our future selves and console loged out otherwise we want to return a redirect which is a function that comes in from next snation and then we just need to give this one a path that we want to redirect to so in this case that will be data. URL so this is a URL that we get back from initiating this signin with ooth method so this will send us off to GitHub to authenticate but then after that's finished we still need to redirect the user back to our landing page and so we do that by passing an additional parameter for options which is set to an object with the key redirect to set to our origin and so we can get our origin above by calling the headers function which should come in from next SL headers so we can just import that manually so we want to say import headers from next SL headers and then calling this headers function will give us back a list of all of the headers so we want to call get and pass it the string origin and this is complaining that null is not assignable to to type string or undefined so we can just make this a string by using backx and then dollar sign open curly and then Clos curly after it and backs don't worry we need to do this for the next step anyway so when we click that GitHub logo we call this sign in with oo function which gives us back a URL which we redirect to to kick off that authentication flow with GitHub and then when that completes we want to redirect to the landing page and now back in our application if we click here to sign in with GitHub it will step us through that oo flow with GitHub and eventually we'll end up back on the landing page of our application okay cool now that we have authentication let's make the rest of our app protected so you need to be signed in to be able to see any of those emails if we have a look at our next. config.js file we'll see this has a redirect setup from the landing page of our application to /f/ inbox so that's going to take us to this F route and then this is a dynamic route so this part of the URL will come in as this name variable and this page. TSX server component will be mounted for that route so we want this one to require authentication and we also want this new route to require authentication so since these both exist within the same sub route of slf SL whatever the folder name is we can create a new file for layout. TSX which will be loaded for any routes within this folder So This Server component and also This Server component so this is a pretty simple layout component it takes some children as a prop and then returns those children again so we're not rendering anything additional but any logic we add before this return statement is going to be run for any of the child routes of this component so let's create a new superbase client by calling the create client function again that comes in from our utils folder we then want to check whether we have an authenticated user so we can say const the data that comes back and we want to destructure the user object we get this by awaiting a call to superbase .g get user and so this user object will either be a user or null so if we don't have a user then we want to redirect which again is a function that comes in from next / navigation and the path we want to navigate unauthenticated users to is/ login otherwise if we do have a user then we just continue on to render the children so let's step through this process in our application so we click the sign in with GitHub button and it doesn't work hang on what's going on here are we not redirect in correctly to the landing page well let's add the best damn debugging tool there is out there the console.log here statement and let's go back to our application and sign in with GitHub again we can see something's going on that little bar is pulsing when we click this so let's open up the console of our development server and we can see here here here so we definitely got here so let's move this under our get user statement and check what is our user set to and again let's click the button and open up our console and we see user is null okay you got me I knew this was going to happen but I wanted you to experience it with me the problem is that by default superbase JS stores the user session in local storage so we can see it is getting set correctly but local storage doesn't exist on the server and guess where server components and server actions run on the server therefore we need to use cookies to store the user's session rather than local storage thankfully we've developed a super handy package called SSR for this exact problem let's use pmpm to install or I the at superbase SL SSR package we also need at superbase SLS superbas JS but since we already have this installed in our project we just need the SSR package and now that that's done we can run our development server again and then open up this helper function for create client and we want to change this import to the create server client function which means we can get rid of this Alias and this one comes in from the SSR package we can then copy and paste this one and then this is lit up red because we need to pass these two environment variables but then we also need an additional configuration object called options so we can pass that one so I'm just going to paste this one in and this is just declaring how to get set and remove a cookie in nextjs so we need an instance of our cookie store so we can declare that above which means we need to refactor this slightly to actually have a body of our function and then we want to return this big create server client blob so if we paste that one here then above that return statement we can declare a new variable for cookie store which is the result of calling the cookies function that comes in from next slhe headers and so this cookie store can now be used to interact with the cookie headers on our request so we can call Cookie store.get pass it a name and then if we get a cookie back then we want to return its value and then we also declare how to set and also remove a cookie we also need to import this cookie options type which it's not nicely inferring but this comes in as a type from the SSR package so we can say we want the create server client function and also the type for cookie options and so this adds quite a bit to the configuration when we're creating our superbase client but anywhere we're calling this create client function can remain exactly as it is as well as how we're using that client to do things like get our user or over in our DB actions. TS file where we're using our super based client to perform mutations or in our queries. TS file that has all of our data fetching logic thankfully we also have this awesome nextjs orth guide which will be linked in the description that steps through all of this with some nice copy and pastable code Snippets so you don't need to pause the video and type out every single character sorry if you already did that there's also a sneaky way to generate all of this so you don't have to type any of it but we'll talk about that at the end of the video there are just two more bits we need to configure the first one is in our login page after we've authentic indicated with GitHub we want to redirect to our origin so this will either be Local Host over Port 3000 or whatever our production URL is but then we want to navigate to/ or/ callback and then we need to declare this new route so under the app folder let's create a new file at or/ callback route. TS so this will be a route Handler and again I'm just going to paste in this Big Blob so this is listening to get requests on this route it's then getting the code from the search pams which will be automatically sent to this route by GitHub during that authentication flow so then we're creating a superbase client to exchange that unique code for the user's session and then we're just redirecting the user again back to that origin so this will just navigate back to the landing page so this pattern is called the proof key for code exchange pattern or pixie which is just a more secure way of doing oor so when GitHub is happy that our user is who they say they are it redirects them to our SL or/ callback route with this unique code which we exchange for the user session and so all of that redirection stuff happens automatically by telling GitHub where to redirect the user to after completing that authentication process and we can test this whole authentication flow in the browser by going to the authentication page and clicking sign in with GitHub and you can see we've been successfully redirected to the landing page and we can see my GitHub Avatar and also my GitHub username and if we open up the console and go over to application we can see our superbase session has been correctly set under cookies so our user is now authenticated but there's a bug when the session expires and superbase attempts to refresh a new sash the user will be unexpectedly signed out and if we have a look under application and cookies they're gone where are my cookies the reason this is happening is because server components only get read access to cookies so when we call super base. o.get user this will automatically refresh expired sessions before returning that user object but because this layout is a server component it can't update that cookie with our new session and so the browser just automatically removes the expired one therefore we need to use a route Handler server action or middleware to refresh this session before it hits our server component route so let's create another helpful Little Helper under utils /s superbase so this is going to be a new file called middleware dots and this is going to export out this big scary blob no it's not really that scary it's just a quite verbose way of again getting setting and then removing a cookie the difference is in middleware we need to change the cookies on both the request and the response so it looks just a little bit more intimidating again you can get that one from the docs Linked In the description or just wait just a little bit longer and I'll show you that single command that does all of this for you so now we just need our actual middleware dots file so we want to create that at the root most point of our project so again middleware .ts and we're going to paste this one in here so this one uses our middleware helper to create a superbase client it passes in the request so we can modify the cookies on that request and gives us back a modified response and also our superbase client then we're calling superb. o.get user and we're not actually doing anything with the user we're just throwing it away but again this get user function attempts to refresh expired sessions and then because middleware has read and write access to those cookies it can update the cook on the request and the response before returning this response which will load our server component route that the user requested so again this just ensures that we have a fresh session before we reach the server component because the server component only has read access to these cookies to determine whether this user is authenticated or not and the last little part of this middleware file is exporting a config containing a matcher and so this is a big scary rex or regx pattern that excludes a bunch of stuff so static files Bacons all these different image types things that we don't want to run this middleware Logic on because they're just assets for our application rather than server component routes which is all we really need to run this for and now our user can go on Happily using this application and reading all of their unread emails and when their session is ready to expire it will be automatically refreshed in the background as they're going through using the application but that's quite a bit of manual configuration if you want to skip all of that I recommend you check out this video right here we use a special super based template that's built right into the create next app CLI tool to configure all of this server side cookie stuff so you don't even need to think about it but until next time keep building cool stuff
Info
Channel: Supabase
Views: 8,216
Rating: undefined out of 5
Keywords: supabase tutorial, best firebase alternative, open source database
Id: VVElr2n90KY
Channel Id: undefined
Length: 13min 41sec (821 seconds)
Published: Sat Apr 06 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.