homearrowBlogsarrowHow to use NextAuth.js & why use API routes?
Web Development

How to use NextAuth.js & why use API routes?

author

Codenova

Blockchain & Web Development Company

Last updated onFeb 11, 2026
How to use NextAuth.js & why use API routes?

➤ What is NextAuth?


NextAuth.js is a free and open-source library that makes adding authentication to your Next.js apps simple and hassle-free. It’s super flexible, works with tons of login providers (like Google, GitHub, and more), and fits perfectly with Next.js’ serverless setup. Whether you need basic login or more advanced features like managing user roles, NextAuth.js has you covered.



➤ Key Features of NextAuth:



1. Multi-Provider Authentication:


  • Supports OAuth providers like Google, Facebook, GitHub, Twitter, etc.
  • Allows email/password-based sign-ins and “Magic Link” email authentication.
  • Can integrate with custom authentication systems using custom OAuth or credentials.



2. Session Management:


  • Provides built-in methods to manage user sessions on both client and server sides.
  • Supports JWT-based sessions or database-persistent sessions.



3. Secure by Default:


  • Ensures secure handling of authentication workflows.
  • Implements protections against common vulnerabilities like CSRF (Cross-Site Request Forgery).



4. Serverless Ready:


  • Works seamlessly with serverless environments.
  • Leverages Next.js API routes for authentication endpoints.



5. Customizable and Extendable:


  • Provides a wide range of configuration options for session behavior, callbacks, and events.
  • Offers middleware support for access control and token validation.



6. Database Support:


  • Works with popular databases (PostgreSQL, MySQL, MongoDB, etc.) through adapters.
  • Stores user data, session tokens, and OAuth account details when persistent storage is configured.



7. Authorization and Role Management:


  • Extendable to include role-based or permission-based access control using session or JWT data.


8. Server-Side Rendering (SSR) Support:


  • Enables rendering user-specific content securely with server-side rendering.


NextAuth can create tokens, specifically JSON Web Tokens (JWTs), to handle user authentication and session data. How it works depends on your setup:


  • If you choose the JWT session strategy, everything is stateless, meaning no session data is stored in a database. Instead, all the information is packed into a token that gets sent back and forth between the client and server.
  • If you go with the database session strategy, it’s stateful. This means session tokens are saved in a database, and the server checks the database to validate user sessions.



In either case, NextAuth takes care of generating and managing these tokens so you don’t have to worry about the complicated stuff.



➤ Typical Use Cases:


  • Secure login for a Next.js web application.
  • Building a multi-provider authentication system.
  • Implementing user-specific dashboards or protected routes.
  • Enabling single sign-on (SSO) functionality.
  • Managing user sessions in a stateless fashion via JWT.



➤ How Are Tokens Generated?


Tokens are created during the authentication process. The following steps summarize the process:


  1. The user authenticates via an OAuth provider, email, or credentials.
  2. NextAuth generates a JWT containing relevant user information.
  3. The token is signed using the NEXTAUTH_SECRET and sent to the client in a secure cookie.



import NextAuth from "next-auth";
import Providers from "next-auth/providers";

export default NextAuth({
  providers: [
    Providers.Google({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    }),
  ],
  session: {
    strategy: "jwt", // Use JWT for session management
  },
  jwt: {
    secret: process.env.NEXTAUTH_SECRET, // Secret key for signing the token
  },
  callbacks: {
    async jwt({ token, user, account, profile }) {
      // Add custom fields to the token
      if (user) {
        token.id = user.id;
        token.role = user.role || "user"; // Add user role
      }
      return token;
    },
    async session({ session, token }) {
      // Add token fields to the session object
      session.user.id = token.id;
      session.user.role = token.role;
      return session;
    },
  },
}); 



➤ Token Structure


NextAuth’s JWT typically includes:


  • iat (Issued At): Timestamp of token creation.
  • exp (Expiration): Token expiration timestamp.
  • sub (Subject): Unique identifier for the user.
  • Custom fields: Any additional data added via the jwt callback (e.g., user roles, permissions).



➤ Where does NextAuth store tokens?


In NextAuth, the storage of tokens depends on the type of token (e.g., session token or JWT) and the configuration of your NextAuth setup. Here’s how NextAuth manages token storage:


1. Session Token Storage

If you’re using a database-backed session strategy (the default option), the session token is stored in two places:



a) Database


  • The session token is stored securely in the database in the sessions table.
  • This token is associated with a user via a unique userId in the database.


b) Cookies (Client-Side)


  • A session token is stored in an HTTP-only secure cookie on the client-side.
  • This cookie is sent with each request to identify the session.
  • The cookie is not accessible via JavaScript, making it secure against Cross-Site Scripting (XSS).


