Next.js App Router Authentication (Sessions, Cookies, JWTs)

leerob
4 Feb 202411:31

Summary

TLDRIn this video, the presenter demonstrates how to implement basic session authentication in Next.js without additional libraries, focusing on creating, managing, and securing sessions using cookies and JWTs. The tutorial covers essential aspects such as login, logout, and session refresh, highlighting the use of Next.js functions and middleware. Additionally, the video explores using the NextAuth.js library for more advanced and abstracted authentication, supporting multiple providers like GitHub. The presenter emphasizes the importance of securing secret keys and touches on future updates and deeper topics like authorization and database sessions.

Takeaways

  • 🔐 The video covers basic session authentication in Next.js without additional libraries, as well as other options if you prefer not to build your own authentication system.
  • 🖥️ The example begins with a simple Next.js application setup, showing how to handle sessions in the root layout and index route.
  • 📋 The session management involves setting up a login function that processes form data, creates a session object, and stores it as an HTTP-only cookie using Next.js's cookies function.
  • 🔒 Encryption of the session data is handled with the Jose library, which signs the JWT (JSON Web Token) using a secret key. This key should be kept secure, ideally in an environment variable.
  • 🕒 The session expiration is managed by updating the session cookie every time the user interacts with the application, ensuring it doesn't expire prematurely.
  • 🛠️ Middleware is used to refresh the session on every request by decrypting the session data, updating the expiration time, and setting a new cookie.
  • 📂 The video also demonstrates how to read the session information from the cookies using a getSession function, allowing the application to display user-specific data.
  • 🚪 The logout function simply deletes the session cookie, effectively logging the user out.
  • 🧩 The video contrasts the basic custom authentication setup with the more robust NextAuth.js library, which provides built-in support for various authentication providers like GitHub.
  • 📚 The video concludes by mentioning additional resources and documentation on more advanced topics like authorization, protecting server actions, and integrating with other popular authentication libraries like Auth0, Supabase, and Clerk.

Q & A

  • What is the primary focus of the video?

    -The primary focus of the video is to demonstrate how to implement basic session authentication in Next.js without using any additional libraries, followed by an introduction to using NextAuth.js for more complex authentication setups.

  • What is the purpose of the `login` function in the code example?

    -The `login` function handles user authentication by processing form data, creating a session for the user, and setting it as an HTTP-only cookie. This session is encrypted using a JSON Web Token (JWT) before being stored.

  • Why is the session stored as an HTTP-only cookie?

    -The session is stored as an HTTP-only cookie to ensure that it can only be accessed by the server, enhancing security by preventing client-side scripts from accessing the session data.

  • What role does the `encrypt` function play in the authentication process?

    -The `encrypt` function is responsible for signing and encrypting the JWT, which contains the session data. This ensures that the session information is secure and can only be decrypted by the server.

  • How does the middleware in Next.js contribute to session management?

    -The middleware runs before every request in the application. It updates the session expiration time by calling the `updateSession` function, which refreshes the session if a valid session cookie is present.

  • What happens when the `getSession` function is called?

    -The `getSession` function reads the session cookie, decrypts it, and returns the session data. This allows the application to retrieve information about the logged-in user, such as their email address.

  • How does the logout process work in this authentication setup?

    -The logout process involves calling the `logout` function, which deletes the session cookie using the `cookies` function in Next.js. This effectively logs the user out by removing their session data.

  • What is the advantage of using NextAuth.js over the custom authentication setup?

    -NextAuth.js provides a higher level of abstraction, simplifying the implementation of authentication by offering built-in support for various providers like GitHub, Google, and others. It handles many aspects of authentication, including session management and route protection, without requiring the developer to write as much custom code.

  • How does NextAuth.js manage sessions differently from the custom setup?

    -NextAuth.js abstracts the session management by automatically handling session tokens, CSRF protection, and session refreshes. It also offers a middleware with configurable options to control when and where the session management should run.

  • What are some key differences between cookie-based sessions and database sessions?

    -Cookie-based sessions store session data directly in the client's cookies, often as an encrypted JWT. Database sessions, on the other hand, store session data on the server side in a database, with the client only holding a session identifier. This can provide additional security and scalability benefits, especially for larger applications.

Outlines

00:00

🔐 Introduction to Authentication in Next.js

