很抱歉,如果这是一个愚蠢的问题,但我无法理解如何将客户端浏览器重定向回在通过我们的 SAML 身份提供程序 (IdP) 成功进行身份验证后最初请求的任何 URL。我正在使用最新版本的 passport-saml、passport 和 express。
例如,假设客户端最初从另一个不 protected 页面上的链接请求 /foo/bar
,但由于这是 protected 资源,我以重定向到 /login
,这是我调用 passport.authenticate('saml')
的地方。
app.get('/login', passport.authenticate('saml'));
function ensureAuth(req, res, next) {
if (req.user.isAuthenticated()) {return next();}
else {res.redirect('/login');}
}
app.get('/foo/bar', ensureAuth, function(req, res) {
...
});
该调用会将浏览器重定向到我的 IdP 的登录页面,并且在成功进行身份验证后,IdP 将 POST 回我的 /login/callback
路由。在该 route ,我再次使用 passport.authenticate(saml)
来验证响应 SAML,如果一切正常,我就可以将浏览器重定向回请求的资源......但是怎么做我知道请求的资源是什么?因为它是一个 POST 回调,所以我丢失了与原始请求相关的任何状态。
app.post('/login/callback', passport.authenticate('saml'), function(req, res) {
res.redirect('...can I know which url to redirect back to?...');
});
passport-saml readme 中的示例只是显示硬编码重定向回根资源,但我想重定向回最初请求的 URL (/foo/bar
)。
我是否可以向 IdP 发送一个 url 或其他值,该 IdP 将在响应 SAML 中进行往返并回传?如果是这样,我如何在我的 /login/callback
路由中访问它?
或者有没有更好的 express /Passport 方式来做这件事,我错过了?
您能提供的任何帮助将不胜感激!
最佳答案
Can I send a url, or some other value, to the IdP that will get round-tripped and POSTed back in the response SAML? And if so, how can I access it in my /login/callback route?
要通过 IdP 来回传递一个值,您需要使用 RelayState
。这是一个您可以发送给 IdP 的值,如果您这样做了,他们有义务将其发送回去而不做任何更改。
这里是SAML specifications不得不说:
3.1.1 Use of RelayState
Some bindings define a "RelayState" mechanism for preserving and conveying state information. When such a mechanism is used in conveying a request message as the initial step of a SAML protocol, it places requirements on the selection and use of the binding subsequently used to convey the response. Namely, if a SAML request message is accompanied by RelayState data, then the SAML responder MUST return its SAML protocol response using a binding that also supports a RelayState mechanism, and it MUST place the exact RelayState data it received with the request into the corresponding RelayState parameter in the response.
要将其与 passport-saml 一起使用,您必须将其添加为 additionalParams
值。下面的代码显示了这种情况。
saml = new SamlStrategy
path: appConfig.passport.saml.path
decryptionPvk: fs.readFileSync(appConfig.passport.saml.privateKeyFile)
issuer: appConfig.passport.saml.issuer
identifierFormat: tenant.strategy.identifierFormat
entryPoint: tenant.strategy.entryPoint
additionalParams:{'RelayState':tenant.key}
,
(profile, next) ->
# get the user from the profile
上面的代码来自 Multi-Tenancy saml 实现,因此我将 tenant.key
作为 RelayState
参数发送。然后,我从 IdP 的 POSTed 返回正文中检索此值,并使用它来重新建立我需要的所有状态。
getTenantKey: (req, next) ->
key = req.body?.RelayState ? routes.match(req.path).params.tenentKey
next null, key
您的情况可能更简单。您可能希望将最终目标 url 存储在时间有限的缓存中,然后将缓存键作为 RelayState
参数发送。
无论如何,如果您只使用原始 SAML 请求 ID 作为缓存键,则可以完全避免使用 RelayState
。此值始终通过 InResponseTo
字段发回给您。
关于node.js - 使用passport-saml 进行身份验证后,如何重定向回最初请求的url?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24601188/