You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

刷新令牌过期时如何在Next.js中间件中直接登出(Auth.js)

直接在Next.js中间件处理刷新令牌过期并登出的实现方案

核心结论

完全可以跳过中间客户端页面,直接在Next.js中间件完成登出操作,并携带会话过期提示重定向到登录页。删除Auth.js的令牌Cookie是合法且有效的实现方式,但要注意完整清理所有会话相关Cookie,同时正确传递提示信息。

具体实现步骤

  1. 在jwt回调中标记刷新令牌过期状态
    当检测到刷新令牌过期时,在JWT payload中加入refreshTokenExpired: true的标识,让中间件能直接识别该状态:

    async jwt({ token, account }) {
      if (account && account.refresh_token) {
        token.refreshToken = account.refresh_token;
        token.accessTokenExpires = Date.now() + account.expires_in * 1000;
      }
    
      // 访问令牌未过期,直接返回
      if (Date.now() < token.accessTokenExpires) {
        return token;
      }
    
      // 尝试刷新令牌
      try {
        const response = await fetch(`${process.env.AUTH_API_URL}/refresh`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ refreshToken: token.refreshToken }),
        });
        const newTokens = await response.json();
        if (!response.ok) throw new Error();
    
        return {
          ...token,
          accessToken: newTokens.access_token,
          refreshToken: newTokens.refresh_token,
          accessTokenExpires: Date.now() + newTokens.expires_in * 1000,
        };
      } catch (error) {
        // 刷新令牌过期,标记状态
        return { ...token, refreshTokenExpired: true };
      }
    }
    
  2. 在middleware.ts中拦截并处理过期状态
    中间件里解析JWT后,检查refreshTokenExpired标识,若是则清理Auth.js的所有相关Cookie,再重定向到带提示参数的登录页:

    import { NextResponse } from 'next/server';
    import type { NextRequest } from 'next/server';
    import { getToken } from 'next-auth/jwt';
    
    export async function middleware(request: NextRequest) {
      const token = await getToken({ req: request, secret: process.env.NEXTAUTH_SECRET });
    
      // 仅处理已登录但刷新令牌过期的请求
      if (token?.refreshTokenExpired) {
        const loginUrl = new URL('/login?error=session_expired', request.url);
        const response = NextResponse.redirect(loginUrl);
    
        // 清理Auth.js的会话及CSRF令牌Cookie(覆盖HTTP/HTTPS场景)
        response.cookies.delete('next-auth.session-token');
        response.cookies.delete('__Secure-next-auth.session-token');
        response.cookies.delete('next-auth.csrf-token');
        response.cookies.delete('__Secure-next-auth.csrf-token');
    
        return response;
      }
    
      // 正常路由逻辑放行
      return NextResponse.next();
    }
    
    export const config = {
      matcher: ['/dashboard/:path*', '/profile/:path*'], // 仅对需要认证的路由生效
    };
    
  3. 在登录页显示会话过期提示
    登录页通过searchParams获取重定向带来的error参数,判断后显示对应的提示:

    import { useSearchParams } from 'next/navigation';
    
    export default function LoginPage() {
      const searchParams = useSearchParams();
      const error = searchParams.get('error');
    
      return (
        <div className="login-wrapper">
          {error === 'session_expired' && (
            <div className="alert alert-warning">您的会话已过期,请重新登录</div>
          )}
          {/* 登录表单代码 */}
        </div>
      );
    }
    

关键注意事项

  • Cookie清理完整性:Auth.js在HTTP和HTTPS环境下使用的Cookie名称不同,必须同时删除普通和__Secure-前缀的Cookie,避免残留会话信息。
  • NEXTAUTH_SECRET配置:中间件调用getToken必须配置正确的NEXTAUTH_SECRET,否则无法解析JWT内容。
  • 避免重定向循环:确保中间件的matcher不包含登录页路径,否则会陷入无限重定向。

内容的提问来源于stack exchange,提问作者fleskara

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 14:20:05