如何在Auth.js(NextAuth v5)中正确实现10秒令牌过期功能?
实现NextAuth v5中10秒令牌过期的测试功能
我正在开发一个使用NextAuth(v5)进行身份验证的Next.js项目,希望为测试目的实现10秒的令牌过期功能。目标是用户登录后可在10秒内访问受保护路由,令牌过期后刷新页面或导航时需重定向至登录页。
当前实现代码
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 ], };
已尝试的方法
- 在
session: { strategy: "jwt", ...}下配置maxAge等参数,期望令牌10秒后过期,但令牌过期规则未按预期生效,客户端仍可在10秒后访问受保护路由。
预期行为
- 用户登录后可在10秒内访问路由。
- 10秒后令牌过期,用户刷新页面或导航时会被重定向至登录页。
注意:本实现基于NextAuth v5(当前最新版本),部分概念和API(如令牌处理和会话管理)与旧稳定版(如v4)不同。
解决方案
在NextAuth v5中,要实现JWT令牌的10秒过期,需要从以下几个方面调整配置:
1. 配置JWT与会话的过期时间
在auth.ts的NextAuth配置中,需同时设置session.maxAge和jwt.maxAge,并在session回调中同步会话过期时间:
export const { handlers, signIn, signOut, auth } = NextAuth({ ...authConfig, pages: { signIn: '/sign-in' }, session: { strategy: "jwt", maxAge: 10, // 会话最大存活时间(秒) }, jwt: { maxAge: 10, // JWT令牌过期时间(秒) }, 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; // 同步会话过期时间与JWT session.expires = new Date(Date.now() + 10 * 1000).toISOString(); return session; }, }, });
2. 修正middleware的会话验证逻辑
NextAuth v5中auth是异步函数,需调用后获取会话;可手动校验会话过期时间增强可靠性:
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 session = await req.auth(); // v5中需调用auth()获取会话 const isLoggedIn = !!session; if(!isLoggedIn){ if(url.pathname.startsWith('/api')){ return NextResponse.json( { message: "Unauthorized" }, { status: 401 } ); }else{ url.pathname = '/sign-in' return NextResponse.redirect(url); } } // 可选:手动校验会话是否过期 if(session?.expires && new Date(session.expires) < new Date()){ if(url.pathname.startsWith('/api')){ return NextResponse.json({ message: "Session expired" }, { status: 401 }); }else{ url.pathname = '/sign-in'; return NextResponse.redirect(url); } } return NextResponse.next(); })
关键说明
- NextAuth v5中
session.maxAge控制会话生命周期,jwt.maxAge控制JWT本身过期时间,两者需保持一致才能生效。 - 在
session回调中手动设置session.expires,可让客户端感知会话过期时间,提升体验。 - 必须调用
await req.auth()获取会话对象,而非直接访问req.auth,这是v5的API变化点。
内容的提问来源于stack exchange,提问作者Juhil Savani
相关产品推荐
相关产品推荐

