DEV Community

Cover image for NextAuth.js: An easy way to add authentication to your Next.js project
Jaime
Jaime

Posted on

NextAuth.js: An easy way to add authentication to your Next.js project

Recently, I needed to add session management to a Next.js project and came across NextAuth.js. It’s a pretty solid library that simplifies login, logout, and session handling.

Here are the steps I followed:

1. API Auth Route Handler

First, create the following file:

api/auth/[...nextauth]/route.ts
Enter fullscreen mode Exit fullscreen mode

And add this content: (you can customize it based on your provider and config needs)

import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";

type UserToken = { id: string; name: string; email: string };

const handler = NextAuth({
  providers: [
    CredentialsProvider({
      name: "Credentials",
      credentials: {
        username: { label: "Username", type: "text", placeholder: "admin" },
        password: {
          label: "Password",
          type: "password",
          placeholder: "1234",
        },
      },
      async authorize(credentials, req) {
        return { id: "1", name: "Admin", email: "[email protected]" };
      },
    }),
  ],
  secret: process.env.NEXTAUTH_SECRET,
  callbacks: {
    async jwt({ token, user }) {
      if (user) {
        token.user = user;
      }
      return token;
    },
    async session({ session, token }) {
      session.user = token.user as UserToken;
      return session;
    },
  },
});

export { handler as GET, handler as POST };
Enter fullscreen mode Exit fullscreen mode

This is the main configuration file, and it defines a few key things:

  • Provider

NextAuth.js supports multiple providers. For this simple demo, I’m using Credentials, which is super handy when you already have a login system in place. It basically lets you plug directly into your existing auth service.

  • authorize

This function is where you hook into your internal login service. If it returns an object, NextAuth.js treats it as a successful login and creates a session. If you return null, it means login failed.

Note: providers is an array—so you can support multiple login methods, like Credentials (custom login), Google, GitHub, etc.

  • JWT

This callback attaches the user data returned by authorize to the token. You can include whatever you want inside the token here. That token will later be used to build the session.

  • session

This is where the session is created using the token. You’ll see how the user info gets added to the session object. This is what your app can access using the useSession() hook on the client side.

For this demo, I’m not calling any real auth service. Just passing a user and password is enough to simulate a session. But in a real-world scenario, you’d call your actual login API inside authorize, and then return the user object (or null on failure).

2. UI Updates

Now that the provider setup is done, the next step is to implement the UI components. In this case, I only have two components:

  • Page

A very simple page that uses 'use client' (required for client-side hooks like useSession) and wraps everything in SessionProvider:

"use client";

import { SessionProvider } from "next-auth/react";

import LoginButton from "./login-btn";

export default function Page() {
  return (
    <SessionProvider>
      <LoginButton />
    </SessionProvider>
  );
}
Enter fullscreen mode Exit fullscreen mode

Note: The LoginButton component uses useSession, so it needs to be inside a SessionProvider.

  • LoginButton

A very simple LoginButton component that uses useSession to either show a Sign In or Sign Out button depending on the session state:

import { useSession, signIn, signOut } from "next-auth/react";

export default function Component() {
  const { data: session } = useSession();

  if (session) {
    return (
      <div>
        <p>
          Signed in as <strong>{session.user.name}</strong>
        </p>
        <button onClick={() => signOut()}>Sign out</button>
      </div>
    );
  }

  return (
    <div>
      <p>Not signed in</p>
      <button onClick={() => signIn()}>Sign in</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

And that’s it—you’ve got a simple login system in place using NextAuth.js

Sign In Using NextAuth.js

Default Login Form

Sign Out Using NextAuth.js

Demo

Make sure to check out the Website and take a look at the Codebase.

Thanks for reading!

Top comments (0)