We have implemented a SAML SSO ,we have used passport-saml for the same. The login works perfectly using "http-post" as authnRequestBinding.But I am unable to find any such method for logout . it appears logout defaults to http redirection and this does not work correctly.
First of all, you need to define the logoutUrl and logoutCallback in the config for the passport-saml. The logoutUrl is the url where your server will send the logoutRequest. So it is an URL got from the identity provider you are using. The logoutCallback is as the name says, the callbackUrl which will be called by the browser (through redirect) after logout is done. Here's how you add those configurations:
module.exports = {
development: {
app: {
name: 'Passport SAML strategy example',
port: process.env.PORT || 8443
},
passport: {
strategy: 'saml',
saml: {
logoutUrl: 'idp-logout-url-here',
logoutCallback: 'your-logout-callback-url-here'
}
}
}
};
Then you need to have the SamlStrategy somewhere in your code, where you will use the config defined above. Of course the config will have other variables as well, I just put the logout related variables there for now.
Finally, you need to have your own logout route defined in your node application, which will initiate the logout process when called:
app.get('/logout', function(req, res) {
if (req.user == null) {
return res.redirect('/');
}
return SamlStrategy.logout(req, function(err, uri) {
return res.redirect(uri);
});
});
As you can see from above, it will call the logout function defined in the SamlStrategy. So there is a logout function defined in the passport-saml strategy. As in the above, you need to give it a callback function, which will then redirect the response to the uri. That uri will be the logoutCallback url you defined earlier.
If you're wondering what is the SamlStrategy there, it is actually the strategy of the passport-saml. I can show you how to get it working. In a separate file, called 'saml-strategy.js' for example, put this:
const SamlStrategy = require('passport-saml').Strategy;
var config = require('./config.js')['development'];
module.exports = new SamlStrategy(
{
otherImportantvariable1: config.passport.saml.OtherImportantvariable1,
logoutUrl: config.passport.saml.logoutUrl,
logoutCallback: config.passport.saml.logoutCallback
}
function (profile, done) {
user = Object.assign({}, profile);
return done(null, user);
}
);
Insert all your important config variables same way as the logout related variables are defined above. Include the config created in the first step.
Then you can just require the SamlStrategy to the same file where you have your routes:
const SamlStrategy = require('../config/saml-strategy');
Please ask if anything is unclear!
Logout fix for ADFS is as follows,
1) Session index attribute should be added as part of passport-saml logout request. you can get that from passport profile object.
function (profile, done) {
console.log('Profile: %j', profile);
return done(null,
{
id: profile.nameID,
sessionIndex: profile.sessionIndex
});
If there is no sessionIndex returned from ADFS. Then, NameID rule in relying part trusts should be as follows,
Add NameID as "Claim rule name", choose "Active Directory" as Attribute store, choose "SAM-Account-Name" as LDAP Attribute and "Name ID" as "Outgoing claim type", finish the wizard and confirm the claim rules window. (Reference: spring saml ADFS)
2) Debug using the ADFS logs (Event viewer) and check whether your error is similar to the one below,
The SAML Single Logout request does not correspond to the logged-in session participant. Requestor: app.yyy.com
Request name identifier: Format: urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified, NameQualifier: SPNameQualifier: , SPProvidedId: Logged-in session participants: Count: 1, [Issuer: app.yyy.com, NameID: (Format: , NameQualifier: SPNameQualifier: , SPProvidedId: )]This request failed.
If yes, It means that nameIDFormat should be left empty for logging out the session. Previously I was using nameIDFormat that was specified for authentication request and it did not work.
HTTP-POST binding does not make any difference without this config.
Hope this helps !
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With