目前,我正在开发NodeJS应用程序中的passport-saml实现。这样做的原因是让我们的客户能够连接到他们的AD FS系统并利用SingleSignOn(单点登录)。
因为我们还想提供注销功能,所以我正在研究这一逻辑。然而,我似乎不能让这个简单的功能工作。我已经用谷歌搜索了很多,尝试了很多变体和配置,但不幸的是,它不起作用。
我想给我们的客户提供同时由SP和IdP驱动的SingleLogOut的可能性。这是我的起点。在调试和开发过程中,我已经后退了一步,并试图杀死本地会话,但这似乎是不可能的。
以下是我为SAML配置的路由中的相关代码:
const isAuthenticated = (req, res, next) => {
if (req.isAuthenticated()) {
// User logged in, pass on to next middleware
console.info('User authenticated');
return next();
}
// User not logged in, redirect to login page
console.info('User not authenticated');
return res.redirect('/login');
};
// GET-routes
app.get('/',
isAuthenticated,
(req, res) => {
res.send('Authenticated');
});
app.get('/login',
passport.authenticate('saml', {
successRedirect: '/',
failureRedirect: '/login/fail',
}));
app.get('/logout',
(req, res) => {
passport._strategy('saml').logout(req, (err, url) => {
return res.redirect(url);
});
});
// POST-routes
app.post('/adfs/callback',
(req, res, next) => {
passport.authenticate('saml', (err, user) => {
// If error occurred redirect to failure URL
if (err) return res.redirect('/login/fail');
// If no user could be found, redirect to failure URL
if (!user) return res.redirect('/login/fail');
// User found, handle registration of user on request
req.logIn(user, (loginErr) => {
if (loginErr) return res.status(400).send(err);
// Request session set, put in store
store.set(req.sessionID, req.session, (storeErr) => {
if (storeErr) return res.status(400).send(storeErr);
return res.redirect('/');
});
});
})(req, res, next);
});
app.post('/logout/callback', (req, res) => {
// Destroy session and cookie
store.destroy(req.sessionID, async (err) => {
req.logout();
return res.redirect('/');
});
});可以看出,我控制了会话存储的处理(设置和销毁会话,但如果这是不明智的,请建议)。实现的会话存储是MemoryStore (https://www.npmjs.com/package/memorystore)。
发生的情况是,当用户登录时,一切工作正常。然后,一个请求被发送到路由/logout,然后发生了一些事情,我可以看到会话发生了变化,会话ID以及passport-saml (nameID,sessionIndex)的相关参数也发生了变化,然后用户被重路由到“/”。
但是,该用户将被视为未通过身份验证,并重新路由到“/login”。有人会争辩说它就到此为止,因为必须重新输入凭据。情况并非如此,因为用户直接再次登录,而无需重新输入凭据,我不知道如何防止这种情况。
我真的希望任何人都知道发生了什么:)如果需要更多的信息,我很乐意听到。
发布于 2020-02-04 15:51:28
因此,经过大量的研究和调查,我确实找到了这个问题的解决方案。诀窍在于passport-saml包的定义,特别是authncontext参数。
因此,之前我将SamlStrategy选项定义为:
{
// URL that should be configured inside the AD FS as return URL for authentication requests
callbackUrl: `<URL>`,
// URL on which the AD FS should be reached
entryPoint: <URL>,
// Identifier for the CIR-COO application in the AD FS
issuer: <identifier>,
identifierFormat: null,
// CIR-COO private certificate
privateCert: <private_cert_path>,
// Identity Provider's public key
cert: <cert_path>,
authnContext: ["urn:federation:authentication:windows"],
// AD FS signature hash algorithm with which the response is encrypted
signatureAlgorithm: <algorithm>,
// Single Log Out URL AD FS
logoutUrl: <URL>,
// Single Log Out callback URL
logoutCallbackUrl: `<URL>`,
}但经过大量研究后,我意识到这一点:windows选项是罪魁祸首,所以我将其更改为:
{
// URL that should be configured inside the AD FS as return URL for authentication requests
callbackUrl: `<URL>`,
// URL on which the AD FS should be reached
entryPoint: <URL>,
// Identifier for the CIR-COO application in the AD FS
issuer: <identifier>,
identifierFormat: null,
// CIR-COO private certificate
privateCert: <private_cert_path>,
// Identity Provider's public key
cert: <cert_path>,
authnContext: ["urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport",
"urn:federation:authentication:windows"],
// AD FS signature hash algorithm with which the response is encrypted
signatureAlgorithm: <algorithm>,
// Single Log Out URL AD FS
logoutUrl: <URL>,
// Single Log Out callback URL
logoutCallbackUrl: `<URL>`,
},这基本上意味着它不会检索默认登录到系统的用户的Windows凭据,从而重定向到ADFS服务器的登录屏幕。
发布于 2020-09-18 06:07:35
在会话设置中使用authnContext:"urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport“将在注销后再次显示用户名和密码页面。
注销已达到https://adfs-url/adfs/ls/?wa=wsignout1.0。
重新登录后会创建一个新的session-id。
https://stackoverflow.com/questions/59194317
复制相似问题