saml 2.0.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,15 @@
1
+ name: Semgrep
2
+ on:
3
+ pull_request: {}
4
+ push:
5
+ branches: ["master"]
6
+ jobs:
7
+ semgrep:
8
+ name: Scan
9
+ runs-on: ubuntu-latest
10
+ if: (github.actor != 'dependabot[bot]' && github.actor != 'snyk-bot')
11
+ steps:
12
+ - uses: actions/checkout@v2
13
+ - uses: returntocorp/semgrep-action@v1
14
+ with:
15
+ publishToken: ${{ secrets.SEMGREP_APP_TOKEN }}
@@ -0,0 +1,6 @@
1
+ <component name="InspectionProjectProfileManager">
2
+ <profile version="1.0">
3
+ <option name="myName" value="Project Default" />
4
+ <inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
5
+ </profile>
6
+ </component>
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="JavaScriptLibraryMappings">
4
+ <includedPredefinedLibrary name="Node.js Core" />
5
+ </component>
6
+ </project>
@@ -5,6 +5,7 @@
5
5
  <excludeFolder url="file://$MODULE_DIR$/temp" />
6
6
  <excludeFolder url="file://$MODULE_DIR$/.tmp" />
7
7
  <excludeFolder url="file://$MODULE_DIR$/tmp" />
8
+ <excludeFolder url="file://$MODULE_DIR$/.idea" />
8
9
  </content>
9
10
  <orderEntry type="inheritedJdk" />
