So in order to enable login we have to install NextAuth version 5 inside of our project. So head to the Auth.js documentation here and in the guides section all the way to the bottom you're gonna find an upgrade guide to version 5. So first of all let's install the proper version of NextAuth. So if you're watching this into the future perhaps it will not have this sign and it's just going to be NextAuth. All that matters is that the version is higher than 4, meaning minimum 5.
So let's go ahead inside of our terminal here, let's shut down the app and let's run npm install next-out like this and after you run this go ahead and run your project again and confirm in your package.json that you have NextAuth beginning with the version 5 like this. Great! So now let's go ahead and see what new features we have. So this is the one I like the most. The Universal Auth.
Previously when you wanted to access the currently logged in user in server component, you had to use different kinds of methods. We had getServerSession, we had getSession, we had without, getToken, useSession, all of those things. Now they have all been replaced with a universal auth so I think this is a great change. In here we also have some breaking changes like the import being deprecated. So the next, middleware, jvt, adapters, none of this exists anymore.
And now we finally have the configuration. So let's go ahead and do this. So in the root of our application create a new file called auth.cs like this. So a very simple name. What I'm gonna do is copy this snippet from here and I'm gonna paste it inside like that.
What we have to do now is we have to add the get and the post inside the API for next auth and you can see that in here we export this universal auth lib which we can then later use in server components to get to currently logged in user session or get no session at all if we are logged out. So let's go ahead and use this get and post to add them to our API routes. So in here we have to create an API folder inside of the app folder, then an out folder, then a catch all next out route and finally route.cs inside. So let's go ahead and do that. So inside of here I'm going to go ahead and collapse everything, go inside of the app folder, create a new folder called API, then another folder called auth inside and then another one where you spread next auth inside of squared brackets and then route.cs and inside I'm simply going to copy and paste this snippet from here like this and paste it here and what we have to do is change the import to go to the root so at slash alph like that because our alph file should be located in the root of our application.
Where is it? There we go, auth.cs and this is optional and I'm going to remove it because we're not working on the edge because we are using Prisma which by default doesn't support the edge. And then what you can do is go to localhost 3000 slash api slash auth slash providers and in here oh we have an error as you can see missing secret I believe we can also see that inside of our terminal here. There we go. You can see that the moment I added this auth file it's saying that we have an error missing secret.
So you can see that we have this link here which we can click on and open it like this and in here we have instructions on what we have to do. So we have to add our secret environment variable. So let's go ahead and do that. So I'm going to go inside of my environment file and I'm going to add an our secret and in here you can write whatever you want for development purposes. So you can simply write just a secret and then if I try and go to this route again slash API auth providers and refresh, there we go.
You can see that it noticed that we have a github provider inside of our auth.ts file. But for production it is recommended that you either generate your own secret using OpenSSL but that is only available on Unix systems like Linux or Mac. So you can run this in your terminal if you want, or you can simply click here and that's gonna generate a random one for you. So this is for production, right? You don't want your out secrets to be this simple, but in development, it's completely fine.
And if I refresh it's still working. Perfect. So now that we have this done what I want to do is I want to set up the middleware and in here you have a nice little table showing what has changed from version 4 to version 5 if you want if you're interested in that. So you can see that getServerSession with the out options had been placed with a universal out call. In the middleware we no longer have with out and middleware we now just have out.
UseSession has stayed the same for client components but you can see that everything else uses the new Auth Universal call so I really like this change. So now let's set up our middleware. So inside of the root of our application here create a new file middleware.cs and here is an important thing to understand about the middleware. So middleware is not next out specific middleware is next.js specific so please don't misspell the name of this file otherwise it's not going to work And now I'm gonna copy this snippet from here and I'm gonna paste everything inside of the middleware like this. And here's an important thing for you to understand about the middleware.
So I've seen a lot of misconception about this config matcher right here. A lot of people don't understand exactly what it does. Some people think that this is where you want to put your private routes. Some people think that this is where you should put your public routes. The truth is everything that you put inside of here will not be used to check whether it's public or private.
It's simply going to be used to invoke the middleware. So if I go ahead and add for example slash out slash login here, this is not going to be protected or public. This is simply going to invoke this function right here. Or if I write a long regular expression for a bunch of different things then everything will invoke the middleware. Right?
So let's try this out. So if I go ahead and add a console log of request next URL dot path name here and I'm going to give it a little string here so it's clearer to see and let's make sure that our app is running. There we go, it's running. And if I go inside of my auth slash login now, there we go. You can see that it says route auth slash login.
But if I go on register, you can see that I don't have that console log so the middleware was not invoked but if I go ahead and add slash out slash register here as well then in the terminal when I refresh the register page there we go you can see that the route is slash out slash register. So that's how the middleware works, right? So it's not black and white where you have to put your public routes here or where you have to put your private routes here. It is simply a matcher for anything you want to invoke the middleware. And as you can see from the documentation in here, in NextOut, we have a regular expression to invoke on every single thing, except this specific regular expressions, which we don't want to invoke.
But in my experience this is not the perfect regular expression. There is a better one and you've probably used it a lot of times if you followed my previous tutorials. And that is the regular expression from Qlrk. So I'm gonna paste the link in the description so you can find this page right here where you can find this matcher which I really like which is perfect for this project. The reason I like this matcher so much is because well if you've used Qlrk then you probably know that they are really the creme de la creme of developer experience and authentication.
So what I'm trying to do in this tutorial is come as close as possible to using Clerk, but in Next Health, of course. So let's go ahead and copy this matcher from here. If you cannot find it in the documentation you can also immediately go to my github and find it there. So I'm gonna replace my existing matcher with that matcher and now let's go ahead and see what's gonna be logged inside of our terminal. So I'm going to go ahead and refresh the register page and as you can see the register page is logged.
If I go to the login page now the login page is logged. If I go inside of slash then the slash is locked. If I go inside of slash API out providers, you can see that API out providers is locked. So what did we achieve here? We achieved that every single route except specific next static files and next images are going to invoke the middleware.
And this is the perfect use case for us. The reason I want it like this is because I rather want to manually... I want to invoke the middleware everywhere. So both on authorized routes, both on routes used to log in, both on private routes and also on public routes. And then in the middle where I'm gonna decide what I want to do with those routes.
Right? So you can see how we can easily get the is logged in status using request.auth and we can turn that into a boolean by adding two exclamation points here. So I'm going to add a new console.log is logged in to be is logged in like this. So let's go ahead and go inside of our terminal now and let's refresh the landing page and there we go you can see that the route is slash and is logged in is false. If I go to out you can see that the route is slash out slash login and is logged in is false.
So I'm gonna use the combination of the path name and the logged in status to decide what to do with the route that the currently logged in user is on. And this is another structure that I plan to use for this app. I want my entire app to be protected by default. The reason I want that because I feel that most applications work like that. So you are most likely going to have fewer public routes than private routes.
So it doesn't make sense that we have to write every single private route. Instead let's consider the entire application to be fully protected and it needs to be authorized to access it. And then we're going to separate just a couple of routes like a landing page, the documentation, something like that to be able to be accessed for non-authorized users. So that's what we achieved with this middleware here and well you just saw how easy it is to get some tokens from here. Alright, so I hope that kind of cleared up what the middleware is used for.
So it's not used for explicitly private routes or public routes. It can be used for anything you want to invoke the middleware. If you wanted to you can of course manually write every single route that we have inside but it's better to use a regular expression for this specifically because of this app folder API auth and in here we have a catch-all meaning that we don't exactly know which future routes or sub routes could be inside so by using a regular expression we made sure that we will invoke the middleware every single time any of those routes is being touched. What I want to do now is I want to go back to the upgrade guide here and I want to scroll a bit down and in here you're gonna find something called edge compatibility. So as you know we are using Prisma which by default does not work on the edge Which means that we are not going to be able to use a lot of callbacks and events inside of the auth.ts files which we would usually be able to if our database supported the edge.
But thankfully there is a solution for that and that is to separate out config and then use the config in the middleware so the middleware is the problematic part because middleware works on the edge so we can't use Prisma here so what we have to do is we have to create a file out.config.cs so let's go ahead and do that so I'm gonna create on the same level as out create a new file out.config.cs like this and let's go ahead and copy and paste this snippet here like this so we get the provider we get the type next out config and we export default an object with the providers which satisfies the next out config what we have to do next is go back inside of auth.cs file and now we can safely add the Prisma adapter which does not work on the Edge. So that's why we have to separate those two files so we're gonna use this file instead to trigger the middleware and not this one which will use the Prisma adapter. So let's go ahead and change what we need. We no longer need the GitHub import and we no longer need the providers.
Instead, we're going to import out.config from .slash out.config, or if you wanna be consistent, you can use the add sign, and let's simply spread the out.config like this, there we go. But we still have to add our prisma adapter so let's go ahead and add the prisma adapter from out prisma adapter make sure that you have this package installed so if you don't you can simply go into the terminal and run npm install auth prisma adapter like this but I believe that if I go ahead and install this we already have this I think we did it in the previous module so you can of course always confirm inside of your package.json it should be first, auth prisma adapter like this. So we have the prisma adapter and we also need our database util from .slash lib database or at .slash lib database. So let's go ahead and add the adapter to be Prisma adapter and pass in the database and we also have to change the session to use a strategy JVT. We cannot use the database session strategy That's why I didn't add the session model inside of our Prisma schema because with Prisma we cannot use the database session because it doesn't work on the edge.
We have to use JVT strategy here. And now that we modified this we also have to modify our middleware here. So it doesn't use this auth where we clearly use the non-edge supported prisma adapter so instead we have to use the auth config file to extract the auth middleware from it And we can do that very simply by following the instructions here. So inside of the middleware we have to import out.config from .slash out.config and we have to import next.out from next.out. And then we can destructure the out from next.out and out.config.
Let's go ahead and do that. We no longer need this import. Instead, we need the out config from .slash out config or at out config and we need next out from next out. And then what we can do is write const next out and pass in the out config. And then inside simply get the out.
And there we go. Everything should now work exactly as it worked before. So if I go ahead and open my terminal here and if I do, let me just close this one. So make sure you have npm run dev running. If I refresh, there we go.
Route is slash out slash login and is logged in is currently false because we are not logged in. Perfect! So everything seems to still be working but what we can do now is we can of course do some callbacks. I'm going to talk about callbacks later when we actually start you know implementing them but callbacks are extremely useful when you want something to trigger specifically on some next out actions like sign in, authorize, sign out, redirect, things like that. But we're going to explore that a bit later.
What I want to do now is I want to go ahead and I want to attempt to use this auth.ts file, specifically this auth constant export to see if I can get the currently logged in session. Obviously we are not logged in, so I think I already know what that's gonna look like, but let's just try for fun. So inside of the app folder, I'm gonna create a route group inside of parentheses called protected. And then inside, I'm gonna create a new folder called settings. So that's going to be our protected route in the future.
For now let's just give it a page.psx here and let's go ahead and export the settings page and let's write a div settings page. So you can find this by going to localhost 3000 slash settings directly. No need to go for the protected. I just wanna have an organizational folder where I'm gonna keep all of my protected routes so I know visually that they should be protected. So now go to localhost 3000 slash settings here and you should just see the text which says settings page like this.
So now what I wanna do is I wanna turn this into an asynchronous server component and I want to import out from at slash out. And then what we can do is get the session by using await out. And to render it here I'm simply going to use json.stringify inside of curly brackets. So json.stringify and passing the session like that. And there we go.
You can see that the current session is null like this, exactly as it should be. Perfect. So let's go ahead and do the following. If the user is logged out I don't want them to be able to access this settings route. So here's what I want to do.
I want to go ahead and I want to create a new file in the root of my application called routes.cs. So on the same level as out middleware completely out of outside of any folder that we have so far. And inside of here, let's go ahead and do the following. Let's export const public routes. So in here, we're going to write all the routes which we will allow logged out users to visit.
So obviously that's gonna be the landing page for now, like this. If you want to you can write a little JS document here. Let me just find how we write that. Like this. So you can write an array of routes that are accessible to the public like that these routes do not require authentication and you can give it a type of string.
So we're just practicing JS doc a bit. And now let's go ahead and do this. Let's export const auth routes. So these are the routes which will be used for authentication. So for now that is slash out slash login and slash out slash register.
So let's copy and paste the JS document here if you want to. You obviously don't have to. So this is an array of routes that are used for authentication and let's go ahead and write these routes will redirect logged in users to slash settings like this and let's go ahead now and let's write another one here export const API out prefix that's simply going to be a string slash API slash out so that's going to represent this file which we created here. API out. So inside of our middleware it's important we're not gonna add that manually to public routes but it's gonna be a special case so that we never block this API route.
It's important that this is always allowed to logged in or logged out users, they need to be able to access slash API slash out. So we can add a JS document for that as well to explain it briefly. So this is very simply gonna be the prefix for API authentication routes, like that. And I'm gonna write in here, routes that start with this prefix are used for API authentication purposes and the type is just a string without an array like that and to make our code a bit better let's also add export const default login redirect so this is going to be the place where we're going to redirect whenever the user is logged in unless specified differently. So let's add a little JS doc for this.
The default redirect the path after logging in and the type for that is a simple string. Like that. There we go. So now we have defined our first routes here and now what we can do is we can go back inside of our middleware .ps here and let's remove everything inside. And instead let's go ahead and let's import everything we need from our routes.
So import from at slash routes. We need the default login redirect, we need API out prefix, we need out routes and we need public routes like this. And then in here in the middleware I'm going to go ahead and destructure the next url so it's easier to access. I'm going to check if we are currently logged in by using a boolean of request.auth and then I'm gonna define if we are on auth route. So actually first let's do is API auth route.
So const is API auth route. So next URL.pathname.startsWith API auth prefix. Like this, Let me try and expand this a bit more. And you can see that because of our JS doc, we can clearly see what this means. The prefix for API authentication routes.
These are routes that start with this prefix and they are used for API authentication purposes. So we always want to allow these routes. That's why I want to have them in a special constant. So whenever the middleware hits any of those routes which are the following routes for example slash API slash out providers there is no reason for us to protect this obviously next out needs it to work properly right so make sure that you don't accidentally protect those routes so always confirm that your API out prefix is correct right here. Great!
Now let's go ahead and check if we are on a public route. So const is public route. That's going to be next that's going to be sorry public routes dot includes next url dot path name. So if the next url dot path name is any of the following so you can see that public routes is an array of routes which are accessible to the public these routes do not require authentication So this is how we're gonna know if the user is trying to access a route which is completely public and we are always gonna allow that. And lastly let's add const isAuthRoute.
So that's gonna be authRoutes.includes nextURL.pathName. Like this. So if it is authRoute that is an array of routes which are used for authentication This routes will redirect logged in users to slash settings like that So basically if the user is already logged in and they try to access the login screen, we're not gonna allow that. We're gonna redirect them back to the settings page. But we're gonna do the opposite if the user is logged out.
If they are logged out and they try to access the settings page, we're gonna redirect them to the Auth login page. So you can see how powerful the middleware can be when you allow it to be invoked on every single route that you can imagine. So now let's write this logic. So first thing we obviously have to allow is if is API out throughout. We don't even have to check if we are logged in or not in here.
Simply return null meaning do not do any action regarding this and you can go ahead and try this again by going into localhost 3000 slash api out providers and this should still work just fine. Now what I want to do is check if we are currently on an out route. So let's go ahead and write if we are on an out route is out route and then by default we're always gonna allow people to visit the auth route, right? But before we do that let's check if we are logged in. So if is logged in, in that case what we're gonna do is return response redirect new URL and in here we're gonna use the default login redirect.
So the reason I want to put that in a constant is so you can easily change it later if you change your mind and don't want to redirect user to the settings. If you want the dashboard to be the main route you can easily do that here and we're carefully going to use that in all the correct places. And whenever you use the redirect in the middleware and the new URL constructor you also have to pass next URL as the last argument here. So inside the new URL constructor make sure that you pass the next URL so it doesn't matter if you manually wrote slash settings like this you will still need to pass next URL and the reason we need to do that is so it creates an absolute URL. Because this is not an absolute URL.
But when you combine it with a second parameter, which is next URL inside of this, then that will create it into localhost 3000 slash settings, which is what we need. So you can use that. And I'm gonna bring this back to use the default login redirect here. Like this. So just by adding this, I believe nothing should be changed yet.
So if I go back to my homepage here, and if I click sign in, there we go. I can still visit the auth route. Why can I visit it? Because I am not logged in. So I'm not getting redirected to the settings page because I'm genuinely not logged in and I just want to log in first.
And then also the order of this if clauses matters so make sure that you do it in this exact order so first allow every single API route and then go ahead and check the auth routes So it matters because while the auth routes are technically public routes, remember we did not include them here. So we have to check them first before we check the public routes manually. Otherwise you're going to be left in an infinite redirect loop. So when you added this, make sure you've confirmed that you can go to localhost 3000 slash API slash out slash providers. Then when you added this, make sure that you can visit your out page right here.
This is how you're gonna help yourself if you have any errors. If you can see the exact thing that I am seeing everything is going fine. And now let's do the following. If we are not logged in and if we are not on a public route, in that case, we are gonna return response, redirect new URL slash auth slash login and pass in next URL as the second argument. And then outside of any if clauses by default we're gonna allow every other route.
So this is how we're gonna use our middleware as you can see. We're gonna invoke it on every single client and API route but on specific routes which we define inside of our file here like out login register or a slash page in that case we're gonna go ahead and do some different behavior right so you can see that we return null here which basically means allow this don't do anything if this happens So if the user is not on a public route, is on a public route, we're just gonna fall back to this. Meaning that there's nothing we have to do here, right? It's completely fine. But otherwise it's gonna start checking for logged in.
If it's not logged in and it's not on a public route we will redirect the user to the login page. Perfect! So let's try this out now. Here's what should happen. You should be able to see Auth login normally.
You should be able to see out register normally. You should be able to go to slash API slash out providers completely fine. But here is a route that you should not be able to visit. Localhost 3000 slash settings. If I go here I am immediately redirected back to the login page.
So make sure that inside of your routes, you didn't write the settings page in the public routes. But here's what happens if I add it to the public routes. So if I add settings to my public routes now, I can go ahead and visit the settings page. There we go. I can now visit the settings page.
So I believe this is quite a useful middleware which we have created. Just remove the settings from the public routes. And we have quite easy controls outside of the middleware itself because I feel like it's too cluttered to keep it all together inside of here. I believe it's complex enough to have this. Great!
So I really really like this middleware and I think we've pretty much mastered the middleware now, right? So I believe you know what it's time for. It's time for us to go back inside of auth.ts right here and to actually add, well not here, my apologies, the config and to actually remove the github provider for now and instead add the credentials provider which will finally allow us to call this login function and once we log in we will be immediately redirected to the settings page and once we log out from the settings page we're gonna get redirected back to here. First things first let's remove the github provider we don't need it like this instead let's go ahead and let's import the credentials from next slash out slash providers slash credentials like this and let's move this to the top right here and now I want to import the login schema from dot slash schemas So we already use the login schema inside of our login form and inside of our login server action here, right? But I'm gonna use it one more time in the credentials provider, because remember, in NextOut, just because we have this server action for login doesn't mean that every user will always use that.
There are definitely some users which can bypass our server action and not use this login screen at all, right? They can manually send information to the app API out if they want to. So that's why we also have to do the login schema check here in the providers. So in the providers go ahead and add the credentials. Open an object inside of here and let's write an asynchronous function authorize like that and it's going to give us the credentials in the props.
So inside of here I want to go ahead and validate the fields again. So const validated fields are going to be login schema.safeparse credentials like this. And then if validated fields are a success in that case let's go ahead and let's destructure the email and the password from validated fields dot data like that. And then what I want to do is I want to check if that the email which was passed in the credentials provider is actually connected to any user in my database so I know that I can check the password. So const user is gonna be await getUserByEmail from data user.
I'm gonna change this to the at sign and pass in the email. And then I'm gonna check if there is no user or if there is a user but there is no user.password. In that case I'm just gonna break this function. So how can it happen that the user has no password? Well, it can happen if they logged in using Google or GitHub.
So if they create an account using Google and GitHub and then they come around and try to use the credentials provider, we are not gonna allow that because they don't have a password. And in order for credential provider to work, we need to compare the hashed password inside of our database with the password that the user just passed. So if this passes, that means okay, this user registered using their name, email and password. So what I have to do next is check if the passwords match like this so let's write a wait and we have to import bcrypt here so let's import bcrypt from bcrypt.js or bcrypt I found in my development process that bcrypt.js has less errors because I actually had an error when I used bcrypt.js but you can try it out if you want to but I believe that I also use bcrypt.js inside of my register action So just confirm that you use it in the same place. So in the register I use bcrypt.js and in the out config I use bcrypt.js and just confirm that in your package.json you have bcrypt.js installed and also the types for bcrypt.js in dev dependencies.
All right, so now that we have that, what we can do is await bcrypt.compare and we're gonna compare first the password which the user just entered and then the hash from our database using user.password because remember that is a hash so this way we are confirming that they entered the correct password without us knowing what the actual password is because we're just comparing the hash we have no idea what is the actual password of the user perfect and if passwords match return the user like that And then go outside of this if function here and return null by default. There we go. So what we have to do now is we have to go inside of the Auth.cs and the same way we can export sign in we can also export sorry the same way we can export out we can export sign in and sign out and this can be used in server components or server actions that cool yes So now let's go ahead and do the following. Let's go inside of our actions and let's go inside of login.cs. So this is the place where we have to call that login function.
So first thing I want to do is remove this return here. And instead, let's use the validated fields.data and let's destructure the email and the password like that. And then let's go ahead and let's attempt to log in so I'm gonna go ahead and import sign in using at slash out so make sure that you added an export for that here and then I'm gonna wrap that inside of a try and catch block so I'm just gonna to do this and all we have to do in the try block is a wait, sign in give it the type of sign in which in our case is credentials here and go ahead and give it an email and a password and let's go ahead and write redirect to to be default login redirect from out routes from at slash routes like this. So this will be the settings page like this. So later what we're gonna do is we're gonna have a callback URL or that.
So that's why I'm manually defining this here. So we don't have this yet but later when we implement the callback functionality, we're gonna add that here. So that's why we need this field. Usually, I believe this is still gonna work if you just don't add a redirect to. But if you have a redirect to and the callback URL is null, then it will not redirect.
So it's just going to be weird, right? So that's why I'm adding redirect to default login redirect. And it's explicit, so I like it. It's like telling me, all right, when you log in, this is where you will be redirected to. So I don't have to think, you know, okay, I have to think about my middleware now and I have to think Okay, so once they get logged in this is what will fire and then that will redirect me to here, right?
Technically, I just know that because we just wrote it but in here it's more explicit so I like it this way. And then in here we have to check if error is the instance of auth error. Is it auth error? Auth error. I'm just not sure where we can import this so I think that we can import outError from nextOut there we go, so import outError from nextOut So if the error is an instance of AuthError, we can open a switch case on the error.type here and if the case is...
Let me just see, is it case? Yeah, without the colon. So if the case is... Let's see why is it not auto-completing... There we go.
So you can see we have a bunch of different cases that you can cover but I'm just going to focus on the credential sign in here. So if this is the case I'm going to return an object with an error invalid credentials like this. Let's give it a default case the return an error of something went wrong like that and what's important when using sign in inside of server actions is that inside of the catch function at the end of this if clause you also throw the error back otherwise it will not redirect you So make sure you add throw error. They do this also in the official Next.js course. So I'm not sure if this is a bug or a behavior, but yeah, you have to throw an error, otherwise it will not redirect you to the login redirect, which in our case is the settings page.
So first I want to test the invalid credentials one out. So I believe that this is technically already working but let's just try it out. So I'm gonna write a random email here and a random password and now I believe I should get an error invalid credentials. There we go. It says invalid credentials.
So if you remember your email and your password you can enter it. I believe I have an email newmail.com or newexample.com and my password was 123456 and I think there we go. You can see that this redirects me to the settings page. So it means that I'm officially logged in and you can see my session here because remember in the settings page if I go inside of app protected settings in here you can see that we evade out and JSON stringify the session meaning that I am logged in and now if I go and try and go to the landing page I can still see this because this is a public route but if I click sign in you can see that I'm redirected to the settings page that's because of that part inside of our middleware file so inside of where is it middleware right here if it is the auth route and if we are logged in we redirect the user back to the settings like that so we handled so many cases with our middleware I really really like how we did this. What we have to do now is we have to add a logout button so that you we can actually clear our cache and stuff right.
So inside that's going to be very simple so make sure that inside of your out.cs You added an export for sign out and then inside of your app folder protected settings page.tsx go ahead and add a form here and add a little button which will just say sign out. Give it a type of submit and give this an action to be an arrow function. Make sure it's an asynchronous arrow function. Add and use server here and simply call await sign out from at slash out. As simple as this.
So this is how you can use the sign out function in server components. Yes, you can also use that inside of client components but not by importing from here. So this is exclusively for server components, server actions and stuff and basically all side server things. But don't worry later I'm going to show you how you can also sign out and sign in using completely client components. So no need for server actions at all.
Great! So I believe that if I click sign out here, I should be redirected to the out page. And there we go! And if I try and go manually to slash settings again, I'm redirected back to the settings page. Great!
We officially implemented login. Let's go ahead and create a new account here so I'm gonna call this test. Test at mail.com 123456. Create an account. Great!
Let's go ahead and here let's use test at mail.com 1, 2, 3, 4, 5, 6, 7. That should give me invalid credentials and if I remove one that should log me back in. There we go! You can see my exact information here. Perfect!
So what I want us to learn next is how to extend this session object with a couple of more stuff, right? Because name and email is not enough. We also need the ID. We also need the role. We need a bunch of more things inside of our session.
And thankfully, NextOut has callbacks which can do that. So that's what we're gonna learn in the next module. This was a very long chapter, but I hope it cleared up some doubts that you had in the middleware and how all of that stuff works. So great, great job and see you in the next chapter.