admin管理员组

文章数量:1125973

I’m working on a Next.js project using NextAuth (v5) for authentication. I want to implement a 10-second token expiry for testing purposes. The goal is that after logging in, users can access protected routes for 10 seconds. Once the token expires, refreshing the page or navigating should redirect them to the login page.

Here’s my current implementation:

auth.ts

import NextAuth from "next-auth"
import authConfig from "@/auth.config"
 
export const { handlers, signIn, signOut, auth } = NextAuth({
  ...authConfig,
  pages: {
    signIn: '/sign-in'
  },
  session: {
    strategy: "jwt",
    // maxAge: <number>,
    // updateAge: <number>,
  },
  callbacks: {
    async jwt({ token, user }) {
      console.log('\n hello from jwt callback. \n'); // DEBUG
      if (user){
        token.firstName = user.firstName;
        token.lastName = user.lastName;
        token.email = user.email;
      }
      return token;
    },

    async session({ session, token }) {
      console.log('\n hello from session callback. \n'); // DEBUG
      session.user.firstName = token.firstName as string;
      session.user.lastName = token.lastName as string;
      session.user.email = token.email as string; 
      return session;
    },
  },
});

middleware.ts

import authConfig from "@/auth.config"
import NextAuth from "next-auth"
import { NextResponse } from "next/server";

const { auth: middleware } = NextAuth(authConfig);

export default  middleware( async (req) => {
  const url = req.nextUrl.clone();
  if(url.pathname.startsWith('/api/auth')) return NextResponse.next();
  if(url.pathname.startsWith('/api/users')) return NextResponse.next();

  const isLoggedIn = !!req.auth;

  if(!isLoggedIn){
    if(url.pathname.startsWith('/api')){ 
      return NextResponse.json(
        { message: "Unauthorized" },
        { status: 401 } 
      );
    }else{
      url.pathname = '/sign-in'
      return NextResponse.redirect(url);
    }
  }
  return NextResponse.next();
})
 
export const config = {
  matcher: [
    "/((?!.*\\.[\\w]+$|_next|sign-in|sign-up).*)", // Match all paths except static files, `_next`, `sign-in` and `sign-up` paths
    "/",                           // Root route
    "/api/:path*",                 // API routes
    "/trpc/:path*",                // TRPC routes
  ],
};

My Attempts:

  • I attempted setting the configurations under session: { strategy: "jwt", ...}, expecting the token to expire after 10 seconds. However, it seems that the token expiry isn’t being enforced as expected, and client can still access protected routes beyond the 10-second limit.

Expected Behavior:

  • Users can access routes for 10 seconds after logging in.
  • After 10 seconds, the token should expire, and users should be redirected to the login page when they reload or navigate.

Note:

Since this implementation is based on NextAuth v5 (the latest version at the time), it may feel unfamiliar or different to developers who are used to older stable versions of NextAuth (i.e., v4). Some concepts and APIs, such as token handling and session management, may have changed.

I’m working on a Next.js project using NextAuth (v5) for authentication. I want to implement a 10-second token expiry for testing purposes. The goal is that after logging in, users can access protected routes for 10 seconds. Once the token expires, refreshing the page or navigating should redirect them to the login page.

Here’s my current implementation:

auth.ts

import NextAuth from "next-auth"
import authConfig from "@/auth.config"
 
export const { handlers, signIn, signOut, auth } = NextAuth({
  ...authConfig,
  pages: {
    signIn: '/sign-in'
  },
  session: {
    strategy: "jwt",
    // maxAge: <number>,
    // updateAge: <number>,
  },
  callbacks: {
    async jwt({ token, user }) {
      console.log('\n hello from jwt callback. \n'); // DEBUG
      if (user){
        token.firstName = user.firstName;
        token.lastName = user.lastName;
        token.email = user.email;
      }
      return token;
    },

    async session({ session, token }) {
      console.log('\n hello from session callback. \n'); // DEBUG
      session.user.firstName = token.firstName as string;
      session.user.lastName = token.lastName as string;
      session.user.email = token.email as string; 
      return session;
    },
  },
});

middleware.ts

import authConfig from "@/auth.config"
import NextAuth from "next-auth"
import { NextResponse } from "next/server";

const { auth: middleware } = NextAuth(authConfig);