The video begins by introducing the topic of authentication in Next.js, emphasizing that it is a broad topic with many facets. The focus of this video is on demonstrating basic session authentication without relying on additional libraries. The video will cover logging in and out, session handling, and provide a brief overview of other available options. The speaker mentions that the code and documentation will be provided in the description, and the application has been set up locally to guide through the authentication process.

05:04

📄 Setting Up Basic Authentication

The speaker dives into the basic setup for authentication, starting with the root layout and index route. The session-based authentication is implemented by creating and managing session cookies. The process involves logging in, retrieving session data, and displaying user information. The code uses server actions to handle login and logout, where the session information is stored in an encrypted cookie. The encryption is done using the Jose library to create a JWT (JSON Web Token) and securely store it. The expiration of the session is managed by setting an HTTP-only cookie, ensuring security by restricting access to the server side only.

10:05

🔄 Managing Sessions and Middleware

The video continues by explaining how session management is handled, particularly the update of session cookies with every request. The middleware file is responsible for running before every request, calling the updateSession function to refresh the session. The decrypt function is used to verify the JWT, ensuring that the session is legitimate before it is updated. The getSession function retrieves session information by reading the cookies, allowing the application to manage user sessions efficiently. The logout process is also covered, showing how the session cookie is deleted, effectively ending the session.

🛠️ Implementing Authentication with NextAuth.js

The speaker introduces an abstraction layer using the NextAuth.js library, which simplifies the implementation of authentication. This library supports multiple authentication providers, such as GitHub, Google, and Discord. The example demonstrates how to set up authentication using the GitHub provider, including sign-in, sign-out, and route handling. The code is structured similarly to the previous example but is more abstracted and flexible, allowing for easy integration of various providers. The middleware configuration is also explained, ensuring that session refreshes only run on specific routes, excluding static files and images.

📚 NextAuth.js Updates and Future Considerations

The video concludes by mentioning that the version of NextAuth.js used in the example is a beta version, which may have become stable by the time viewers watch the video. The speaker briefly discusses the depth of the authentication topic, touching on authorization and the importance of protecting server actions and route handlers. The video primarily covered cookie-based sessions, but other methods like database sessions were mentioned. The speaker encourages viewers to explore further resources, including new documentation and examples using various popular authentication libraries, and invites feedback on what topics to cover in future videos.

Mindmap

Keywords

💡Next.js

Next.js is a popular React framework used for building web applications. It offers features like server-side rendering and static site generation, making it ideal for performance-optimized and SEO-friendly websites. In the video, Next.js serves as the core platform for implementing authentication, demonstrating its flexibility and power in managing both the front-end and back-end logic.

💡Session Authentication

Session authentication is a method of maintaining a user's authentication status by storing session data on the server, typically in a cookie. In the video, basic session authentication in Next.js is shown, where user data is stored in a session cookie that is encrypted and managed server-side, ensuring secure user identification across requests.

💡JWT (JSON Web Token)

JWT is a compact, URL-safe token format used for securely transmitting information between parties as a JSON object. It is commonly used for authentication purposes. In the video, JWTs are encrypted and stored as cookies to manage session data, allowing the application to verify and maintain user sessions securely.

💡Cookies

Cookies are small pieces of data stored on the client's browser, used to track information like user sessions. In the video, cookies play a critical role in managing session authentication, where the session data is stored as an HTTP-only cookie, ensuring that it is accessible only by the server and not exposed to client-side scripts.

💡Middleware

Middleware is a function that intercepts requests and responses in a web application, often used for tasks like authentication, logging, or input validation. In the video, middleware in Next.js is used to update and refresh the session cookie with each request, ensuring the session remains active as long as the user interacts with the application.

💡Encryption

Encryption is the process of converting data into a coded format to prevent unauthorized access. In the context of the video, encryption is used to secure the JWT before storing it in a cookie, ensuring that sensitive session information is protected from being easily read or tampered with.

💡NextAuth.js

NextAuth.js is a library that provides authentication solutions for Next.js applications. It supports various providers like GitHub, Google, and more, simplifying the implementation of authentication features. The video demonstrates how NextAuth.js can be used as an abstraction layer on top of the basic authentication setup, offering a more streamlined and flexible approach to handling user authentication.

💡Server Actions

Server actions are functions that handle specific tasks on the server side, such as processing form submissions or managing authentication workflows. In the video, server actions are used to handle login and logout processes, interacting with the session cookie to either create or destroy user sessions based on user inputs.

