K8s部署Next-Auth Azure AD认证请求超时问题求助
Azure AD SSO部署到K8s集群后出现请求超时错误
本地环境(localhost:3000)运行正常,但部署到私有企业内部网络的K8s集群后,Pod日志出现[SIGNIN_OAUTH_ERROR]错误,提示“outgoing request timed out after 3500ms”,前端UI显示“请尝试使用其他账号登录”。
复现步骤
在[...nextauth].ts中配置AzureADProvider,并为jwt回调中的Graph请求添加了HttpsProxyAgent代理,代码如下:
import NextAuth, { NextAuthOptions } from "next-auth"; import AzureADProvider from "next-auth/providers/azure-ad"; import { HttpsProxyAgent } from "https-proxy-agent"; const authOptions: NextAuthOptions = { providers: [ AzureADProvider({ id: "azure-ad", name: "Azure AD", tenantId: process.env.NEXT_PUBLIC_TENANT_NAME as string, clientId: process.env.NEXT_PUBLIC_CLIENT_ID as string, clientSecret: process.env.NEXTAUTH_SECRET as string, }), ], callbacks: { async jwt({ token, account }) { var myHeaders = new Headers(); if (account) { myHeaders.append("Authorization", account.access_token); let fetchOptions = { method: "GET", headers: myHeaders, redirect: "follow", agent: new HttpsProxyAgent("http://proxy.company.com:8080"), } as RequestInit; token.iNumber = await fetch( "https://graph.microsoft.com/v1.0/me?$select=displayName,mail", fetchOptions ) .then((response) => response.json()) .then((response) => response["onPremisesSamAccountName"]) .catch((error) => console.log("error", error)); } return token; }, async session({ session, token, user }) { return { ...session, user: { ...session.user, iNumber: token.iNumber, }, }; }, }, debug: true, }; export default NextAuth(authOptions);
预期与实际行为
- 预期:认证完成后重定向至首页
- 实际:跳转至错误URL:
https://app-hostname.com/api/auth/signin?error=OAuthSignin
环境信息
{ "name": "my_app", "version": "0.1.0", "private": true, "scripts": { "dev": "next dev", "build": "next build", "start": "next start" }, "dependencies": { "@emotion/react": "^11.10.6", "@testing-library/react": "^14.0.0", "@types/node": "18.15.11", "@types/react": "18.0.37", "@types/react-dom": "18.0.11", "next": "13.2.4", "next-auth": "^4.22.1", "react": "18.2.0", "react-dom": "18.2.0", "sharp": "^0.32.0", "typescript": "5.0.4" } }
问题原因
当前代码仅在jwt回调中的Graph API请求配置了代理,但AzureADProvider本身的OAuth流程(获取授权码、交换令牌等核心请求)没有走代理。K8s集群内的Pod处于企业私有网络,无法直接访问外部Azure AD服务,导致请求超时。
解决方案
1. 为AzureADProvider全局配置代理
修改[...nextauth].ts,为AzureADProvider的所有请求添加代理,同时复用代理实例优化性能:
import NextAuth, { NextAuthOptions } from "next-auth"; import AzureADProvider from "next-auth/providers/azure-ad"; import { HttpsProxyAgent } from "https-proxy-agent"; // 复用代理实例,避免重复创建 const proxyAgent = new HttpsProxyAgent("http://proxy.company.com:8080"); const authOptions: NextAuthOptions = { providers: [ AzureADProvider({ id: "azure-ad", name: "Azure AD", tenantId: process.env.NEXT_PUBLIC_TENANT_NAME as string, clientId: process.env.NEXT_PUBLIC_CLIENT_ID as string, clientSecret: process.env.NEXTAUTH_SECRET as string, // 重写provider的客户端请求逻辑,添加代理 async client(options) { const baseClient = await AzureADProvider.client(options); const originalFetch = baseClient.fetch; // 为所有provider请求添加代理 baseClient.fetch = async (url, init) => { return originalFetch(url, { ...init, agent: proxyAgent, // 可选:延长超时时间,适配代理网络延迟 signal: AbortSignal.timeout(10000), }); }; return baseClient; }, }), ], callbacks: { async jwt({ token, account }) { if (!account) return token; var myHeaders = new Headers(); myHeaders.append("Authorization", account.access_token); try { const response = await fetch( "https://graph.microsoft.com/v1.0/me?$select=displayName,mail,onPremisesSamAccountName", { method: "GET", headers: myHeaders, redirect: "follow", agent: proxyAgent, signal: AbortSignal.timeout(10000), } as RequestInit ); if (!response.ok) throw new Error(`Graph请求失败:${response.status}`); const data = await response.json(); token.iNumber = data.onPremisesSamAccountName; } catch (error) { console.error("获取用户信息失败:", error); // 可选:设置默认值或抛出错误中断流程 // token.iNumber = "unknown"; } return token; }, async session({ session, token }) { return { ...session, user: { ...session.user, iNumber: token.iNumber, }, }; }, }, debug: true, }; export default NextAuth(authOptions);
2. 额外检查项
- 确认企业代理允许访问Azure AD相关域名:
login.microsoftonline.com、graph.microsoft.com - 如果代理需要身份认证,修改代理地址格式:
http://username:password@proxy.company.com:8080 - 检查K8s集群网络策略是否允许Pod访问代理服务器的8080端口
内容的提问来源于stack exchange,提问作者walidmourou
相关产品推荐
相关产品推荐

