So, you want to add authentication to your Next.js app and figured Auth.js might be the right tool; however, you’re not sure how to get started. No problem. In this post, I’ll break down the steps to get you up and running.
Auth.js, formerly known as NextAuth.js, is a flexible authentication library that works with most modern web frameworks such as Next.js, SvelteKit, and Express.
Auth.js makes it easy for you to implement authentication and authorization logic in your project. Let’s jump into the steps, but before we do, If you want a break down of the difference check out this article: Authentication vs Authorization: The Dynamic Duo of App Security Explained
Authentication Steps
(This tutorial uses TypeScript, but if you are using JavaScript, change the .ts files to .js)
1. Install the Auth.js package
Install the package via the code below:
npm install nextauth@beta
2. Generate a secret via the auth CLI
Auth.js has one mandatory environment variable, AUTH_SECRET
. This variable should contain a random value that will be used by the library to encrypt the token & email verification.
Auth.js has A CLI tool that will generate the secret and create a .env
file for us.
Use the code below to generate the secret.
npx auth secret
3. Create a config file and Setup the provider
We now need to create an auth.ts
configuration file. This file will configure Auth.js to use the provider (GitHub in our case) and manage the authentication in the app.
- Create a
src/lib/auth.ts
file. - Import
NextAuth
&GitHub
(or whichever provider you want if not GitHub) - Destructure & Export the methods (
handlers
,signIn
,signOut
,auth
) returned from thenextAuth
function call.
import NextAuth from 'next-auth';
import Github from 'next-auth/providers/github';
export const{ handlers, signIn, signOut, auth } = NextAuth({
providers:[Github], // or the provider(s) you need.
})
Note
- You can name the auth.ts file whatever you want & place it wherever you like, however it’s a good idea to stay consistent.
4. Create a […nextauth] API route
Auth.js needs an API endpoint to handle authentication requests. Let’s handle this by creating a route at /app/api/auth/[…nextauth]/route.ts
. […nextauth] filename is a special catch-all route.
This route receives all auth-related requests (like sign-in, callback, sign-out) and it’s how we call the auth handlers from the auth.ts file.
The NextAuth
function returns the handlers, then the [...nextauth]/route.ts
file uses them, so Auth.ts can run on any incoming request.
/*
* imports the handlers from NextAuth via the auth.js
* file we just created.
*/
import { handlers } from "@lib/auth";
export const { GET, POST } = handlers;
Note
- The name must be written exactly like this ‘[…nextauth]’
- This file must be an App Router Route Handler, however, the rest of your app can stay under
page/
if you’d like.
5. Create a server action file
In this step, we’ll create a server action. A server action is a special function that runs securely on the backend but can be called from a client component.
Here’s how we’ll set it up:
1. First, create a server action file /src/app/action/next-auth-actions.ts
.
2. Import the next auth signIn
& signOut
functions from Auth.ts.
3. Now, we’ll wrap these in our own async functions (like loginAction and logoutAction) that:
- Call the Auth.ts functions
- Handle the redirect after success
4. Finally, let’s export them so any component can use these ready-made auth actions.
Note
- A server action file must have the
"use server"
directive at the top of the file.- In a project where you are using both email and auth.js you can place this functionality in the /src/action/auth-actions.ts file
'use server';
import { signIn, signOut } from '@lib/auth';
export async function NextAuthLogin() {
await signIn('github', { redirectTo: '/dashboard' });
}
export async function NextAuthLogout() {
await signOut({ redirectTo: '/' });
}
Server Action Files Info
- Server Action files can be named anything & placed anywhere.
- Server Actions allow the client component to access the functionality of the server-side code.
- Async functions
- CRUD functionality
- Secure API calls
- etc
6. Create a login page route
Next we need to create a login page route. This is where we will setup the form that the user will interact with in order to login in to our auth flow. To do this we need to use the NextAuthLogin action that we just created. Remember NextAuthLogin is an asynchronous function that called Auth.js signIn function.
The key here is how we call our server-side async function from our client-side login component. While client components themselves can’t be async functions, they can trigger async operations like server actions within thier event handlers.
This is where the Server Actions come in to play, they provide a seamless way to call server code directly from your client components.
1. First, create a login route, I’m placing mine at /src/app/(auth)/login/page.tsx.
2. Import the NextAuthLogin function from the /src/actions/next-auth-actions.ts file.
Example
'use client';
// for next auth login function
import { NextAuthLogin } from '@app/actions/auth';
export default function Login() {
return (
<>
<main>
<button onClick={() => NextAuthLogin} >
Sign in With GitHub
</button>
</main>
</>
);
}
3. Lastly, We need to create a button and assign an anonymous function to it’s onClick event handler that then calls the NextAuthLogin function.
Client component info
- Client components aren’t
async
, but their event handlers can be.- Authentication logic must securely run on the server side.
7. Register an OAuth Provider (GitHub)
In this step we need to register the OAuth provider. Since I coved this in a recent post I have added the link here. GitHub OAuth: How to register an app
By following these steps you now have the knowledge to implement authentication logic in your Next.js app using Auth.js. The next step is deciding which resources a user can have access to. You can learn more about authorization in this article: How to Add User Authorization to Next.js with Auth.js.
If you enjoyed this article feel free to give me a shout on one of my social media channels.