我有一个用 React 编写的前端,以及一个处理 SAML 身份验证过程 (Azure AD) 的 Express 后端服务器。该后端可通过为 React 应用程序提供服务的 nginx 服务器进行访问:它代理将以
/api
为前缀的所有请求传递到后端。这样客户端不知道后端,只有 nginx 知道。
问题是 Passport 似乎不适用于此设置。事情是这样发生的:
/api/login
。/home
路由,但请求会话未保存或似乎从未转发到客户端,从而导致客户端经过身份验证。这里是
app.js
中的Passport初始化:
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())
这是我在 Express 中的回调路线:
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) => {
// it never goes past here, as neither the metho nor the user object exist in the request
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 无法正确检测身份验证?
您的
nginx
配置也与此处相关。在不知道的情况下,我只能提供最好的猜测。对于在会话配置中设置 secure: true
的配置,您还必须配置 nginx
来转发协议,例如:
proxy_set_header X-Forwarded-Proto $scheme;
您可以提出一些其他问题来帮助您找出问题:
secure: true
是否有效?如果是这样,nginx
可能并不表示请求是通过 https
传入的。请参阅上面的 proxy_set_header
指令。nginx
是否通过 https
或 http
为网站提供服务? https
是 secure: true
属性的要求。有关类似问题,请参阅Express-session Secure Cookies 不起作用。
请参阅 https://gist.github.com/nikmartin/5902176 获取可能会给您一些其他尝试想法的食谱。