代理环境下Passport无法持久化会话问题排查
问题:反向代理架构下Passport无法保持SAML认证状态
场景
我使用React开发前端,后端是处理Azure AD SAML认证的Express服务器。后端通过部署React应用的Nginx服务器对外提供服务:Nginx会将所有以/api为前缀的请求反向代理到后端,客户端仅知晓Nginx地址,不知道后端的真实地址。
当前Passport在该配置下无法正常工作,具体流程如下:
- 客户端点击认证按钮,React请求
/api/login路由; - Nginx将请求代理到后端,由Passport接管认证流程;
- 客户端通过IDP表单完成登录,Passport正确处理回调(已成功解析IDP返回的用户信息,后端日志能确认获取到用户);
- 后端将客户端重定向到
/home路由,但会话未保存或未转发给客户端,导致客户端仍处于未认证状态。
相关代码
Passport初始化配置(app.js)
app.set('trust proxy', 1) app.use( session({ cookie: { path: '/', secure: true, httpOnly: false, sameSite: 'none', domain: `https://${process.env.FRONTEND_DOMAIN}` }, resave: false, saveUninitialized: true, secret: 'TOI_MEME_TU_LE_C' }) ) app.use(passport.initialize()) app.use(passport.session())
SAML回调路由
router.post('/saml/acs', bodyParser.urlencoded({ extended: false }), (req, res, next) => { passport.authenticate('saml', (err, user) => { if (err) { let error = 'generic' if (err.message.includes('RequestDenied')) { error = 'request_denied' } else if (err.message.includes('unspecified')) { error = 'unspecified' } return res.redirect(`https://${process.env.FRONTEND_DOMAIN}/login?error=${error}`) } console.log(`${user.firstname} ${user.lastname} (${user.employeeId ?? '-> no employeeId <-'}) is connected.`) req.login(user, error => { if (error) { console.log('Erreur lors du login.', error) return next(error) } console.log('Login successful, is authenticated?: ' + req.isAuthenticated()) return res.redirect(`https://${process.env.FRONTEND_DOMAIN}`) }) })(req, res, next) })
注:两条日志均正常输出!第二条日志显示
req.isAuthenticated()返回true,确认认证成功。
验证认证状态的/me路由
router.get('/me', (req, res) => { // 无法通过此判断,请求中既无该方法也无用户对象 if (!req.isAuthenticated()) { return res.status(401).send({ error: "Not connected." }) } if (!req.user) { return res.status(500).send({ error: "No user on the request." }) } res.status(200).json(req.user) })
已尝试的排查动作
- 移除Passport回调中的自定义错误处理,无效果;
- 调整Cookie的各项配置参数,无效。
疑问
为何Passport在认证成功后,无法正确识别后续请求的认证状态?
内容的提问来源于stack exchange,提问作者Tom Blanchet
相关产品推荐
相关产品推荐

