Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support dynamic SAML configuration lookup
Browse files Browse the repository at this point in the history
stavros-wb committed Apr 4, 2018
1 parent 2de3528 commit 20aa0a9
Showing 4 changed files with 140 additions and 1 deletion.
1 change: 1 addition & 0 deletions lib/passport-saml/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
exports.Strategy = require('./strategy');
exports.MultiSamlStrategy = require('./multiStrategy');
exports.SAML = require('./saml').SAML;
43 changes: 43 additions & 0 deletions lib/passport-saml/multiStrategy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
'use strict';
var util = require('util');
var saml = require('./saml');
var SamlStrategy = require('./strategy');

function MultiSamlStrategy (options, verify) {
if (!options || typeof options.fetchSamlOptions != 'function') {
throw new Error('Please provide a finder method');
}

SamlStrategy.call(this, options, verify);
this._fetchSamlOptions = options.fetchSamlOptions;
}

util.inherits(MultiSamlStrategy, SamlStrategy);

MultiSamlStrategy.prototype.authenticate = function (req, options) {
var self = this;

this._fetchSamlOptions(req, function (err, samlOptions) {
if (err) {
throw err;
}

self._saml = new saml.SAML(samlOptions);
self.constructor.super_.prototype.authenticate.call(self, req, options);
});
}

MultiSamlStrategy.prototype.logout = function (req, options) {
var self = this;

this._fetchSamlOptions(req, function (err, samlOptions) {
if (err) {
throw err;
}

self._saml = new saml.SAML(samlOptions);
self.constructor.super_.prototype.logout.call(self, req, options);
});
}

module.exports = MultiSamlStrategy;
2 changes: 1 addition & 1 deletion lib/passport-saml/saml.js
Original file line number Diff line number Diff line change
@@ -802,7 +802,7 @@ SAML.prototype.processValidlySignedAssertion = function(xml, inResponseTo, callb
if(conErr)
throw conErr;
}

if (self.options.audience) {
var audienceErr = self.checkAudienceValidityError(
self.options.audience, conditions.AudienceRestriction);
95 changes: 95 additions & 0 deletions test/multiStrategy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
'use strict';

var sinon = require('sinon');
var should = require( 'should' );
var SamlStrategy = require( '../lib/passport-saml/index.js' ).Strategy;
var MultiSamlStrategy = require( '../lib/passport-saml/index.js' ).MultiSamlStrategy;

function verify () {}

describe('Strategy()', function() {
it('extends passport Strategy', function() {
function fetchSamlOptions () { return {} }
var strategy = new MultiSamlStrategy({ fetchSamlOptions: fetchSamlOptions }, verify);
strategy.should.be.an.instanceOf(SamlStrategy);
});

it('throws if wrong finder is provided', function() {
function createStrategy (){ return new MultiSamlStrategy({}, verify) };
should.throws(createStrategy);
});
});

describe('strategy#authenticate', function() {
beforeEach(function() {
this.superAuthenticateStub = sinon.stub(SamlStrategy.prototype, 'authenticate');
});

afterEach(function() {
this.superAuthenticateStub.restore();
});

it('calls super with request and auth options', function(done) {
var superAuthenticateStub = this.superAuthenticateStub;
function fetchSamlOptions () { return {} }

var strategy = new MultiSamlStrategy({ fetchSamlOptions: fetchSamlOptions }, verify);
strategy.authenticate().then(
function () {
sinon.assert.calledOnce(superAuthenticateStub);
done();
}
);
});

it('fetches the options using the finder', function(done) {
var req = { test: 'foo' };
var fetchSamlOptions = sinon.stub().withArgs(req).
onFirstCall().
returns({});

var strategy = new MultiSamlStrategy({ fetchSamlOptions: fetchSamlOptions }, verify);
strategy.authenticate().then(done);
});

it('uses fetched options to setup passport options', function(done) {
var passportOptions = {
passReqToCallback: true,
authnRequestBinding: 'HTTP-POST'
};
function fetchSamlOptions () { return passportOptions }

var strategy = new MultiSamlStrategy({ fetchSamlOptions: fetchSamlOptions }, verify);
strategy.authenticate().then(
function() {
strategy._passReqToCallback.should.eql(true);
strategy._authnRequestBinding.should.eql('HTTP-POST');
done();
}
);
});

it('uses fetched options to setup internal saml provider', function(done) {
var samlOptions = {
issuer: 'http://foo.issuer',
callbackUrl: 'http://foo.callback',
cert: 'deadbeef',
host: 'lvh',
acceptedClockSkewMs: -1,
identifierFormat:
'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
path: '/saml/callback',
logoutUrl: 'http://foo.slo',
signatureAlgorithm: 'sha256'
};
function fetchSamlOptions () { return samlOptions }

var strategy = new MultiSamlStrategy({ fetchSamlOptions: fetchSamlOptions }, verify);
strategy.authenticate().then(
function() {
strategy._saml.options.should.containEql(samlOptions);
done();
}
);
});
});

0 comments on commit 20aa0a9

Please sign in to comment.