'How can I implement Single Logout using Passport.js on a node / express middleware
Am implementing SAML SSO using Passport and passport-saml in a node/express middleware.
Have the following express user and strategy defined:
User
const savedUsers = [];
passport.serializeUser((expressUser, done) => {
done(null, expressUser);
});
passport.deserializeUser((expressUser, done) => {
done(null, expressUser);
});
Strategy
const strategy = new Strategy(
{
entryPoint: process.env.SSO_ENTRYPOINT,
issuer: process.env.SSO_ISSUER,
protocol: process.env.SSO_PROTOCOL,
logoutUrl: process.env.SSO_LOGOUT_URL,
cert: fs.readFileSync('./.cert/saml-cert.pem', 'utf-8'),
path: 'sso/callback'
},
(expressUser, done) => {
if (!savedUsers.includes(expressUser)) {
savedUsers.push(expressUser);
}
return done(null, expressUser);
}
);
SSO works fine. What I can't figure out is how to get SLO working. Have seen some examples on SO along the lines of:
strategy.logout(req, function(err, requestUrl) {
// LOCAL logout
req.logout();
// redirect to the IdP with the encrypted SAML logout request
res.redirect(requestUrl);
});
But this doesn't work - partly because I don't know what the requestUrl should be and secondly how the Passport logoutUrl is used and whether I need to supply additional data. The logoutUrl is the Single Logout Service URL provided by the ISP (PingIdentity in my case).
The docs on the passport website are sparse.
Any help greatly appreciated.
Solution 1:[1]
For anyone who encounters the same issue I figured it out. Not much to it in the end.
- Change the Strategy. Needed to add additional logout params in the Strategy object:
additionalLogoutParams: {Signature: fs.readFileSync(process.env.SSO_CERT_ONE_LINE_LOCATION, 'utf-8')},
The cert is the same .pem certificate defined in the cert param but with the -----BEGIN CERTIFICATE-----, -----END CERTIFICATE----- and line breaks removed.
- Change the
logoutmethod:
strategy.logout(req, (err, request) => {
if (err) {
return res.redirect(`[error logout url]`);
}
else {
req.session.destroy(function (err) {
if (!err) {
return res.redirect(request);
} else { alert(err); }
});
}
})
strategy.logout constructs the logout request based on the logoutUrl in the strategy and adds the certificate as a query param.
This is then passed in return res.redirect(request) which should redirect you to the IDP and destroy the open session. Make sure to define a logout callback url in your IDP config - as this will be the URL the IDP redirects back to with the SAML logout response.
As a side note on SSO - to get SSO working on Azure I had to make sure a few cookie settings were defined:
req.session.cookie.secure = true
req.session.cookie.httpOnly = false
req.session.cookie.sameSite = 'None'
These flags had to be set the opposite way round when testing locally.
(Also had to make sure Enable Access-Control-Allow-Credentials was checked in CORS config on Azure).
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Dharman |