export default  middleware( async (req) => {
  const url = req.nextUrl.clone();
  if(url.pathname.startsWith('/api/auth')) return NextResponse.next();
  if(url.pathname.startsWith('/api/users')) return NextResponse.next();

  const isLoggedIn = !!req.auth;

  if(!isLoggedIn){
    if(url.pathname.startsWith('/api')){ 
      return NextResponse.json(
        { message: "Unauthorized" },
        { status: 401 } 
      );
    }else{
      url.pathname = '/sign-in'
      return NextResponse.redirect(url);
    }
  }
  return NextResponse.next();
})
 
export const config = {
  matcher: [
    "/((?!.*\\.[\\w]+$|_next|sign-in|sign-up).*)", // Match all paths except static files, `_next`, `sign-in` and `sign-up` paths
    "/",                           // Root route
    "/api/:path*",                 // API routes
    "/trpc/:path*",                // TRPC routes
  ],
};

My Attempts:

  • I attempted setting the configurations under session: { strategy: "jwt", ...}, expecting the token to expire after 10 seconds. However, it seems that the token expiry isn’t being enforced as expected, and client can still access protected routes beyond the 10-second limit.

Expected Behavior:

  • Users can access routes for 10 seconds after logging in.
  • After 10 seconds, the token should expire, and users should be redirected to the login page when they reload or navigate.

Note:

Since this implementation is based on NextAuth v5 (the latest version at the time), it may feel unfamiliar or different to developers who are used to older stable versions of NextAuth (i.e., v4). Some concepts and APIs, such as token handling and session management, may have changed.

Share edited yesterday John Doe asked Jan 9 at 2:46 John DoeJohn Doe 231 silver badge7 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 1

You can update like this.

  1. Set Token Expiration In your auth.ts file, configure the session option with the maxAge property to define the token's lifespan:

session: {
  strategy: "jwt",
  maxAge: 10, // Token will expire after 10 seconds
},

  1. Handle Token Expiry in Callbacks To ensure the token expires and is invalidated properly, add logic to the jwt callback:

callbacks: {
  async jwt({ token, user }) {
    const now = Math.floor(Date.now() / 1000); 
    const maxAge = 10; 


    if (user) {
      token.issuedAt = now;
    }

    if (now - (token.issuedAt ?? 0) > maxAge) {
      return null; 
    }

    return token;
  },

  async session({ session, token }) {
    if (!token) {
      return null;
    }

    session.user = {
      firstName: token.firstName,
      lastName: token.lastName,
      email: token.email,
    };

    return session;
  },
},

  1. Validate Tokens in Middleware Update middleware.ts to check token validity and redirect users when the token has expired:

export default async function middleware(req) {
  const { auth } = req; 
  const url = req.nextUrl.clone();

  if (!auth) {
    if (url.pathname.startsWith('/api')) {
      return NextResponse.json({ message: "Unauthorized" }, { status: 401 });
    }
    url.pathname = '/sign-in';
    return NextResponse.redirect(url);
  }

  const now = Math.floor(Date.now() / 1000);
  if (auth.token?.issuedAt && now - auth.token.issuedAt > 10) {
    url.pathname = '/sign-in';
    return NextResponse.redirect(url);
  }

  return NextResponse.next();
}

Here is the code that worked for me for this problem, where I chose step 2 over 3:

import NextAuth from "next-auth"
import authConfig from "@/auth.config"
// imports ... 
 
const TOKEN_EXPIRY = 60 * 60;

export const { handlers, signIn, signOut, auth } = NextAuth({
  ...authConfig,
  pages: {
    signIn: '/sign-in'
  },
  session: {
    strategy: "jwt",
    maxAge: TOKEN_EXPIRY
    // updateAge: <number>,
  },
  callbacks: {

    // callbacks ...

    async jwt({ token, user }) {
      const now = Math.floor(Date.now() / 1000); 

      if (user){
        token.issuedAt = now;
        token.firstName = user.firstName;
        token.lastName = user.lastName;
        token.email = user.email;
      }

      if (now - (token.issuedAt as number ?? 0) > TOKEN_EXPIRY) {
        return null; 
      }

      return token;
    },

    // callbacks ...

  },
});

Acknowledgment: Thanks to Emre for this solution.

本文标签: nextjsHow to properly handle token expiry with Authjs (NextAuth v5)Stack Overflow