💡Form Data

Form data refers to the data that is submitted by users through forms on a website. This data is processed on the server to perform various actions, such as logging in a user. In the video, form data is extracted and used in the login function to identify the user and initiate the session, illustrating how user inputs drive the authentication process.

💡Route Handlers

Route handlers are functions that manage requests to specific endpoints in a web application, determining how the application responds to different URLs. The video shows how route handlers are set up in Next.js to handle authentication routes, such as login and logout, providing a structured way to manage different parts of the authentication process.

Highlights

Introduction to basic session authentication in Next.js without additional libraries.

Exploration of Next.js root layout and index route setup for authentication.

Explanation of using cookies for session management, including setting and deleting cookies.

Introduction of JWT (JSON Web Token) encryption using the 'Jose' library.

Discussion on securing JWT with environment variables to prevent exposure of secret keys.

Demonstration of session expiration and cookie handling in Next.js.

Overview of the 'updateSession' function and its role in refreshing sessions.

Insight into the decryption process for verifying and decrypting JWTs.

Explanation of the 'getSession' function for retrieving session information from cookies.

Comparison of basic session authentication with a NextAuth.js abstraction.

Introduction to using NextAuth.js with GitHub as an authentication provider.

Discussion of middleware configuration in NextAuth.js for route handling and session refreshing.

Explanation of different authentication strategies, including cookie-based and database sessions.

Mention of alternative authentication libraries like Clerk, Lucia, Auth0, and Supabase.

Closing remarks on the depth of authentication topics, including authorization and protecting server actions.

Transcripts

play00:00

Let's talk about authentication in Next.js.

play00:02

This is a broad topic, and there's a lot that we could talk about.

play00:05

In this video, I'm going to cover showing how to do basic session authentication in

play00:10

Next.js without any additional libraries.

play00:13

Then, I'll also show some other options you can use too, if you don't want to roll your

play00:17

own auth.

play00:18

So, let's get into it.

play00:19

The code for this video will be in the description, and we've also published new docs for both

play00:23

the pages and the app router, so go check those out.

play00:26

But what I've done is I've cloned this application locally.

play00:29

I've got it up in my editor, and we're just going to talk through some of the bits here.

play00:32

First, we have our root layout, which hasn't changed from setting up a hello world Next.js

play00:37

app.

play00:38

This is just the HTML in the body of our application.

play00:40

And then, I have our index route.

play00:42

So, I have our page file denoting that route.

play00:44

This is a server component, so we've marked it as async, and we're awaiting getting the

play00:50

session for our application.

play00:51

If there's a user, we're going to print out information about the user here; otherwise,

play00:56

we're just going to say it's null.

play00:57

Then, we have two different forms here.

play00:59

We have one form that allows the user to log in, and it calls the server action.

play01:03

It calls this login function and then redirects back.

play01:07

And then, we also have the same thing, basically, to log out.

play01:10

So, this is just a basic scaffolding of log in, log out.

play01:13

There's, of course, a lot more that we can do here, but the real meat of understanding

play01:17

the basics of authentication is going to be in the login and logout functions.

play01:23

So, we've moved all of this library, everything related to authentication, into this one lib.ts

play01:29

file.

play01:31

Let's start with login.

play01:32

So, the login function that gets called over here, I'll just type in [email protected], hit

play01:40

enter to submit our form, and we see this information that is logged out on the right.

play01:46

This login function is called; it takes in the form data.

play01:50

I can read information from the form, like the email.

play01:53

I can put some other additional information here on the user object in your application.

play01:57

This is where you would probably talk to a database and look up information about the

play02:01

user.

play02:02

And once we get that information back, then we get to create our session.

play02:07

So, we're going to define when we want it to expire through a new date.

play02:12

We're going to make this session object, which is going to be encrypted, and it takes the

play02:17

user and the time that it expires, and then we set this as a cookie.

play02:22

So, Next.js has this cookies function that allows you to set and delete cookies.

play02:27

So, we set this with the name of session, we pass along the session, we say when it

play02:33

expires, and critically, we say this is an HTTP-only cookie, so you can only read this

play02:38

on the server.

play02:39

Now, we skipped over this encryption part, but this is really important.

play02:42

So, if we go up to encrypt, you'll see that we're doing a couple of things here.

