Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

InResponseTo support for logout #356

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions lib/passport-saml/saml.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,10 @@ SAML.prototype.generateLogoutRequest = function (req) {
};
}

return xmlbuilder.create(request).end();
return Q.ninvoke(this.cacheProvider, 'save', id, instant)
.then(function() {
return xmlbuilder.create(request).end();
});
};

SAML.prototype.generateLogoutResponse = function (req, logoutRequest) {
Expand Down Expand Up @@ -467,10 +470,13 @@ SAML.prototype.getAuthorizeForm = function (req, callback) {
};

SAML.prototype.getLogoutUrl = function(req, options, callback) {
var request = this.generateLogoutRequest(req);
var operation = 'logout';
var overrideParams = options ? options.additionalParams || {} : {};
this.requestToUrl(request, null, operation, this.getAdditionalParams(req, operation, overrideParams), callback);
var self = this;
return self.generateLogoutRequest(req)
.then(function(request) {
var operation = 'logout';
var overrideParams = options ? options.additionalParams || {} : {};
return self.requestToUrl(request, null, operation, self.getAdditionalParams(req, operation, overrideParams), callback);
});
};

SAML.prototype.getLogoutResponseUrl = function(req, options, callback) {
Expand Down
92 changes: 72 additions & 20 deletions test/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -589,18 +589,21 @@ describe( 'passport-saml /', function() {
'saml:NameID': [ { _: 'bar', '$': { Format: 'foo' } } ] } };

var samlObj = new SAML( { entryPoint: "foo" } );
var logoutRequest = samlObj.generateLogoutRequest({
var logoutRequestPromise = samlObj.generateLogoutRequest({
user: {
nameIDFormat: 'foo',
nameID: 'bar'
}
});
parseString( logoutRequest, function( err, doc ) {
delete doc['samlp:LogoutRequest']['$']["ID"];
delete doc['samlp:LogoutRequest']['$']["IssueInstant"];
doc.should.eql( expectedRequest );
done();
});

logoutRequestPromise.then(function(logoutRequest) {
parseString( logoutRequest, function( err, doc ) {
delete doc['samlp:LogoutRequest']['$']["ID"];
delete doc['samlp:LogoutRequest']['$']["IssueInstant"];
doc.should.eql( expectedRequest );
done();
});
})
});

it( 'generateLogoutRequest adds the NameQualifier and SPNameQualifier to the saml request', function( done ) {
Expand All @@ -621,20 +624,23 @@ describe( 'passport-saml /', function() {
NameQualifier: 'Identity Provider' } } ] } };

var samlObj = new SAML( { entryPoint: "foo" } );
var logoutRequest = samlObj.generateLogoutRequest({
var logoutRequestPromise = samlObj.generateLogoutRequest({
user: {
nameIDFormat: 'foo',
nameID: 'bar',
nameQualifier: 'Identity Provider',
spNameQualifier: 'Service Provider'
}
});
parseString( logoutRequest, function( err, doc ) {
delete doc['samlp:LogoutRequest']['$']["ID"];
delete doc['samlp:LogoutRequest']['$']["IssueInstant"];
doc.should.eql( expectedRequest );
done();
});

logoutRequestPromise.then(function(logoutRequest) {
parseString( logoutRequest, function( err, doc ) {
delete doc['samlp:LogoutRequest']['$']["ID"];
delete doc['samlp:LogoutRequest']['$']["IssueInstant"];
doc.should.eql( expectedRequest );
done();
});
})
});

it( 'generateLogoutResponse', function( done ) {
Expand Down Expand Up @@ -680,19 +686,65 @@ describe( 'passport-saml /', function() {
'$': { 'xmlns:saml2p': 'urn:oasis:names:tc:SAML:2.0:protocol' } } ] } };

var samlObj = new SAML( { entryPoint: "foo" } );
var logoutRequest = samlObj.generateLogoutRequest({
var logoutRequestPromise = samlObj.generateLogoutRequest({
user: {
nameIDFormat: 'foo',
nameID: 'bar',
sessionIndex: 'session-id'
}
});
parseString( logoutRequest, function( err, doc ) {
delete doc['samlp:LogoutRequest']['$']["ID"];
delete doc['samlp:LogoutRequest']['$']["IssueInstant"];
doc.should.eql( expectedRequest );
done();

logoutRequestPromise.then(function(logoutRequest) {
parseString( logoutRequest, function( err, doc ) {
delete doc['samlp:LogoutRequest']['$']["ID"];
delete doc['samlp:LogoutRequest']['$']["IssueInstant"];
doc.should.eql( expectedRequest );
done();
});
})
});

it( 'generateLogoutRequest saves id and instant to cache', function( done ) {
var expectedRequest = {
'samlp:LogoutRequest':
{ '$':
{ 'xmlns:samlp': 'urn:oasis:names:tc:SAML:2.0:protocol',
'xmlns:saml': 'urn:oasis:names:tc:SAML:2.0:assertion',
//ID: '_85ba0a112df1ffb57805',
Version: '2.0',
//IssueInstant: '2014-05-29T03:32:23Z',
Destination: 'foo' },
'saml:Issuer':
[ { _: 'onelogin_saml',
'$': { 'xmlns:saml': 'urn:oasis:names:tc:SAML:2.0:assertion' } } ],
'saml:NameID': [ { _: 'bar', '$': { Format: 'foo' } } ],
'saml2p:SessionIndex':
[ { _: 'session-id',
'$': { 'xmlns:saml2p': 'urn:oasis:names:tc:SAML:2.0:protocol' } } ] } };

var samlObj = new SAML( { entryPoint: "foo" } );
var cacheSaveSpy = sinon.spy(samlObj.cacheProvider, 'save')
var logoutRequestPromise = samlObj.generateLogoutRequest({
user: {
nameIDFormat: 'foo',
nameID: 'bar',
sessionIndex: 'session-id'
}
});

logoutRequestPromise.then(function(logoutRequest) {
parseString( logoutRequest, function( err, doc ) {

var id = doc['samlp:LogoutRequest']['$']["ID"];
var issueInstant = doc['samlp:LogoutRequest']['$']["IssueInstant"];

id.should.be.an.instanceOf(String);
issueInstant.should.be.an.instanceOf(String);
cacheSaveSpy.called.should.eql(true);
cacheSaveSpy.calledWith(id, issueInstant).should.eql(true);
done();
});
})
});

describe( 'generateServiceProviderMetadata tests /', function() {
Expand Down