2. JWT Token Storage


If you configure the JWT session strategy (session: “jwt” in the NextAuth config), NextAuth does not store session tokens in the database. Instead:


a) Client-Side


  • No tokens are persistently stored on the client.
  • Authentication state is managed via a short-lived cookie (containing the session state).


b) Server-Side


  • The JWT is generated and signed using the secret (NEXTAUTH_SECRET) and is sent to the client via cookies.
  • This JWT contains all necessary session data, such as the user ID, email, and roles, encoded within the token.


3. Where Cookies Are Stored

  • Cookies are stored in the browser’s cookie storage.
  • They are configured as:


- HttpOnly: Prevents access via JavaScript.

- Secure: Ensures cookies are sent only over

- HTTPS.SameSite: Prevents cross-origin request leakage.Expiration: Defined based on your session configuration.


4. Database Storage (Optional)


If you enable a database adapter, NextAuth can store additional data:

  • Accounts Table: OAuth accounts and tokens (like refresh tokens) for a user.
  • Users Table: User profile information.
  • Sessions Table: Session tokens when using a database-backed session strategy.


Import NextAuth from "next-auth";
import Providers from "next-auth/providers";

export default NextAuth({
  providers: [
    Providers.Google({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    }),
  ],
  session: {
    strategy: "jwt", // Use "database" for database-backed sessions
  },
  jwt: {
    secret: process.env.NEXTAUTH_SECRET,
  },
  database: process.env.DATABASE_URL, // Optional for persistent sessions
});



➤ How to verify NextAuth token?



1. Use getToken for Server-Side Verification


NextAuth provides a built-in utility called getToken for token verification. This is the recommended way to verify tokens in server-side contexts like API routes or middleware.


Example: Verify Token in API Route



import { getToken } from "next-auth/jwt";

export default async function handler(req, res) {
  const secret = process.env.NEXTAUTH_SECRET; // Ensure this matches your NextAuth config
  const token = await getToken({ req, secret });

  if (token) {
    // Token is valid
    res.status(200).json({ message: "Token is valid", token });
  } else {
    // Token is invalid
    res.status(401).json({ message: "Unauthorized" });
  }
}



Parameters for getToken:

  • req: The HTTP request object.
  • secret: (Optional) Secret used to sign the token. Defaults to NEXTAUTH_SECRET.


2. Verify Token Manually (Optional)


If you need more control or want to verify the token outside the Next.js ecosystem, you can use a library like jsonwebtoken to verify the token manually.


Example: Manual Verification


import jwt from "jsonwebtoken";

export default function verifyToken(token) {
  try {
    const secret = process.env.NEXTAUTH_SECRET; // Same secret used in NextAuth
    const decoded = jwt.verify(token, secret);
    return decoded; // Token is valid
  } catch (error) {
    console.error("Token verification failed:", error);
    return null; // Token is invalid
  }
}



Steps:

  1. Extract the token (e.g., from headers or cookies).
  2. Use jwt.verify with the same secret key (NEXTAUTH_SECRET) to decode and validate the token.


3. Access and Verify Token in Middleware


If you’re using Next.js Middleware, you can verify the token as part of your request handling logic.


Example: Middleware with getToken


import { NextResponse } from "next/server";
import { getToken } from "next-auth/jwt";

export async function middleware(req) {
  const secret = process.env.NEXTAUTH_SECRET;
  const token = await getToken({ req, secret });

  if (!token) {
    return NextResponse.redirect(new URL("/api/auth/signin", req.url));
  }

  return NextResponse.next(); // Continue to the requested resource
}



4. Token Validation in Frontend


In the frontend, you typically rely on session handling (useSession) rather than verifying tokens directly. However, if you need to check the token:


Example: Use getSession for Frontend Validation


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

export default async function checkSession() {
  const session = await getSession();
  if (session) {
    console.log("Session is valid:", session);
  } else {
    console.log("Session is invalid or expired.");
  }
}



5. Common Use Cases for Token Verification


  • API Protection: Ensure that only authenticated users can access certain API endpoints.
  • Role-Based Access Control: Check the user’s roles/permissions stored in the token.
  • Middleware Access Control: Restrict access to specific routes or resources.

By using getToken or manually verifying the token, you can securely validate the NextAuth token and implement robust authentication flows in your application.



Summary


  • NextAuth generates JWTs to securely store user session data and optionally provider access tokens.
  • Tokens are customizable via the jwt and callbacks options.
  • Use getToken or useSession to access tokens securely on the server or client.
  • NextAuth ensures secure token handling with encryption and configurable expiration.