I have a question regarding the proper way to logout a user when using passport-saml for authentication.
The example script with passport-saml shows logging out as this:
app.get('/logout', function(req, res){
req.logout();
res.redirect('/');
});
From what I can tell, this will end the local passport session, but it doesn't seem to send a logout request to the SAML IdP. When the user does another login, it redirects to the IdP but immediately redirects back with the authenticated user. Is there a way to logout with the IdP so that the user has to enter their password again when signing in to my site? I've seen other sites that use our IdP do this, so I think it's possible.
I did notice in the passport-saml code that there is a logout()
method on the passport-saml Strategy object, which doesn't seem to be called by req.logout()
. So I tried switching the code to this:
app.get('/logout', function(req, res) {
//strategy is a ref to passport-saml Strategy instance
strategy.logout(req, function(){
req.logout();
res.redirect('/');
});
});
But I got this error deep in XMLNode.js
Error: Could not create any elements with: [object Object]
at XMLElement.module.exports.XMLNode.element (/.../node_modules/passport-saml/node_modules/xmlbuilder/lib/XMLNode.js:74:15)
at XMLElement.module.exports.XMLNode.element (/.../node_modules/passport-saml/node_modules/xmlbuilder/lib/XMLNode.js:54:25)
at XMLElement.module.exports.XMLNode.element (/.../node_modules/passport-saml/node_modules/xmlbuilder/lib/XMLNode.js:54:25)
at new XMLBuilder (/.../node_modules/passport-saml/node_modules/xmlbuilder/lib/XMLBuilder.js:27:19)
at Object.module.exports.create (/.../node_modules/passport-saml/node_modules/xmlbuilder/lib/index.js:11:12)
at SAML.generateLogoutRequest (/.../node_modules/passport-saml/lib/passport-saml/saml.js:169:21)
Am I not calling this method correctly? Or should I not be calling this method directly and calling some other method instead?
I see that in generateLogoutRequest()
it is referring to two properties on the req.user
that I'm not sure are there:
'saml:NameID' : {
'@Format': req.user.nameIDFormat,
'#text': req.user.nameID
}
If these properties are not there, will that cause this error? If so, I assume that maybe I need to ensure that these properties are added to the user object that is returned from the verify callback function?
Thanks for any help anyone might be able to provide on this.
Passport exposes a logout() function on req (also aliased as logOut() ) that can be called from any route handler which needs to terminate a login session. Invoking logout() will remove the req. user property and clear the login session (if any).
The “req. isAuthenticated()” function can be used to protect routes that can be accessed only after a user is logged in eg.
Yes adding the nameIDFormat and nameID to the user will solve the issue.
logoutUrl: 'http://example.org/simplesaml/saml2/idp/SingleLogoutService.php',
The logout method in the strategy does not actually send any request. the callback function is called with the request as parameter.
To launch the logout process :
passport.logoutSaml = function(req, res) {
//Here add the nameID and nameIDFormat to the user if you stored it someplace.
req.user.nameID = req.user.saml.nameID;
req.user.nameIDFormat = req.user.saml.nameIDFormat;
samlStrategy.logout(req, function(err, request){
if(!err){
//redirect to the IdP Logout URL
res.redirect(request);
}
});
};
edit: the nameId and nameIdFormat has to be saved somewhere on successful login
var samlStrategy = new SamlStrategy(
{
callbackUrl: 'https://mydomain/auth/saml/callback',
entryPoint: 'https://authprovider/endpoint',
logoutUrl: 'https://authprovider/logoutEndPoint',
issuer: 'passport-saml'
},
function(profile, done) {
//Here save the nameId and nameIDFormat somewhere
user.saml = {};
user.saml.nameID = profile.nameID;
user.saml.nameIDFormat = profile.nameIDFormat;
//Do save
});
});
This URL should be configured in your SP metadata in your IdP configuration. The IdP will redirect to that URL once the logout is done.
in your routes :
app.post('/auth/saml/logout/callback', passport.logoutSamlCallback);
In your passport configuration :
passport.logoutSamlCallback = function(req, res){
req.logout();
res.redirect('/');
}
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