play02:49

This is an asynchronous function.

play02:50

It takes in the payload for our JWT, or JSON Web Token, and we're going to call this function

play02:58

from this library here, Jose, which is going to allow us to sign the JWT based on the payload

play03:08

and the algorithm that we want, when it was issued, when we wanted it to expire at, and

play03:13

then the secret key that we're going to use for that encryption.

play03:17

Now, here I've just defined it up top.

play03:19

In your application, you probably want this to be an environment variable or something

play03:23

that people wouldn't have access to, so definitely don't want this value to get exposed.

play03:28

So, we take this, this is what's actually going to encrypt that JWT.

play03:32

So, let's take a look at what that looks like in my browser.

play03:35

I'm going to open up devtools, and I'm going to reload the page.

play03:39

There's no session right now because it had expired.

play03:42

So, I'll do [email protected], I'll hit log in, and we set this session key here.

play03:48

So, let's take this value, this encrypted JWT, and let's pop on over to jwt.io.

play03:54

So, I've pasted this in here, and we see on the right, it determines what the algorithm

play03:59

was, it shows the payload of the data, and then it says, "Hey, if you want to verify

play04:03

the signature, you need to put in that secret bit."

play04:06

So, this is just a nice way of being able to kind of visualize that data, just a helpful

play04:10

little tip.

play04:11

So, the session is stored as a cookie here, and we said it expired in 10 seconds.

play04:15

So, when I reload the page, it's expired, that cookie is no longer there; it's done.

play04:22

If I log in again, [email protected], and I reload, what you're going to notice is that the value

play04:31

of "expires" is getting updated every single time, and you would also see that reflected

play04:36

in the decrypted value of the JWT that we're storing.

play04:40

So, how is this happening, and why are we doing this?

play04:42

Well, if we pop back over to our application code, and we look at the middleware file,

play04:47

this file is going to run in front of every request in our application, and it's calling

play04:52

this function.

play04:53

It's taking in the web request, and it's calling "update session" with that web request.

play04:59

So, let's pop back into our authentication file, where we've been kind of building our

play05:03

own auth library, and we have updateSession.

play05:07

So, it takes in that request, NextRequest is just an extension of the web request, takes

play05:13

in that request, it looks at the cookies.

play05:16

If there's no session, if there's no session cookie provided, you can just return back;

play05:20

otherwise, refresh that session so it doesn't expire.

play05:24

So, we decrypt that value from the session, we set a new expiration time, we tell NextResponse

play05:32

that we're going to produce a response, a web response from this, and then on that response,

play05:37

we set a new cookie.

play05:38

Now, the bit that we skipped over here was the decrypt function.

play05:43

So, let's go take a look at that.

play05:45

Decrypt takes in this input, it uses Jose as well, too, to verify, based on the input,

play05:52

based on the key, based on the algorithm that we encrypted it with.

play05:56

If this, you know, is legit, we're going to decrypt it and return back the payload.

play06:00

So, that happened down here, where we got back the value from decrypt, and then we were

play06:05

able to update the cookie.

play06:07

To round out our auth implementation, we need to read information about the request.

play06:11

So, we talked about this getSession function when we first looked at the page, but what

play06:16

exactly was this doing?

play06:17

Well, really, it's just reading from the cookies.

play06:20

So, we already showed how we were setting the JWT as a cookie for our session; all this

play06:25

function is doing is just reading from the cookies, looking for that session value, and

play06:29

then decrypting the value.

play06:31

So, that's how, inside of here, again, if I go back to the browser, I do example.com,

play06:37

this could look at my database or something.

play06:39

That's how this getSession function is able to get back information about the session.

play06:44

Now, if I click log out with the server action, what's going to happen, if you watch my console

play06:50

over on the right side, you see that the cookie was deleted.

play06:54

So, it was removed out of my cookies.

play06:57

And if we click into the logout function, all this was doing was calling the Next.js

play07:03

cookies function, and it was essentially destroying the session.

play07:07

So, this file is really all it takes for the most minimal session-based authentication

play07:14

inside of a Next.js application.

play07:16

You're reading your values inside of your page, you are using a middleware to refresh

play07:22

that information, and it, of course, can get way more detailed than this.

play07:26

But I think it's helpful to step from just a really basic example, and we can add complexity

play07:31

on top from there.

play07:32