10
11
  <orderEntry type="sourceFolder" forTests="false" />
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="PrettierConfiguration">
4
+ <option name="myRunOnSave" value="true" />
5
+ <option name="myRunOnReformat" value="true" />
6
+ </component>
7
+ </project>
@@ -0,0 +1,2 @@
1
+
2
+ �javascript:S1488"bImmediately return this expression instead of assigning it to the temporary variable "signatures".(����8�����/
@@ -0,0 +1,15 @@
1
+
2
+ <
3
+ CHANGELOG.md,a/b/ab09011fa121d0a2bb9fa4ca76094f2482b902b7
4
+ G
5
+ test/test-auth0_rsa.pub,1/6/16c55078736dc7b024c5f6aee3724b578a6f762e
6
+ <
7
+ package.json,7/0/7030d0b2f71b999ff89a343de08c414af32fc93a
8
+ C
9
+ test/test-auth0.pem,9/8/988145bf095565ed2790e577ca6610aae3f148eb
10
+ C
11
+ test/test-auth0.key,b/f/bf580f9fe6b7aafd1864a1b474928848f50d9486
12
+ =
13
+
14
+ I
15
+ test/test-auth0-chain.pem,1/5/152d3f39906314d7648bee688e6cf0e074eac700
package/CHANGELOG.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ## [3.0.0](https://github.com/auth0/node-saml/compare/v2.0.1...v3.0.0) (2022-05-12)
6
+
7
+
8
+ ### ⚠ BREAKING CHANGES
9
+
10
+ * handle poorly formatted PEM files (#85)
11
+
12
+ ### Bug Fixes
13
+
14
+ * handle poorly formatted PEM files ([#85](https://github.com/auth0/node-saml/issues/85)) ([8830a23](https://github.com/auth0/node-saml/commit/8830a238d33e2e198acd81fb6d972583848bfe26))
15
+
5
16
  ### [2.0.1](https://github.com/auth0/node-saml/compare/v2.0.0...v2.0.1) (2022-02-09)
6
17
 
7
18
 
package/lib/utils.js CHANGED
@@ -1,8 +1,8 @@
1
- var fs = require('fs');
2
- var Parser = require('@xmldom/xmldom').DOMParser;
1
+ const fs = require('fs');
2
+ const Parser = require('@xmldom/xmldom').DOMParser;
3
3
 
4
4
  exports.pemToCert = function(pem) {
5
- var cert = /-----BEGIN CERTIFICATE-----([^-]*)-----END CERTIFICATE-----/g.exec(pem.toString());
5
+ const cert = /-----BEGIN CERTIFICATE-----([^-]*)-----END CERTIFICATE-----/g.exec(pem.toString());
6
6
  if (cert && cert.length > 0) {
7
7
  return cert[1].replace(/[\n|\r\n]/g, '');
8
8
  }
@@ -29,11 +29,11 @@ exports.reportError = function(err, callback){
29
29
  * @api private
30
30
  */
31
31
  exports.uid = function(len) {
32
- var buf = []
33
- , chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
34
- , charlen = chars.length;
32
+ const buf = []
33
+ , chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
34
+ , charlen = chars.length;
35
35
 
36
- for (var i = 0; i < len; ++i) {
36
+ for (let i = 0; i < len; ++i) {
37
37
  buf.push(chars[getRandomInt(0, charlen - 1)]);
38
38
  }
39
39
 
@@ -41,16 +41,15 @@ exports.uid = function(len) {
41
41
  };
42
42
 
43
43
  exports.removeWhitespace = function(xml) {
44
- var trimmed = xml
45
- .replace(/\r\n/g, '')
46
- .replace(/\n/g,'')
47
- .replace(/>(\s*)</g, '><') //unindent
48
- .trim();
49
- return trimmed;
44
+ return xml
45
+ .replace(/\r\n/g, '')
46
+ .replace(/\n/g, '')
47
+ .replace(/>(\s*)</g, '><') //unindent
48
+ .trim();
50
49
  };
51
50
 
52
51
  /**
53
- * Retrun a random int, used by `utils.uid()`
52
+ * Return a random int, used by `utils.uid()`
54
53
  *
55
54
  * @param {Number} min
56
55
  * @param {Number} max
@@ -69,10 +68,29 @@ function getRandomInt(min, max) {
69
68
  * @return {function(): Node}
70
69
  */
71
70
  exports.factoryForNode = function factoryForNode(pathToTemplate) {
72
- var template = fs.readFileSync(pathToTemplate)
73
- var prototypeDoc = new Parser().parseFromString(template.toString())
71
+ const template = fs.readFileSync(pathToTemplate);
72
+ const prototypeDoc = new Parser().parseFromString(template.toString());
74
73
 
75
74
  return function () {
76
75
  return prototypeDoc.cloneNode(true);
77
76
  };
78
77
  };
78
+
79
+ /**
80
+ * Standardizes PEM content to match the spec (best effort)
81
+ *
82
+ * @param pem {Buffer} The PEM content to standardize
83
+ * @returns {Buffer} The standardized PEM. Original will be returned unmodified if the content is not PEM.
84
+ */
85
+ exports.fixPemFormatting = function (pem) {
86
+ let pemEntries = pem.toString().matchAll(/([-]{5}[^-\r\n]+[-]{5})([^-]*)([-]{5}[^-\r\n]+[-]{5})/g);
87
+ let fixedPem = ''
88
+ for (const pemParts of pemEntries) {
89
+ fixedPem = fixedPem.concat(`${pemParts[1]}\n${pemParts[2].replaceAll(/[\r\n]/g, '')}\n${pemParts[3]}\n`)
90
+ }
91
+ if (fixedPem.length === 0) {
92
+ return pem;
93
+ }
94
+
95
+ return Buffer.from(fixedPem)
96
+ }
@@ -1,12 +1,12 @@
1
- var xmlenc = require('xml-encryption');
1
+ const xmlenc = require('xml-encryption');
2
2
 
3
- var utils = require('../utils');
3
+ const utils = require('../utils');
4
4
 
5
5
  exports.fromEncryptXmlOptions = function (options) {
6
6
  if (!options.encryptionCert) {
7
7
  return this.unencrypted;
8
8
  } else {
9
- var encryptOptions = {
9
+ const encryptOptions = {
10
10
  rsa_pub: options.encryptionPublicKey,
11
11
  pem: options.encryptionCert,
12
12
  encryptionAlgorithm: options.encryptionAlgorithm || 'http://www.w3.org/2001/04/xmlenc#aes256-cbc',
@@ -29,8 +29,26 @@ exports.unencrypted = function (xml, callback) {
29
29
  exports.encrypted = function (encryptOptions) {
30
30
  return function encrypt(xml, callback) {
31
31
  xmlenc.encrypt(xml, encryptOptions, function (err, encrypted) {
32
- if (err) return callback(err);
33
- callback(null, utils.removeWhitespace(encrypted));
32
+ if (err) {
33
+ // Attempt to fix errors and retry
34
+ xmlenc.encrypt(
35
+ xml,
36
+ {
37
+ ...encryptOptions,
38
+ rsa_pub: utils.fixPemFormatting(encryptOptions.rsa_pub),
39
+ pem: utils.fixPemFormatting(encryptOptions.pem),
40
+ },
41
+ function (retryErr, retryEncrypted) {
42
+ if (retryErr) {
43
+ return callback(retryErr);
44
+ }
45
+
46
+ callback(null, utils.removeWhitespace(retryEncrypted));
47
+ }
48
+ );
49
+ } else {
50
+ callback(null, utils.removeWhitespace(encrypted));
51
+ }
34
52
  });
35
53
  };
36
54
  };
package/lib/xml/sign.js CHANGED
@@ -1,10 +1,10 @@
1
- var utils = require('../utils');
2
- var SignedXml = require('xml-crypto').SignedXml;
1
+ const utils = require('../utils');
2
+ const SignedXml = require('xml-crypto').SignedXml;
3
3
 
4
- var algorithms = {
4
+ const algorithms = {
5
5
  signature: {
6
6
  'rsa-sha256': 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
7
- 'rsa-sha1': 'http://www.w3.org/2000/09/xmldsig#rsa-sha1'
7
+ 'rsa-sha1': 'http://www.w3.org/2000/09/xmldsig#rsa-sha1'
8
8
  },
9
9
  digest: {
10
10
  'sha256': 'http://www.w3.org/2001/04/xmlenc#sha256',
@@ -22,16 +22,16 @@ exports.fromSignXmlOptions = function (options) {
22
22
  if (!options.xpathToNodeBeforeSignature)
23
23
  throw new Error('xpathToNodeBeforeSignature is required')
24
24
 
25
- var key = options.key;
26
- var pem = options.cert;
27
- var signatureAlgorithm = options.signatureAlgorithm || 'rsa-sha256';
28
- var digestAlgorithm = options.digestAlgorithm || 'sha256';
29
- var signatureNamespacePrefix = (function (prefix) {
25
+ const key = options.key;
26
+ const pem = options.cert;
27
+ const signatureAlgorithm = options.signatureAlgorithm || 'rsa-sha256';
28
+ const digestAlgorithm = options.digestAlgorithm || 'sha256';
29
+ const signatureNamespacePrefix = (function (prefix) {
30
30
  // 0.10.1 added prefix, but we want to name it signatureNamespacePrefix - This is just to keep supporting prefix
31
31
  return typeof prefix === 'string' ? prefix : '';
32
32
  })(options.signatureNamespacePrefix || options.prefix);
33
- var xpathToNodeBeforeSignature = options.xpathToNodeBeforeSignature;
34
- var idAttribute = options.signatureIdAttribute;
33
+ const xpathToNodeBeforeSignature = options.xpathToNodeBeforeSignature;
34
+ const idAttribute = options.signatureIdAttribute;
35
35
 
36
36
  /**
37
37
  * @param {Document} doc
@@ -39,44 +39,63 @@ exports.fromSignXmlOptions = function (options) {
39
39
  * @return {string}
40
40
  */
41
41
  return function signXmlDocument(doc, callback) {
42
- var unsigned = exports.unsigned(doc);
43
- var cert = utils.pemToCert(pem);
42
+ function sign(key) {
43
+ const unsigned = exports.unsigned(doc);
44
+ const cert = utils.pemToCert(pem);
44
45
 
45
- var sig = new SignedXml(null, { signatureAlgorithm: algorithms.signature[signatureAlgorithm], idAttribute: idAttribute });
46
- sig.addReference("//*[local-name(.)='Assertion']",
47
- ["http://www.w3.org/2000/09/xmldsig#enveloped-signature", "http://www.w3.org/2001/10/xml-exc-c14n#"],
48
- algorithms.digest[digestAlgorithm]);
46
+ const sig = new SignedXml(null, {
47
+ signatureAlgorithm: algorithms.signature[signatureAlgorithm],
48
+ idAttribute: idAttribute
49
+ });
50
+ sig.addReference("//*[local-name(.)='Assertion']",
51
+ ["http://www.w3.org/2000/09/xmldsig#enveloped-signature", "http://www.w3.org/2001/10/xml-exc-c14n#"],
52
+ algorithms.digest[digestAlgorithm]);
49
53
 
50
- sig.signingKey = key;
54
+ sig.signingKey = key;
51
55
 
52
- sig.keyInfoProvider = {
53
- getKeyInfo: function (key, prefix) {
54
- prefix = prefix ? prefix + ':' : prefix;
55
- return "<" + prefix + "X509Data><" + prefix + "X509Certificate>" + cert + "</" + prefix + "X509Certificate></" + prefix + "X509Data>";
56
- }
57
- };
56
+ sig.keyInfoProvider = {
57
+ getKeyInfo: function (key, prefix) {
58
+ prefix = prefix ? prefix + ':' : prefix;
59
+ return "<" + prefix + "X509Data><" + prefix + "X509Certificate>" + cert + "</" + prefix + "X509Certificate></" + prefix + "X509Data>";
60
+ }
61
+ };
62
+
63
+ sig.computeSignature(unsigned, {
64
+ location: {reference: xpathToNodeBeforeSignature, action: 'after'},
65
+ prefix: signatureNamespacePrefix
66
+ });
67
+
68
+ return sig.getSignedXml();
69
+ }
58
70
 
59
- sig.computeSignature(unsigned, {
60
- location: { reference: xpathToNodeBeforeSignature, action: 'after' },
61
- prefix: signatureNamespacePrefix
62
- });
71
+ let signed
72
+ try {
73
+ try {
74
+ signed = sign(key)
75
+ } catch (err) {
76
+ signed = sign(utils.fixPemFormatting(key))
77
+ }
63
78
 
64
- var signed = sig.getSignedXml();
65
- if (callback) {
66
- setImmediate(callback, null, signed);
67
- } else {
68
- return signed;
79
+ if (callback) {
80
+ setImmediate(callback, null, signed);
81
+ } else {
82
+ return signed;
83
+ }
84
+ } catch (e) {
85
+ if (callback) {
86
+ setImmediate(callback, e)
87
+ }
88
+ throw e
69
89
  }
70
90
  };
71
91
  };
72
-
73
92
  /**
74
93
  * @param {Document} doc
75
94
  * @param {Function} [callback]
76
95
  * @return {string}
77
96
  */
78
97
  exports.unsigned = function (doc, callback) {
79
- var xml = utils.removeWhitespace(doc.toString());
98
+ const xml = utils.removeWhitespace(doc.toString());
80
99
  if (callback) {
81
100
  setImmediate(callback, null, xml)
82
101
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "saml",
3
- "version": "2.0.1",
3
+ "version": "3.0.0",
4
4
  "engines": {
5
5
  "node": ">=12"
6
6
  },
@@ -46,6 +46,32 @@ describe('saml 1.1', function () {
46
46
  assertSignature(signedAssertion, options);
47
47
  });
48
48
 
49
+ it('should not error when cert is missing newlines', function () {
50
+ // cert created with:
51
+ // openssl req -x509 -new -newkey rsa:2048 -nodes -subj '/CN=auth0.auth0.com/O=Auth0 LLC/C=US/ST=Washington/L=Redmond' -keyout auth0.key -out auth0.pem
52
+
53
+ var options = {
54
+ cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
55
+ key: fs.readFileSync(__dirname + '/test-auth0.key')
56
+ };
57
+
58
+ var signedAssertion = saml11[createAssertion]({...options, cert: Buffer.from(options.cert.toString().replaceAll(/[\r\n]/g, ''))});
59
+ assertSignature(signedAssertion, options);
60
+ });
61
+
62
+ it('should not error when key is missing newlines', function () {
63
+ // cert created with:
64
+ // openssl req -x509 -new -newkey rsa:2048 -nodes -subj '/CN=auth0.auth0.com/O=Auth0 LLC/C=US/ST=Washington/L=Redmond' -keyout auth0.key -out auth0.pem
65
+
66
+ var options = {
67
+ cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
68
+ key: fs.readFileSync(__dirname + '/test-auth0.key')
69
+ };
70
+
71
+ var signedAssertion = saml11[createAssertion]({...options, key: Buffer.from(options.key.toString().replaceAll(/[\r\n]/g, ''))});
72
+ assertSignature(signedAssertion, options);
73
+ });
74
+
49
75
  it('should support specifying Issuer property', function () {
50
76
  var options = {
51
77
  cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
@@ -350,6 +376,44 @@ describe('saml 1.1', function () {
350
376
  });
351
377
  });
352
378
 
379
+ it('should not error when encryptionPublicKey is missing newlines', function (done) {
380
+ var options = {
381
+ cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
382
+ key: fs.readFileSync(__dirname + '/test-auth0.key'),
383
+ encryptionPublicKey: Buffer.from(fs.readFileSync(__dirname + '/test-auth0_rsa.pub').toString().replaceAll(/[\r\n]/g, '')),
384
+ encryptionCert: fs.readFileSync(__dirname + '/test-auth0.pem')
385
+ };
386
+
387
+ saml11[createAssertion](options, function(err, encrypted) {
388
+ if (err) return done(err);
389
+
390
+ xmlenc.decrypt(encrypted, { key: fs.readFileSync(__dirname + '/test-auth0.key')}, function(err, decrypted) {
391
+ if (err) return done(err);
392
+ assertSignature(decrypted, options);
393
+ done();
394
+ });
395
+ });
396
+ });
397
+
398
+ it('should not error when encryptionCert is missing newlines', function (done) {
399
+ var options = {
400
+ cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
401
+ key: fs.readFileSync(__dirname + '/test-auth0.key'),
402
+ encryptionPublicKey: fs.readFileSync(__dirname + '/test-auth0_rsa.pub'),
403
+ encryptionCert: Buffer.from(fs.readFileSync(__dirname + '/test-auth0.pem').toString().replaceAll(/[\r\n]/g, ''))
404
+ };
405
+
406
+ saml11[createAssertion](options, function(err, encrypted) {
407
+ if (err) return done(err);
408
+
409
+ xmlenc.decrypt(encrypted, { key: fs.readFileSync(__dirname + '/test-auth0.key')}, function(err, decrypted) {
410
+ if (err) return done(err);
411
+ assertSignature(decrypted, options);
412
+ done();
413
+ });
414
+ });
415
+ });
416
+
353
417
  it('should support holder-of-key suject confirmationmethod', function (done) {
354
418
  var options = {
355
419
  cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
@@ -77,6 +77,96 @@ describe('saml 2.0', function () {
77
77
  assert.equal('urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified', authnContextClassRef.textContent);
78
78
  });
79
79
 
80
+ it('should not error when cert is missing newlines', function () {
81
+ var options = {
82
+ cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
83
+ key: fs.readFileSync(__dirname + '/test-auth0.key'),
84
+ issuer: 'urn:issuer',
85
+ lifetimeInSeconds: 600,
86
+ audiences: 'urn:myapp',
87
+ attributes: {
88
+ 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress': 'foo@bar.com',
89
+ 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name': 'Foo Bar'
90
+ },
91
+ nameIdentifier: 'foo',
92
+ nameIdentifierFormat: 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified'
93
+ };
94
+
95
+ var signedAssertion = saml[createAssertion]({...options, cert: Buffer.from(options.cert.toString().replaceAll(/[\r\n]/g, ''))});
96
+ assertSignature(signedAssertion, options);
97
+
98
+ var nameIdentifier = utils.getNameID(signedAssertion);
99
+ assert.equal('foo', nameIdentifier.textContent);
100
+ assert.equal('urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified', nameIdentifier.getAttribute('Format'));
101
+
102
+ var attributes = utils.getAttributes(signedAssertion);
103
+ assert.equal(2, attributes.length);
104
+ assert.equal('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress', attributes[0].getAttribute('Name'));
105
+ assert.equal('foo@bar.com', attributes[0].textContent);
106
+ assert.equal('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name', attributes[1].getAttribute('Name'));
107
+ assert.equal('Foo Bar', attributes[1].textContent);
108
+
109
+ assert.equal('urn:issuer', utils.getSaml2Issuer(signedAssertion).textContent);
110
+
111
+ var conditions = utils.getConditions(signedAssertion);
112
+ assert.equal(1, conditions.length);
113
+ var notBefore = conditions[0].getAttribute('NotBefore');
114
+ var notOnOrAfter = conditions[0].getAttribute('NotOnOrAfter');
115
+ should.ok(notBefore);
116
+ should.ok(notOnOrAfter);
117
+
118
+ var lifetime = Math.round((moment(notOnOrAfter).utc() - moment(notBefore).utc()) / 1000);
119
+ assert.equal(600, lifetime);
120
+
121
+ var authnContextClassRef = utils.getAuthnContextClassRef(signedAssertion);
122
+ assert.equal('urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified', authnContextClassRef.textContent);
123
+ });
124
+
125
+ it('should not error when key is missing newlines', function () {
126
+ var options = {
127
+ cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
128
+ key: fs.readFileSync(__dirname + '/test-auth0.key'),
129
+ issuer: 'urn:issuer',
130
+ lifetimeInSeconds: 600,
131
+ audiences: 'urn:myapp',
132
+ attributes: {
133
+ 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress': 'foo@bar.com',
134
+ 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name': 'Foo Bar'
135
+ },
136
+ nameIdentifier: 'foo',
137
+ nameIdentifierFormat: 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified'
138
+ };
139
+
140
+ var signedAssertion = saml[createAssertion]({...options, key: Buffer.from(options.key.toString().replaceAll(/[\r\n]/g, ''))});
141
+ assertSignature(signedAssertion, options);
142
+
143
+ var nameIdentifier = utils.getNameID(signedAssertion);
144
+ assert.equal('foo', nameIdentifier.textContent);
145
+ assert.equal('urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified', nameIdentifier.getAttribute('Format'));
146
+
147
+ var attributes = utils.getAttributes(signedAssertion);
148
+ assert.equal(2, attributes.length);
149
+ assert.equal('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress', attributes[0].getAttribute('Name'));
150
+ assert.equal('foo@bar.com', attributes[0].textContent);
151
+ assert.equal('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name', attributes[1].getAttribute('Name'));
152
+ assert.equal('Foo Bar', attributes[1].textContent);
153
+
154
+ assert.equal('urn:issuer', utils.getSaml2Issuer(signedAssertion).textContent);
155
+
156
+ var conditions = utils.getConditions(signedAssertion);
157
+ assert.equal(1, conditions.length);
158
+ var notBefore = conditions[0].getAttribute('NotBefore');
159
+ var notOnOrAfter = conditions[0].getAttribute('NotOnOrAfter');
160
+ should.ok(notBefore);
161
+ should.ok(notOnOrAfter);
162
+
163
+ var lifetime = Math.round((moment(notOnOrAfter).utc() - moment(notBefore).utc()) / 1000);
164
+ assert.equal(600, lifetime);
165
+
166
+ var authnContextClassRef = utils.getAuthnContextClassRef(signedAssertion);
167
+ assert.equal('urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified', authnContextClassRef.textContent);
168
+ });
169
+
80
170
  it('should set attributes', function () {
81
171
  var options = {
82
172
  cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
@@ -513,6 +603,48 @@ describe('saml 2.0', function () {
513
603
  });
514
604
  });
515
605
 
606
+ it('should not error when encryptionPublicKey is missing newline', function (done) {
607
+ var options = {
608
+ cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
609
+ key: fs.readFileSync(__dirname + '/test-auth0.key'),
610
+ encryptionPublicKey: Buffer.from(fs.readFileSync(__dirname + '/test-auth0_rsa.pub').toString().replaceAll(/[\r\n]/g, '')),
611
+ encryptionCert: fs.readFileSync(__dirname + '/test-auth0.pem')
612
+ };
613
+
614
+ saml[createAssertion](options, function (err, encrypted) {
615
+ if (err) return done(err);
616
+
617
+ var encryptedData = utils.getEncryptedData(encrypted);
618
+
619
+ xmlenc.decrypt(encryptedData.toString(), { key: fs.readFileSync(__dirname + '/test-auth0.key') }, function (err, decrypted) {
620
+ if (err) return done(err);
621
+ assertSignature(decrypted, options);
622
+ done();
623
+ });
624
+ });
625
+ });
626
+
627
+ it('should not error when encryptionCert is missing newline', function (done) {
628
+ var options = {
629
+ cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
630
+ key: fs.readFileSync(__dirname + '/test-auth0.key'),
631
+ encryptionPublicKey: fs.readFileSync(__dirname + '/test-auth0_rsa.pub'),
632
+ encryptionCert: Buffer.from(fs.readFileSync(__dirname + '/test-auth0.pem').toString().replaceAll(/[\r\n]/g, ''))
633
+ };
634
+
635
+ saml[createAssertion](options, function (err, encrypted) {
636
+ if (err) return done(err);
637
+
638
+ var encryptedData = utils.getEncryptedData(encrypted);
639
+
640
+ xmlenc.decrypt(encryptedData.toString(), { key: fs.readFileSync(__dirname + '/test-auth0.key') }, function (err, decrypted) {
641
+ if (err) return done(err);
642
+ assertSignature(decrypted, options);
643
+ done();
644
+ });
645
+ });
646
+ });
647
+
516
648
  it('should set attributes', function (done) {
517
649
  var options = {
518
650
  cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
@@ -0,0 +1,160 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIN1jCCDL6gAwIBAgIRANpcJKruPRmYEgAAAAAFph0wDQYJKoZIhvcNAQELBQAw
3
+ RjELMAkGA1UEBhMCVVMxIjAgBgNVBAoTGUdvb2dsZSBUcnVzdCBTZXJ2aWNlcyBM
4
+ TEMxEzARBgNVBAMTCkdUUyBDQSAxQzMwHhcNMjIwMzE3MTAyNjA4WhcNMjIwNjA5
5
+ MTAyNjA3WjAXMRUwEwYDVQQDDAwqLmdvb2dsZS5jb20wWTATBgcqhkjOPQIBBggq
6
+ hkjOPQMBBwNCAATtYBIFrigABQ4fmk2FmwNZhOsA5o5Z+V6m1npj4TjYTAxTLHoO
7
+ Qv2wKY7YfnQD6Jb7yQhc7Jma4UdPV/jplArko4ILtzCCC7MwDgYDVR0PAQH/BAQD
8
+ AgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYE
9
+ FI0OoPWBuG+vJ2nvFqPxQqYA+RyiMB8GA1UdIwQYMBaAFIp0f6+Fze6VzT2c0OJG
10
+ FPNxNR0nMGoGCCsGAQUFBwEBBF4wXDAnBggrBgEFBQcwAYYbaHR0cDovL29jc3Au
11
+ cGtpLmdvb2cvZ3RzMWMzMDEGCCsGAQUFBzAChiVodHRwOi8vcGtpLmdvb2cvcmVw
12
+ by9jZXJ0cy9ndHMxYzMuZGVyMIIJaAYDVR0RBIIJXzCCCVuCDCouZ29vZ2xlLmNv
13
+ bYIWKi5hcHBlbmdpbmUuZ29vZ2xlLmNvbYIJKi5iZG4uZGV2ghIqLmNsb3VkLmdv
14
+ b2dsZS5jb22CGCouY3Jvd2Rzb3VyY2UuZ29vZ2xlLmNvbYIYKi5kYXRhY29tcHV0
15
+ ZS5nb29nbGUuY29tggsqLmdvb2dsZS5jYYILKi5nb29nbGUuY2yCDiouZ29vZ2xl
16
+ LmNvLmlugg4qLmdvb2dsZS5jby5qcIIOKi5nb29nbGUuY28udWuCDyouZ29vZ2xl
17
+ LmNvbS5hcoIPKi5nb29nbGUuY29tLmF1gg8qLmdvb2dsZS5jb20uYnKCDyouZ29v
18
+ Z2xlLmNvbS5jb4IPKi5nb29nbGUuY29tLm14gg8qLmdvb2dsZS5jb20udHKCDyou
19
+ Z29vZ2xlLmNvbS52boILKi5nb29nbGUuZGWCCyouZ29vZ2xlLmVzggsqLmdvb2ds
20
+ ZS5mcoILKi5nb29nbGUuaHWCCyouZ29vZ2xlLml0ggsqLmdvb2dsZS5ubIILKi5n
21
+ b29nbGUucGyCCyouZ29vZ2xlLnB0ghIqLmdvb2dsZWFkYXBpcy5jb22CDyouZ29v
22
+ Z2xlYXBpcy5jboIRKi5nb29nbGV2aWRlby5jb22CDCouZ3N0YXRpYy5jboIQKi5n
23
+ c3RhdGljLWNuLmNvbYIPZ29vZ2xlY25hcHBzLmNughEqLmdvb2dsZWNuYXBwcy5j
24
+ boIRZ29vZ2xlYXBwcy1jbi5jb22CEyouZ29vZ2xlYXBwcy1jbi5jb22CDGdrZWNu
25
+ YXBwcy5jboIOKi5na2VjbmFwcHMuY26CEmdvb2dsZWRvd25sb2Fkcy5jboIUKi5n
26
+ b29nbGVkb3dubG9hZHMuY26CEHJlY2FwdGNoYS5uZXQuY26CEioucmVjYXB0Y2hh
27
+ Lm5ldC5jboIQcmVjYXB0Y2hhLWNuLm5ldIISKi5yZWNhcHRjaGEtY24ubmV0ggt3
28
+ aWRldmluZS5jboINKi53aWRldmluZS5jboIRYW1wcHJvamVjdC5vcmcuY26CEyou
29
+ YW1wcHJvamVjdC5vcmcuY26CEWFtcHByb2plY3QubmV0LmNughMqLmFtcHByb2pl
30
+ Y3QubmV0LmNughdnb29nbGUtYW5hbHl0aWNzLWNuLmNvbYIZKi5nb29nbGUtYW5h
31
+ bHl0aWNzLWNuLmNvbYIXZ29vZ2xlYWRzZXJ2aWNlcy1jbi5jb22CGSouZ29vZ2xl
32
+ YWRzZXJ2aWNlcy1jbi5jb22CEWdvb2dsZXZhZHMtY24uY29tghMqLmdvb2dsZXZh
33
+ ZHMtY24uY29tghFnb29nbGVhcGlzLWNuLmNvbYITKi5nb29nbGVhcGlzLWNuLmNv
34
+ bYIVZ29vZ2xlb3B0aW1pemUtY24uY29tghcqLmdvb2dsZW9wdGltaXplLWNuLmNv
35
+ bYISZG91YmxlY2xpY2stY24ubmV0ghQqLmRvdWJsZWNsaWNrLWNuLm5ldIIYKi5m
36
+ bHMuZG91YmxlY2xpY2stY24ubmV0ghYqLmcuZG91YmxlY2xpY2stY24ubmV0gg5k
37
+ b3VibGVjbGljay5jboIQKi5kb3VibGVjbGljay5jboIUKi5mbHMuZG91YmxlY2xp
38
+ Y2suY26CEiouZy5kb3VibGVjbGljay5jboIRZGFydHNlYXJjaC1jbi5uZXSCEyou
39
+ ZGFydHNlYXJjaC1jbi5uZXSCHWdvb2dsZXRyYXZlbGFkc2VydmljZXMtY24uY29t
40
+ gh8qLmdvb2dsZXRyYXZlbGFkc2VydmljZXMtY24uY29tghhnb29nbGV0YWdzZXJ2
41
+ aWNlcy1jbi5jb22CGiouZ29vZ2xldGFnc2VydmljZXMtY24uY29tghdnb29nbGV0
42
+ YWdtYW5hZ2VyLWNuLmNvbYIZKi5nb29nbGV0YWdtYW5hZ2VyLWNuLmNvbYIYZ29v
43
+ Z2xlc3luZGljYXRpb24tY24uY29tghoqLmdvb2dsZXN5bmRpY2F0aW9uLWNuLmNv
44
+ bYIkKi5zYWZlZnJhbWUuZ29vZ2xlc3luZGljYXRpb24tY24uY29tghZhcHAtbWVh
45
+ c3VyZW1lbnQtY24uY29tghgqLmFwcC1tZWFzdXJlbWVudC1jbi5jb22CC2d2dDEt
46
+ Y24uY29tgg0qLmd2dDEtY24uY29tggtndnQyLWNuLmNvbYINKi5ndnQyLWNuLmNv
47
+ bYILMm1kbi1jbi5uZXSCDSouMm1kbi1jbi5uZXSCFGdvb2dsZWZsaWdodHMtY24u
48
+ bmV0ghYqLmdvb2dsZWZsaWdodHMtY24ubmV0ggxhZG1vYi1jbi5jb22CDiouYWRt
49
+ b2ItY24uY29tgg0qLmdzdGF0aWMuY29tghQqLm1ldHJpYy5nc3RhdGljLmNvbYIK
50
+ Ki5ndnQxLmNvbYIRKi5nY3BjZG4uZ3Z0MS5jb22CCiouZ3Z0Mi5jb22CDiouZ2Nw
51
+ Lmd2dDIuY29tghAqLnVybC5nb29nbGUuY29tghYqLnlvdXR1YmUtbm9jb29raWUu
52
+ Y29tggsqLnl0aW1nLmNvbYILYW5kcm9pZC5jb22CDSouYW5kcm9pZC5jb22CEyou
53
+ Zmxhc2guYW5kcm9pZC5jb22CBGcuY26CBiouZy5jboIEZy5jb4IGKi5nLmNvggZn
54
+ b28uZ2yCCnd3dy5nb28uZ2yCFGdvb2dsZS1hbmFseXRpY3MuY29tghYqLmdvb2ds
55
+ ZS1hbmFseXRpY3MuY29tggpnb29nbGUuY29tghJnb29nbGVjb21tZXJjZS5jb22C
56
+ FCouZ29vZ2xlY29tbWVyY2UuY29tgghnZ3BodC5jboIKKi5nZ3BodC5jboIKdXJj
57
+ aGluLmNvbYIMKi51cmNoaW4uY29tggh5b3V0dS5iZYILeW91dHViZS5jb22CDSou
58
+ eW91dHViZS5jb22CFHlvdXR1YmVlZHVjYXRpb24uY29tghYqLnlvdXR1YmVlZHVj
59
+ YXRpb24uY29tgg95b3V0dWJla2lkcy5jb22CESoueW91dHViZWtpZHMuY29tggV5
60
+ dC5iZYIHKi55dC5iZYIaYW5kcm9pZC5jbGllbnRzLmdvb2dsZS5jb22CG2RldmVs
61
+ b3Blci5hbmRyb2lkLmdvb2dsZS5jboIcZGV2ZWxvcGVycy5hbmRyb2lkLmdvb2ds
62
+ ZS5jboIYc291cmNlLmFuZHJvaWQuZ29vZ2xlLmNuMCEGA1UdIAQaMBgwCAYGZ4EM
63
+ AQIBMAwGCisGAQQB1nkCBQMwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybHMu
64
+ cGtpLmdvb2cvZ3RzMWMzL2ZWSnhiVi1LdG1rLmNybDCCAQMGCisGAQQB1nkCBAIE
65
+ gfQEgfEA7wB2ACl5vvCeOTkh8FZzn2Old+W+V32cYAr4+U1dJlwlXceEAAABf5eg
66
+ 31sAAAQDAEcwRQIgKO/qyXDbVstUmyGkus1+NtSfQeBVeaah4uvJ4h5zODUCIQCr
67
+ IAXRbx0K9/GQGOK/OCcdH04AszWgCoHyR2AZjTaTfQB1AN+lXqtogk8fbK3uuF9O
68
+ PlrqzaISpGpejjsSwCBEXCpzAAABf5eg364AAAQDAEYwRAIgAr7Yby6/4yctoeiV
69
+ N84JsUBOFT8H5Wm9/JxeRhLzOOcCIAXVbvK2b8fGEBcnMXaiMEB3A2NknYf3eeKV
70
+ hkPNl1/BMA0GCSqGSIb3DQEBCwUAA4IBAQAfxzM4OzKzXj4vvS4ian65PHlV1YiY
71
+ JOonKRWzA3LDjZ0TAF1WMEXiD46yV6HYAYdeQTGin6AaL2P4Z11rCVJPQVHW6UGv
72
+ 8AoqW4QmBer0U3dJpu28UZ7IA2KPUdAJKhukl7Y5M4fotMxydh5nmh/743GZw3g9
73
+ krSDY8HAFqhr2R9zo2gh42IPUQI4YJcZiU4vnZlaE9NbaJmZmCm357AJ6RhHMC66
74
+ WZ1O8+UD3EpkFWamhrPEU2GOLFjDDG/SOtXv7BBG0zCn/VRwShCj5kfivZWfWxvN
75
+ /UrJwT49JDcuuHV7P0SwabvCQurMRd7J6ANO+esgdxGavWsnzT4U3Ac2
76
+ -----END CERTIFICATE-----
77
+ -----BEGIN CERTIFICATE-----
78
+ MIIFljCCA36gAwIBAgINAgO8U1lrNMcY9QFQZjANBgkqhkiG9w0BAQsFADBHMQsw
79
+ CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
80
+ MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMjAwODEzMDAwMDQyWhcNMjcwOTMwMDAw
81
+ MDQyWjBGMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp
82
+ Y2VzIExMQzETMBEGA1UEAxMKR1RTIENBIDFDMzCCASIwDQYJKoZIhvcNAQEBBQAD
83
+ ggEPADCCAQoCggEBAPWI3+dijB43+DdCkH9sh9D7ZYIl/ejLa6T/belaI+KZ9hzp
84
+ kgOZE3wJCor6QtZeViSqejOEH9Hpabu5dOxXTGZok3c3VVP+ORBNtzS7XyV3NzsX
85
+ lOo85Z3VvMO0Q+sup0fvsEQRY9i0QYXdQTBIkxu/t/bgRQIh4JZCF8/ZK2VWNAcm
86
+ BA2o/X3KLu/qSHw3TT8An4Pf73WELnlXXPxXbhqW//yMmqaZviXZf5YsBvcRKgKA
87
+ gOtjGDxQSYflispfGStZloEAoPtR28p3CwvJlk/vcEnHXG0g/Zm0tOLKLnf9LdwL
88
+ tmsTDIwZKxeWmLnwi/agJ7u2441Rj72ux5uxiZ0CAwEAAaOCAYAwggF8MA4GA1Ud
89
+ DwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwEgYDVR0T
90
+ AQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUinR/r4XN7pXNPZzQ4kYU83E1HScwHwYD
91
+ VR0jBBgwFoAU5K8rJnEaK0gnhS9SZizv8IkTcT4waAYIKwYBBQUHAQEEXDBaMCYG
92
+ CCsGAQUFBzABhhpodHRwOi8vb2NzcC5wa2kuZ29vZy9ndHNyMTAwBggrBgEFBQcw
93
+ AoYkaHR0cDovL3BraS5nb29nL3JlcG8vY2VydHMvZ3RzcjEuZGVyMDQGA1UdHwQt
94
+ MCswKaAnoCWGI2h0dHA6Ly9jcmwucGtpLmdvb2cvZ3RzcjEvZ3RzcjEuY3JsMFcG
95
+ A1UdIARQME4wOAYKKwYBBAHWeQIFAzAqMCgGCCsGAQUFBwIBFhxodHRwczovL3Br
96
+ aS5nb29nL3JlcG9zaXRvcnkvMAgGBmeBDAECATAIBgZngQwBAgIwDQYJKoZIhvcN
97
+ AQELBQADggIBAIl9rCBcDDy+mqhXlRu0rvqrpXJxtDaV/d9AEQNMwkYUuxQkq/BQ
98
+ cSLbrcRuf8/xam/IgxvYzolfh2yHuKkMo5uhYpSTld9brmYZCwKWnvy15xBpPnrL
99
+ RklfRuFBsdeYTWU0AIAaP0+fbH9JAIFTQaSSIYKCGvGjRFsqUBITTcFTNvNCCK9U
100
+ +o53UxtkOCcXCb1YyRt8OS1b887U7ZfbFAO/CVMkH8IMBHmYJvJh8VNS/UKMG2Yr
101
+ PxWhu//2m+OBmgEGcYk1KCTd4b3rGS3hSMs9WYNRtHTGnXzGsYZbr8w0xNPM1IER
102
+ lQCh9BIiAfq0g3GvjLeMcySsN1PCAJA/Ef5c7TaUEDu9Ka7ixzpiO2xj2YC/WXGs
103
+ Yye5TBeg2vZzFb8q3o/zpWwygTMD0IZRcZk0upONXbVRWPeyk+gB9lm+cZv9TSjO
104
+ z23HFtz30dZGm6fKa+l3D/2gthsjgx0QGtkJAITgRNOidSOzNIb2ILCkXhAd4FJG
105
+ AJ2xDx8hcFH1mt0G/FX0Kw4zd8NLQsLxdxP8c4CU6x+7Nz/OAipmsHMdMqUybDKw
106
+ juDEI/9bfU1lcKwrmz3O2+BtjjKAvpafkmO8l7tdufThcV4q5O8DIrGKZTqPwJNl
107
+ 1IXNDw9bg1kWRxYtnCQ6yICmJhSFm/Y3m6xv+cXDBlHz4n/FsRC6UfTd
108
+ -----END CERTIFICATE-----
109
+ -----BEGIN CERTIFICATE-----
110
+ MIIFYjCCBEqgAwIBAgIQd70NbNs2+RrqIQ/E8FjTDTANBgkqhkiG9w0BAQsFADBX
111
+ MQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTEQMA4GA1UE
112
+ CxMHUm9vdCBDQTEbMBkGA1UEAxMSR2xvYmFsU2lnbiBSb290IENBMB4XDTIwMDYx
113
+ OTAwMDA0MloXDTI4MDEyODAwMDA0MlowRzELMAkGA1UEBhMCVVMxIjAgBgNVBAoT
114
+ GUdvb2dsZSBUcnVzdCBTZXJ2aWNlcyBMTEMxFDASBgNVBAMTC0dUUyBSb290IFIx
115
+ MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAthECix7joXebO9y/lD63
116
+ ladAPKH9gvl9MgaCcfb2jH/76Nu8ai6Xl6OMS/kr9rH5zoQdsfnFl97vufKj6bwS
117
+ iV6nqlKr+CMny6SxnGPb15l+8Ape62im9MZaRw1NEDPjTrETo8gYbEvs/AmQ351k
118
+ KSUjB6G00j0uYODP0gmHu81I8E3CwnqIiru6z1kZ1q+PsAewnjHxgsHA3y6mbWwZ
119
+ DrXYfiYaRQM9sHmklCitD38m5agI/pboPGiUU+6DOogrFZYJsuB6jC511pzrp1Zk
120
+ j5ZPaK49l8KEj8C8QMALXL32h7M1bKwYUH+E4EzNktMg6TO8UpmvMrUpsyUqtEj5
121
+ cuHKZPfmghCN6J3Cioj6OGaK/GP5Afl4/Xtcd/p2h/rs37EOeZVXtL0m79YB0esW
122
+ CruOC7XFxYpVq9Os6pFLKcwZpDIlTirxZUTQAs6qzkm06p98g7BAe+dDq6dso499
123
+ iYH6TKX/1Y7DzkvgtdizjkXPdsDtQCv9Uw+wp9U7DbGKogPeMa3Md+pvez7W35Ei
124
+ Eua++tgy/BBjFFFy3l3WFpO9KWgz7zpm7AeKJt8T11dleCfeXkkUAKIAf5qoIbap
125
+ sZWwpbkNFhHax2xIPEDgfg1azVY80ZcFuctL7TlLnMQ/0lUTbiSw1nH69MG6zO0b
126
+ 9f6BQdgAmD06yK56mDcYBZUCAwEAAaOCATgwggE0MA4GA1UdDwEB/wQEAwIBhjAP
127
+ BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTkrysmcRorSCeFL1JmLO/wiRNxPjAf
128
+ BgNVHSMEGDAWgBRge2YaRQ2XyolQL30EzTSo//z9SzBgBggrBgEFBQcBAQRUMFIw
129
+ JQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwLnBraS5nb29nL2dzcjEwKQYIKwYBBQUH
130
+ MAKGHWh0dHA6Ly9wa2kuZ29vZy9nc3IxL2dzcjEuY3J0MDIGA1UdHwQrMCkwJ6Al
131
+ oCOGIWh0dHA6Ly9jcmwucGtpLmdvb2cvZ3NyMS9nc3IxLmNybDA7BgNVHSAENDAy
132
+ MAgGBmeBDAECATAIBgZngQwBAgIwDQYLKwYBBAHWeQIFAwIwDQYLKwYBBAHWeQIF
133
+ AwMwDQYJKoZIhvcNAQELBQADggEBADSkHrEoo9C0dhemMXoh6dFSPsjbdBZBiLg9
134
+ NR3t5P+T4Vxfq7vqfM/b5A3Ri1fyJm9bvhdGaJQ3b2t6yMAYN/olUazsaL+yyEn9
135
+ WprKASOshIArAoyZl+tJaox118fessmXn1hIVw41oeQa1v1vg4Fv74zPl6/AhSrw
136
+ 9U5pCZEt4Wi4wStz6dTZ/CLANx8LZh1J7QJVj2fhMtfTJr9w4z30Z209fOU0iOMy
137
+ +qduBmpvvYuR7hZL6Dupszfnw0Skfths18dG9ZKb59UhvmaSGZRVbNQpsg3BZlvi
138
+ d0lIKO2d1xozclOzgjXPYovJJIultzkMu34qQb9Sz/yilrbCgj8=
139
+ -----END CERTIFICATE-----
140
+ -----BEGIN CERTIFICATE-----
141
+ MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
142
+ A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
143
+ b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
144
+ MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
145
+ YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
146
+ aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
147
+ jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
148
+ xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
149
+ 1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
150
+ snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
151
+ U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
152
+ 9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
153
+ BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
154
+ AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
155
+ yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
156
+ 38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
157
+ AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
158
+ DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
159
+ HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
160
+ -----END CERTIFICATE-----
Binary file
@@ -1,11 +1,63 @@
1
- var assert = require("assert"),
2
- utils = require("../lib/utils");
3
-
4
- describe("saml 1.1", function() {
5
- describe("pemToCert", function() {
6
- it("should not throw when the cert is invalid", function() {
7
- var cert = utils.pemToCert('abc');
8
- assert.ok(!cert);
9
- });
10
- });
1
+ const assert = require("assert"),
2
+ utils = require("../lib/utils");
3
+ const fs = require("fs");
4
+ const {createPublicKey} = require('crypto')
5
+
6
+ describe("pemToCert", function () {
7
+ it("should not throw when the cert is invalid", function () {
8
+ var cert = utils.pemToCert('abc');
9
+ assert.ok(!cert);
10
+ });
11
11
  });
12
+
13
+ describe("fixPemFormatting", () => {
14
+ it("returns the original when the original is not in PEM format", () => {
15
+ let originalCert = fs.readFileSync(__dirname + '/test-auth0.der');
16
+ let standardizedCert = utils.fixPemFormatting(originalCert);
17
+ assert.strictEqual(originalCert.compare(standardizedCert), 0);
18
+ })
19
+
20
+ it("handles already correctly formatted PEM content", () => {
21
+ let originalCert = fs.readFileSync(__dirname + '/test-auth0_rsa.pub');
22
+ let standardizedCert = utils.fixPemFormatting(originalCert);
23
+ assert.notStrictEqual(originalCert, standardizedCert);
24
+ assert.deepStrictEqual(createPublicKey(originalCert), createPublicKey(standardizedCert));
25
+ })
26
+
27
+ it("handles PEM content with extra data before the cert", () => {
28
+ let originalCert = Buffer.from(`data that should be ignored\n${fs.readFileSync(__dirname + '/test-auth0_rsa.pub').toString()}`)
29
+ let standardizedCert = utils.fixPemFormatting(originalCert);
30
+ assert.notStrictEqual(originalCert, standardizedCert);
31
+ assert.deepStrictEqual(createPublicKey(originalCert), createPublicKey(standardizedCert));
32
+ })
33
+
34
+ it("handles PEM content with extra data after the cert", () => {
35
+ let originalCert = Buffer.from(`${fs.readFileSync(__dirname + '/test-auth0_rsa.pub').toString()}\ndata that should be ignored`)
36
+ let standardizedCert = utils.fixPemFormatting(originalCert);
37
+ assert.notStrictEqual(originalCert, standardizedCert);
38
+ assert.deepStrictEqual(createPublicKey(originalCert), createPublicKey(standardizedCert));
39
+ })
40
+
41
+ it("handles incorrectly formatted PEM content", () => {
42
+ let originalCert = Buffer.from(fs.readFileSync(__dirname + '/test-auth0_rsa.pub').toString().replaceAll(/[\r\n]/g, ''));
43
+ let standardizedCert = utils.fixPemFormatting(originalCert);
44
+ assert.notStrictEqual(originalCert, standardizedCert);
45
+ let correctCert = createPublicKey(fs.readFileSync(__dirname + '/test-auth0_rsa.pub'))
46
+ assert.deepStrictEqual(correctCert, createPublicKey(standardizedCert));
47
+ })
48
+
49
+ it("handles already correctly formatted PEM chains", () => {
50
+ let originalCert = fs.readFileSync(__dirname + '/test-auth0-chain.pem');
51
+ let standardizedCert = utils.fixPemFormatting(originalCert);
52
+ assert.notStrictEqual(originalCert, standardizedCert);
53
+ assert.deepStrictEqual(createPublicKey(originalCert), createPublicKey(standardizedCert));
54
+ })
55
+
56
+ it("handles incorrectly formatted PEM chains", () => {
57
+ let originalCert = Buffer.from(fs.readFileSync(__dirname + '/test-auth0-chain.pem').toString().replaceAll(/[\r\n]/g, ''));
58
+ let standardizedCert = utils.fixPemFormatting(originalCert);
59
+ assert.notStrictEqual(originalCert, standardizedCert);
60
+ let correctCert = createPublicKey(fs.readFileSync(__dirname + '/test-auth0-chain.pem'))
61
+ assert.deepStrictEqual(correctCert, createPublicKey(standardizedCert));
62
+ })
63
+ })