Skip to content
Open
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
37 changes: 37 additions & 0 deletions lib/saml20.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,38 @@ function getNameFormat(name){
return 'urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified';
}

/**
*
* @param {object} options
* @param options.key
* @param options.cert
* @param {string} [options.signatureAlgorithm]
* @param {string} [options.digestAlgorithm]
* @param {boolean} [options.includeAttributeNameFormat=true]
* @param [options.typedAttributes]
* @param {string} [options.issuer] Issuer of the SAML assertion
* @param [options.lifetimeInSeconds] timeframe in which this assertion is valid
* @param [options.recipient] recipient for the confirmation data
* @param [options.audiences]
* @param {string} [options.inResponseTo] SAML SubjectConfirmationData@InResponseTo
* @param {object} [options.attributes] assertion attributes. {@link https://github.com/auth0/node-saml/issues/33 Do not pass an empty object}
* @param [options.sessionIndex] session this assertion applies to
* @param {int} [options.sessionNotOnOrAfterSeconds] after this timestamp, the service provider must reauthenticate
* @param {string} [options.nameIdentifier] SAML nameID
* @param [options.nameIdentifierFormat] SAML nameID format
* @param [options.authnContextClassRef]
* @param [options.xpathToNodeBeforeSignature]
* @param [options.encryptionCert]
* @param [options.encryptionPublicKey]
* @param [options.encryptionAlgorithm]
* @param [options.keyEncryptionAlgorighm] {@link https://github.com/auth0/node-xml-encryption/issues/19 note spelling}
* @param {string} [options.prefix]
* @param {string|number} [options.signatureNamespacePrefix]
* @param {string} [options.uid] SAML document ID
* @param {function<T>} [callback] required if options.encryptionCert is specified
* @return {string|T|null}
* @template T
*/
exports.create = function(options, callback) {
if (!options.key)
throw new Error('Expect a private key in pem format');
Expand Down Expand Up @@ -175,6 +207,11 @@ exports.create = function(options, callback) {
.setAttribute('SessionIndex', options.sessionIndex);
}

if (options.sessionNotOnOrAfterSeconds) {
doc.getElementsByTagName('saml:AuthnStatement')[0]
.setAttribute('SessionNotOnOrAfter', moment.unix(options.sessionNotOnOrAfterSeconds).utc().format('YYYY-MM-DDTHH:mm:ss.SSS[Z]'));
}

var nameID = doc.documentElement.getElementsByTagNameNS(NAMESPACE, 'NameID')[0];

if (options.nameIdentifier) {
Expand Down
19 changes: 18 additions & 1 deletion test/saml20.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ describe('saml 2.0', function () {
assert.equal('123', attributes[4].textContent);
});

it('should set attributes to anytpe when typedAttributes is false', function () {
it('should set attributes to anyType when typedAttributes is false', function () {
var options = {
cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
key: fs.readFileSync(__dirname + '/test-auth0.key'),
Expand Down Expand Up @@ -439,7 +439,24 @@ describe('saml 2.0', function () {
var signature = doc.documentElement.getElementsByTagName('Signature');
assert.equal('saml:Conditions', signature[0].previousSibling.nodeName);
});

it('should add SessionNotOnOrAfter when specified', function() {
var now = 5000;
var options = {
cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
key: fs.readFileSync(__dirname + '/test-auth0.key'),
sessionNotOnOrAfterSeconds: now
};

var signedAssertion = saml.create(options);

var isValid = utils.isValidSignature(signedAssertion, options.cert);
assert.equal(true, isValid);

var doc = new xmldom.DOMParser().parseFromString(signedAssertion, 'text/xml');
var sessionNotOnOrAfter = doc.documentElement.getElementsByTagName('saml:AuthnStatement')[0].getAttribute('SessionNotOnOrAfter');
assert.equal(sessionNotOnOrAfter, '1970-01-01T01:23:20.000Z');
});

it('should not include AudienceRestriction when there are no audiences', function () {
var options = {
Expand Down