Azure App Service上Node.js应用AD认证报无效状态,本地运行正常
我之前在部署Node.js + passport-azure-ad的应用到Azure App Service时,也遇到过一模一样的问题——本地完全正常,一部署就报invalid state received,结合你提到的"登录请求没有set-cookie头"的现象,应该可以按以下步骤解决:
1. 调整Express会话的代理信任与Cookie设置
Azure App Service会通过反向代理处理HTTPS请求,你的应用实际收到的是HTTP请求。如果Express没有信任这个代理,就会认为当前环境是HTTP,导致secure: true的Cookie不会被设置,会话就无法在客户端保存,最终回调时找不到存储在会话里的state值,触发报错。
修改你的Express会话配置:
const session = require('express-session'); // 关键:信任Azure的反向代理,让Express识别真实的请求协议(HTTPS) app.set('trust proxy', 1); app.use(session({ secret: 'your-strong-secret-key', // 替换为你的实际密钥 resave: false, saveUninitialized: false, cookie: { // 生产环境(Azure)下启用secure,本地开发可以根据情况关闭 secure: process.env.NODE_ENV === 'production', sameSite: 'lax', // 如果你的应用有跨域需求,可改为'none',但必须配合secure: true httpOnly: true, maxAge: 24 * 60 * 60 * 1000 // 可选:设置Cookie有效期 } }));
2. 确认redirectUrl与Azure AD回复URL匹配
确保部署后的redirectUrl是Azure App Service的正式HTTPS地址,比如:
redirectUrl: 'https://your-app-name.azurewebsites.net/auth/oidc/return'
同时要在Azure AD应用注册的**"认证"**页面里,把这个地址添加到"重定向URI"列表中,并且确保是HTTPS协议。
3. 验证Azure App Service的ARR Affinity设置
登录Azure门户,找到你的App Service,进入**"配置" > "常规设置",确保"ARR 关联性"**处于开启状态。这个设置能保证同一用户的请求路由到同一个应用实例,避免跨实例的会话丢失问题。
为什么会出现这个差异?
本地开发时,你直接通过HTTPS(localhost:3000)访问应用,Express会正确识别协议并下发secure Cookie,会话能正常保存。但Azure的反向代理机制让应用收到的是HTTP请求,如果没有开启trust proxy,Express会拒绝设置secure Cookie,导致会话Cookie无法传递到客户端,回调时无法从会话中取出之前存储的state,自然就报"无效state"了。
内容的提问来源于stack exchange,提问作者Thomas

