diff --git a/lib/saml11.js b/lib/saml11.js index f359aa54..7156d609 100644 --- a/lib/saml11.js +++ b/lib/saml11.js @@ -3,8 +3,8 @@ var utils = require('./utils'), Parser = require('xmldom').DOMParser, SignedXml = require('xml-crypto').SignedXml, xmlenc = require('xml-encryption'), - moment = require('moment'); - async = require('async'); + moment = require('moment'), + async = require('async'), crypto = require('crypto'); var fs = require('fs'); @@ -28,26 +28,24 @@ exports.create = function(options, callback) { if (!options.key) throw new Error('Expect a private key in pem format'); - if (!options.cert) - throw new Error('Expect a public key cert in pem format'); - options.signatureAlgorithm = options.signatureAlgorithm || 'rsa-sha256'; options.digestAlgorithm = options.digestAlgorithm || 'sha256'; - var cert = utils.pemToCert(options.cert); - var sig = new SignedXml(null, { signatureAlgorithm: algorithms.signature[options.signatureAlgorithm], idAttribute: 'AssertionID' }); sig.addReference("//*[local-name(.)='Assertion']", ["http://www.w3.org/2000/09/xmldsig#enveloped-signature", "http://www.w3.org/2001/10/xml-exc-c14n#"], algorithms.digest[options.digestAlgorithm]); sig.signingKey = options.key; - - sig.keyInfoProvider = { - getKeyInfo: function () { - return "" + cert + ""; - } - }; + + if (options.cert) { + var cert = utils.pemToCert(options.cert); + sig.keyInfoProvider = { + getKeyInfo: function () { + return "" + cert + ""; + } + }; + } var doc; try { diff --git a/lib/saml20.js b/lib/saml20.js index 21c1f278..8cf7c968 100644 --- a/lib/saml20.js +++ b/lib/saml20.js @@ -59,9 +59,6 @@ exports.create = function(options, callback) { if (!options.key) throw new Error('Expect a private key in pem format'); - if (!options.cert) - throw new Error('Expect a public key cert in pem format'); - options.signatureAlgorithm = options.signatureAlgorithm || 'rsa-sha256'; options.digestAlgorithm = options.digestAlgorithm || 'sha256'; @@ -72,21 +69,22 @@ exports.create = function(options, callback) { options.signatureNamespacePrefix = options.signatureNamespacePrefix || options.prefix; options.signatureNamespacePrefix = typeof options.signatureNamespacePrefix === 'string' ? options.signatureNamespacePrefix : '' ; - var cert = utils.pemToCert(options.cert); - var sig = new SignedXml(null, { signatureAlgorithm: algorithms.signature[options.signatureAlgorithm], idAttribute: 'ID' }); sig.addReference("//*[local-name(.)='Assertion']", ["http://www.w3.org/2000/09/xmldsig#enveloped-signature", "http://www.w3.org/2001/10/xml-exc-c14n#"], algorithms.digest[options.digestAlgorithm]); sig.signingKey = options.key; - - sig.keyInfoProvider = { - getKeyInfo: function (key, prefix) { - prefix = prefix ? prefix + ':' : prefix; - return "<" + prefix + "X509Data><" + prefix + "X509Certificate>" + cert + ""; - } - }; + + if (options.cert) { + var cert = utils.pemToCert(options.cert); + sig.keyInfoProvider = { + getKeyInfo: function (key, prefix) { + prefix = prefix ? prefix + ':' : prefix; + return "<" + prefix + "X509Data><" + prefix + "X509Certificate>" + cert + ""; + } + }; + } var doc; try { diff --git a/package.json b/package.json index 2eacb838..d2a1ae21 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "saml", - "version": "0.13.0", + "version": "0.13.1", "devDependencies": { "mocha": "3.5.3", "should": "~1.2.1" diff --git a/test/saml11.tests.js b/test/saml11.tests.js index d924c278..f4314122 100644 --- a/test/saml11.tests.js +++ b/test/saml11.tests.js @@ -22,6 +22,16 @@ describe('saml 1.1', function () { var isValid = utils.isValidSignature(signedAssertion, options.cert); assert.equal(true, isValid); }); + + it('should ignore cert if not present', function () { + var options = { + key: fs.readFileSync(__dirname + '/test-auth0.key') + }; + + var signedAssertion = saml11.create(options); + var isValid = utils.isValidSignature(signedAssertion, fs.readFileSync(__dirname + '/test-auth0.pem')); + assert.equal(true, isValid); + }); it('should support specifying Issuer property', function () { var options = { diff --git a/test/saml20.tests.js b/test/saml20.tests.js index e351cfa3..0487ff8b 100644 --- a/test/saml20.tests.js +++ b/test/saml20.tests.js @@ -56,6 +56,26 @@ describe('saml 2.0', function () { assert.equal('urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified', authnContextClassRef.textContent); }); + + it('should ignore cert if not present', function () { + var options = { + key: fs.readFileSync(__dirname + '/test-auth0.key'), + issuer: 'urn:issuer', + lifetimeInSeconds: 600, + audiences: 'urn:myapp', + attributes: { + 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress': 'foo@bar.com', + 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name': 'Foo Bar' + }, + nameIdentifier: 'foo', + nameIdentifierFormat: 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified' + }; + + var signedAssertion = saml.create(options); + var isValid = utils.isValidSignature(signedAssertion, fs.readFileSync(__dirname + '/test-auth0.pem')); + assert.equal(true, isValid); + }); + it('should set attributes', function () { var options = { cert: fs.readFileSync(__dirname + '/test-auth0.pem'), @@ -440,7 +460,6 @@ describe('saml 2.0', function () { assert.equal('saml:Conditions', signature[0].previousSibling.nodeName); }); - it('should not include AudienceRestriction when there are no audiences', function () { var options = { cert: fs.readFileSync(__dirname + '/test-auth0.pem'),