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

NextAuth未遵循Azure AD B2C会话过期配置的问题求助

NextAuth + Azure AD B2C 会话有效期不匹配问题解决

问题描述

我在SPA应用中使用NextAuth作为认证方案,提供商是Azure AD B2C。目前遇到的问题是:已经在AD B2C中将会话有效期配置为1天,但用户实际会话能保持有效长达一个月。

为测试我添加了以下配置:

session: {
  maxAge: 120,
},
jwt: {
  maxAge: 120,
},

但2分钟后刷新页面,系统会生成新令牌,却不会跳转到登录页。

我需要强制NextAuth遵循B2C的配置,实现用户在X小时无活动后被重定向至登录页。

我的相关代码如下:

import AzureADB2CProvider from "next-auth/providers/azure-ad-b2c";
import NextAuth, { NextAuthOptions } from "next-auth";

export const authOptions: NextAuthOptions = {
  secret: process.env.NEXTAUTH_SECRET,
  session: {
    strategy: "jwt",
    // Even adding this doesn't help invalidating the session
    // Seconds - How long until an idle session expires and is no longer valid.
  
    maxAge: 60, // 20 Seconds
  },
  providers: [
    AzureADB2CProvider({
      tenantId: process.env.AZURE_AD_B2C_TENANT_NAME,
      clientId: process.env.AZURE_AD_B2C_CLIENT_ID!,
      clientSecret: process.env.AZURE_AD_B2C_CLIENT_SECRET!,
      primaryUserFlow: process.env.AZURE_AD_B2C_PRIMARY_USER_FLOW,
      authorization: {
        params: {
          scope: `offline_access openid`,
        },
      },
      profile: (profile) => {
        return {
          id: profile.oid,
          fName: profile.name,
          email: profile.emails?.length ? profile.emails[0] : null,
          myClaim: profile.extension_myClaim,
        };
      },
      checks: ["pkce"],
      client: {
        token_endpoint_auth_method: "none",
      },
    }),
  ],
  callbacks: {
    async jwt({ token, account, profile }) {
      // Persist the OAuth access_token to the token right after signin

      if (profile) {
        token.myClaim = profile.extension_myClaim;
      }
      return token;
    },
    async session({ session, token, user }) {
      // Send properties to the client, like an access_token from a provider.

      session.myClaim = token.myClaim;
      return session;
    },
  },
  pages: {
    signIn: "/auth/signin",
    signOut: "/auth/signout",
  },
};

export default NextAuth(authOptions);

核心问题分析

NextAuth默认会利用offline_access权限自动刷新令牌,忽略手动设置的maxAge;同时未跟踪用户活动时间,导致无活动超时逻辑无法触发。要解决问题,需结合Azure AD B2C返回的令牌过期信息,同时实现无活动超时校验。

具体解决步骤

1. 在JWT回调中保存令牌原生过期时间和活动时间

修改jwt回调,保存B2C返回的exp(令牌过期时间),并添加lastActive字段跟踪用户最后活动时间:

async jwt({ token, account, profile, trigger, session }) {
  // 首次登录时保存B2C返回的令牌过期时间
  if (account) {
    token.exp = account.expires_at;
    token.lastActive = Date.now();
  }
  
  // 客户端触发会话更新时,同步活动时间
  if (trigger === "update" && session?.lastActive) {
    token.lastActive = session.lastActive;
  }

  if (profile) {
    token.myClaim = profile.extension_myClaim;
  }
  return token;
}

2. 在Session回调中校验过期时间和无活动超时

在session回调中同时校验令牌绝对过期时间和无活动超时,超时则抛出错误:

async session({ session, token }) {
  const idleTimeout = 60 * 60 * 1000; // 1小时无活动超时,按需调整
  const currentTime = Date.now();

  // 校验令牌是否绝对过期
  if (token.exp && currentTime > token.exp * 1000) {
    throw new Error("Session expired");
  }

  // 校验无活动超时
  if (token.lastActive && currentTime - token.lastActive > idleTimeout) {
    throw new Error("Session timed out due to inactivity");
  }

  // 同步活动时间到会话
  session.lastActive = token.lastActive;
  session.myClaim = token.myClaim;
  return session;
}

3. 关闭NextAuth自动令牌刷新

在Azure AD B2C Provider配置中移除offline_access scope,避免自动刷新令牌:

authorization: {
  params: {
    scope: `openid`, // 移除offline_access
  },
},

4. 客户端处理会话失效重定向

通过useSession钩子监听会话状态,出现错误时重定向到登录页:

import { useSession } from "next-auth/react";
import { useEffect } from "react";
import { useRouter } from "next/router";

export default function ProtectedPage() {
  const { data: session, status, error } = useSession();
  const router = useRouter();

  useEffect(() => {
    if (error) {
      router.push("/auth/signin");
    }
  }, [error, router]);

  if (status === "loading") {
    return <div>Loading...</div>;
  }

  if (!session) {
    return null;
  }

  return <div>Protected Content</div>;
}

5. 调整Session配置

设置session.updateAge为较短时间,确保定期校验会话状态:

session: {
  strategy: "jwt",
  updateAge: 60 * 5, // 5分钟更新一次会话,触发超时校验
},

注意不要设置maxAge,让B2C的令牌过期时间主导绝对过期逻辑。

关键说明

  • 绝对过期时间:完全遵循Azure AD B2C返回的expires_at,无需手动设置maxAge
  • 无活动超时:通过lastActive字段跟踪,每次客户端交互时调用updateSession更新该字段
  • 关闭自动刷新:移除offline_access避免NextAuth自动延长会话,确保过期后必须重新登录

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 16:05:22