Now, I want to show what an abstraction on this model looks like.

play07:36

So, the basic model I showed is effectively a very light version of NextAuth.js, which

play07:42

is a popular community library.

play07:45

And I want to walk through another example that uses the same setup but using NextAuth.js.

play07:50

So, I've got that example open here on the left, and I've got it running in my browser

play07:54

on the right, and we're going to see, you know, a lot of similar things, just one layer

play07:59

of abstraction higher.

play08:00

So, I have this auth file, auth.ts, it's going to set up some sign-in, sign-out, auth methods,

play08:07

and also some route handlers for our application.

play08:11

And it's going to say that we're using the GitHub provider for auth.

play08:14

Those route handlers are under api/auth/[...nextauth].

play08:18

So, this catch-all route that is going to scaffold a bunch of those route handlers for

play08:23

us, for the library to use.

play08:25

So, we take the GET and the POST from that, you know, central auth setup, and we scaffold

play08:32

out these routes.

play08:34

And then, back in auth, we don't really have to do anything else to get this working with

play08:38

GitHub, but since this is, again, a layer of abstraction higher, this works with a bunch

play08:42

of different auth providers.

play08:43

It could be GitHub, Google, Discord, really any provider you want to use.

play08:48

So, let's go look at the index route in the page.

play08:51

So, for our page, we are calling await auth, which is basically similar to getting the

play08:57

session.

play08:58

This was the value that was exported from our auth file.

play09:01

From the session, we get the user and the email, and then we render out this information

play09:06

below.

play09:07

So, I click sign in with GitHub, I've already configured and authenticated to say, "Yes,

play09:11

I authorized GitHub," so it skipped the modal, but I say, "Okay, welcome, my email address

play09:16

here."

play09:17

I can click sign out, and when I look at these other components, they're very similar.

play09:23

They're forms that have a server action.

play09:25

They call a signin function or a sign-out function.

play09:28

The signin one takes in a string, which is the provider that I'm using, in this instance,

play09:33

GitHub, and sign out just, you know, deletes the session, basically.

play09:37

So, for example, if I open up the cookies, this is for localhost:3001, running on a different

play09:44

port.

play09:45

Making this a bit bigger, we can see there were three cookies created.

play09:48

There's the session token, which is that encrypted JWT; there's the callback URL, and then there's

play09:53

also a csrf token for increased security.

play09:56

So, this is all abstracted away for us; we don't need to do anything here.

play10:00

Just like in the previous example, there's a middleware, so that the session can be refreshed

play10:03

when you reload the page.

play10:05

This one also includes a config option, with a regex for what routes we want this to run

play10:10

on, so it's not going to run the middleware on static files, or next/image, or on the

play10:15

favicon.

play10:16

So, that's probably good to also include as well, too.

play10:18

It's worth noting that, depending on what time you're watching this video, these changes

play10:22

might already be stable.

play10:23

I'm using the latest beta version of the NextAuth.js package, that's been totally refactored for

play10:28

the app router, to really simplify things.

play10:31

So, the code for this is down below, if you want to get started on this version.

play10:34

It might already be stable by the time you watch it, though, so just wanted to quickly

play10:37

mention that, too.

play10:38

The topic of authentication goes super deep.

play10:41

There's not only authentication; there's also authorization.

play10:44

So, we cover some of this in our new docs.

play10:46

We talk a little bit about authorization and protecting server actions, protecting route

play10:51

handlers.

play10:53

In this video, we talked about cookie-based sessions, but there's also database sessions,

play10:57

and, you know, there's really a ton of stuff here.

play11:00

We also include a bunch of examples with other popular authentication libraries, whether

play11:05

it's using Clerk, Lucia, Auth0, Supabase, or any of these here.

play11:10

Worth checking out, if you'd like to see us talk more about authentication.

play11:14

Definitely let me know in the comments what you want to see with Next.js and AuthA, or

play11:18

AuthZ.

play11:19

We can go in more deep context here, but hopefully, this was a good introduction into just a very

play11:25

basic cookie-based session example.

play11:28

Let me know what you thought.

play11:29

Peace!

Rate This

5.0 / 5 (0 votes)

Связанные теги
Next.jsAuthenticationWeb DevelopmentSession ManagementNextAuth.jsGitHub LoginJWTCookiesMiddlewareJavaScript
Вам нужно краткое изложение на английском?