saml 3.0.1 → 4.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.
@@ -1,688 +0,0 @@
1
- var assert = require('chai').assert;
2
- var fs = require('fs');
3
- var utils = require('./utils');
4
- var moment = require('moment');
5
- var should = require('should');
6
- var xmldom = require('@xmldom/xmldom');
7
- var xmlenc = require('xml-encryption');
8
-
9
- var saml = require('../lib/saml20');
10
-
11
- describe('saml 2.0', function () {
12
- saml20TestSuite({
13
- createAssertion: 'create',
14
- assertSignature: Object.assign(function (assertion, options) {
15
- assert.isTrue(utils.isValidSignature(assertion, options.cert));
16
- }, {
17
- it: it
18
- })
19
- });
20
-
21
- saml20TestSuite({
22
- createAssertion: 'createUnsignedAssertion',
23
- assertSignature: Object.assign(function (assertion) {
24
- assert.isEmpty(utils.getXmlSignatures(assertion));
25
- }, {
26
- it: it.skip
27
- })
28
- });
29
-
30
- function saml20TestSuite(options) {
31
- var createAssertion = options.createAssertion;
32
- var assertSignature = options.assertSignature;
33
-
34
- describe('#' + createAssertion, function () {
35
- it('whole thing with default authnContextClassRef', function () {
36
- var options = {
37
- cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
38
- key: fs.readFileSync(__dirname + '/test-auth0.key'),
39
- issuer: 'urn:issuer',
40
- lifetimeInSeconds: 600,
41
- audiences: 'urn:myapp',
42
- attributes: {
43
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress': 'foo@bar.com',
44
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name': 'Foo Bar'
45
- },
46
- nameIdentifier: 'foo',
47
- nameIdentifierFormat: 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified'
48
- };
49
-
50
- var signedAssertion = saml[createAssertion](options);
51
- assertSignature(signedAssertion, options);
52
-
53
- var nameIdentifier = utils.getNameID(signedAssertion);
54
- assert.equal('foo', nameIdentifier.textContent);
55
- assert.equal('urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified', nameIdentifier.getAttribute('Format'));
56
-
57
- var attributes = utils.getAttributes(signedAssertion);
58
- assert.equal(2, attributes.length);
59
- assert.equal('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress', attributes[0].getAttribute('Name'));
60
- assert.equal('foo@bar.com', attributes[0].textContent);
61
- assert.equal('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name', attributes[1].getAttribute('Name'));
62
- assert.equal('Foo Bar', attributes[1].textContent);
63
-
64
- assert.equal('urn:issuer', utils.getSaml2Issuer(signedAssertion).textContent);
65
-
66
- var conditions = utils.getConditions(signedAssertion);
67
- assert.equal(1, conditions.length);
68
- var notBefore = conditions[0].getAttribute('NotBefore');
69
- var notOnOrAfter = conditions[0].getAttribute('NotOnOrAfter');
70
- should.ok(notBefore);
71
- should.ok(notOnOrAfter);
72
-
73
- var lifetime = Math.round((moment(notOnOrAfter).utc() - moment(notBefore).utc()) / 1000);
74
- assert.equal(600, lifetime);
75
-
76
- var authnContextClassRef = utils.getAuthnContextClassRef(signedAssertion);
77
- assert.equal('urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified', authnContextClassRef.textContent);
78
- });
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
-
170
- it('should set attributes', function () {
171
- var options = {
172
- cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
173
- key: fs.readFileSync(__dirname + '/test-auth0.key'),
174
- attributes: {
175
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress': 'foo@bar.com',
176
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name': 'Foo Bar',
177
- 'http://example.org/claims/testemptyarray': [], // should dont include empty arrays
178
- 'http://example.org/claims/testaccent': 'fóo', // should supports accents
179
- 'http://undefinedattribute/ws/com.com': undefined
180
- }
181
- };
182
-
183
- var signedAssertion = saml[createAssertion](options);
184
- assertSignature(signedAssertion, options);
185
-
186
- var attributes = utils.getAttributes(signedAssertion);
187
- assert.equal(3, attributes.length);
188
- assert.equal('saml:AttributeStatement', attributes[0].parentNode.nodeName);
189
- assert.equal('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress', attributes[0].getAttribute('Name'));
190
- assert.equal('foo@bar.com', attributes[0].textContent);
191
- assert.equal('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name', attributes[1].getAttribute('Name'));
192
- assert.equal('Foo Bar', attributes[1].textContent);
193
- assert.equal('http://example.org/claims/testaccent', attributes[2].getAttribute('Name'));
194
- assert.equal('fóo', attributes[2].textContent);
195
- });
196
-
197
- it('should set attributes with the correct attribute type', function () {
198
- var options = {
199
- cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
200
- key: fs.readFileSync(__dirname + '/test-auth0.key'),
201
- attributes: {
202
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress': 'foo@bar.com',
203
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name': 'Foo Bar',
204
- 'http://example.org/claims/testemptyarray': [], // should dont include empty arrays
205
- 'http://example.org/claims/testaccent': 'fóo', // should supports accents
206
- 'http://attributes/boolean': true,
207
- 'http://attributes/booleanNegative': false,
208
- 'http://attributes/number': 123,
209
- 'http://undefinedattribute/ws/com.com': undefined
210
- }
211
- };
212
-
213
- var signedAssertion = saml[createAssertion](options);
214
-
215
- assertSignature(signedAssertion, options);
216
-
217
- var attributes = utils.getAttributes(signedAssertion);
218
- assert.equal(6, attributes.length);
219
- assert.equal('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress', attributes[0].getAttribute('Name'));
220
- assert.equal('foo@bar.com', attributes[0].textContent);
221
- assert.equal('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name', attributes[1].getAttribute('Name'));
222
- assert.equal('Foo Bar', attributes[1].textContent);
223
- assert.equal('http://example.org/claims/testaccent', attributes[2].getAttribute('Name'));
224
- assert.equal('xs:string', attributes[2].firstChild.getAttribute('xsi:type'));
225
- assert.equal('fóo', attributes[2].textContent);
226
- assert.equal('http://attributes/boolean', attributes[3].getAttribute('Name'));
227
- assert.equal('xs:boolean', attributes[3].firstChild.getAttribute('xsi:type'));
228
- assert.equal('true', attributes[3].textContent);
229
- assert.equal('http://attributes/booleanNegative', attributes[4].getAttribute('Name'));
230
- assert.equal('xs:boolean', attributes[4].firstChild.getAttribute('xsi:type'));
231
- assert.equal('false', attributes[4].textContent);
232
- assert.equal('http://attributes/number', attributes[5].getAttribute('Name'));
233
- assert.equal('xs:double', attributes[5].firstChild.getAttribute('xsi:type'));
234
- assert.equal('123', attributes[5].textContent);
235
- });
236
-
237
- it('should set attributes with the correct attribute type and NameFormat', function () {
238
- var options = {
239
- cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
240
- key: fs.readFileSync(__dirname + '/test-auth0.key'),
241
- attributes: {
242
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress': 'foo@bar.com',
243
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name': 'Foo Bar',
244
- 'http://example.org/claims/testemptyarray': [], // should dont include empty arrays
245
- 'testaccent': 'fóo', // should supports accents
246
- 'urn:test:1:2:3': true,
247
- '123~oo': 123,
248
- 'http://undefinedattribute/ws/com.com': undefined
249
- }
250
- };
251
-
252
- var signedAssertion = saml[createAssertion](options);
253
-
254
- assertSignature(signedAssertion, options);
255
-
256
- var attributes = utils.getAttributes(signedAssertion);
257
- assert.equal(5, attributes.length);
258
- assert.equal('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress', attributes[0].getAttribute('Name'));
259
- assert.equal('urn:oasis:names:tc:SAML:2.0:attrname-format:uri', attributes[0].getAttribute('NameFormat'));
260
- assert.equal('foo@bar.com', attributes[0].textContent);
261
- assert.equal('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name', attributes[1].getAttribute('Name'));
262
- assert.equal('urn:oasis:names:tc:SAML:2.0:attrname-format:uri', attributes[1].getAttribute('NameFormat'));
263
- assert.equal('Foo Bar', attributes[1].textContent);
264
- assert.equal('testaccent', attributes[2].getAttribute('Name'));
265
- assert.equal('urn:oasis:names:tc:SAML:2.0:attrname-format:basic', attributes[2].getAttribute('NameFormat'));
266
- assert.equal('xs:string', attributes[2].firstChild.getAttribute('xsi:type'));
267
- assert.equal('fóo', attributes[2].textContent);
268
- assert.equal('urn:test:1:2:3', attributes[3].getAttribute('Name'));
269
- assert.equal('urn:oasis:names:tc:SAML:2.0:attrname-format:uri', attributes[3].getAttribute('NameFormat'));
270
- assert.equal('xs:boolean', attributes[3].firstChild.getAttribute('xsi:type'));
271
- assert.equal('true', attributes[3].textContent);
272
- assert.equal('123~oo', attributes[4].getAttribute('Name'));
273
- assert.equal('urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified', attributes[4].getAttribute('NameFormat'));
274
- assert.equal('xs:double', attributes[4].firstChild.getAttribute('xsi:type'));
275
- assert.equal('123', attributes[4].textContent);
276
- });
277
-
278
- it('should set attributes to anytpe when typedAttributes is false', function () {
279
- var options = {
280
- cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
281
- key: fs.readFileSync(__dirname + '/test-auth0.key'),
282
- typedAttributes: false,
283
- attributes: {
284
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress': 'foo@bar.com',
285
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name': 'Foo Bar',
286
- 'http://example.org/claims/testemptyarray': [], // should dont include empty arrays
287
- 'http://example.org/claims/testaccent': 'fóo', // should supports accents
288
- 'http://attributes/boolean': true,
289
- 'http://attributes/number': 123,
290
- 'http://undefinedattribute/ws/com.com': undefined
291
- }
292
- };
293
-
294
- var signedAssertion = saml[createAssertion](options);
295
-
296
- assertSignature(signedAssertion, options);
297
-
298
- var attributes = utils.getAttributes(signedAssertion);
299
- assert.equal(5, attributes.length);
300
- assert.equal('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress', attributes[0].getAttribute('Name'));
301
- assert.equal('foo@bar.com', attributes[0].textContent);
302
- assert.equal('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name', attributes[1].getAttribute('Name'));
303
- assert.equal('Foo Bar', attributes[1].textContent);
304
- assert.equal('http://example.org/claims/testaccent', attributes[2].getAttribute('Name'));
305
- assert.equal('xs:anyType', attributes[2].firstChild.getAttribute('xsi:type'));
306
- assert.equal('fóo', attributes[2].textContent);
307
- assert.equal('http://attributes/boolean', attributes[3].getAttribute('Name'));
308
- assert.equal('xs:anyType', attributes[3].firstChild.getAttribute('xsi:type'));
309
- assert.equal('true', attributes[3].textContent);
310
- assert.equal('http://attributes/number', attributes[4].getAttribute('Name'));
311
- assert.equal('xs:anyType', attributes[4].firstChild.getAttribute('xsi:type'));
312
- assert.equal('123', attributes[4].textContent);
313
- });
314
-
315
- it('should not set NameFormat in attributes when includeAttributeNameFormat is false', function () {
316
- var options = {
317
- cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
318
- key: fs.readFileSync(__dirname + '/test-auth0.key'),
319
- typedAttributes: false,
320
- includeAttributeNameFormat: false,
321
- attributes: {
322
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress': 'foo@bar.com',
323
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name': 'Foo Bar',
324
- 'http://example.org/claims/testemptyarray': [], // should dont include empty arrays
325
- 'testaccent': 'fóo', // should supports accents
326
- 'urn:test:1:2:3': true,
327
- '123~oo': 123,
328
- 'http://undefinedattribute/ws/com.com': undefined
329
- }
330
- };
331
-
332
- var signedAssertion = saml[createAssertion](options);
333
-
334
- assertSignature(signedAssertion, options);
335
-
336
- var attributes = utils.getAttributes(signedAssertion);
337
- assert.equal(5, attributes.length);
338
- assert.equal('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress', attributes[0].getAttribute('Name'));
339
- assert.equal('', attributes[0].getAttribute('NameFormat'));
340
- assert.equal('foo@bar.com', attributes[0].textContent);
341
- assert.equal('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name', attributes[1].getAttribute('Name'));
342
- assert.equal('', attributes[1].getAttribute('NameFormat'));
343
- assert.equal('Foo Bar', attributes[1].textContent);
344
- assert.equal('testaccent', attributes[2].getAttribute('Name'));
345
- assert.equal('', attributes[2].getAttribute('NameFormat'));
346
- assert.equal('fóo', attributes[2].textContent);
347
- assert.equal('urn:test:1:2:3', attributes[3].getAttribute('Name'));
348
- assert.equal('', attributes[3].getAttribute('NameFormat'));
349
- assert.equal('true', attributes[3].textContent);
350
- assert.equal('123~oo', attributes[4].getAttribute('Name'));
351
- assert.equal('', attributes[4].getAttribute('NameFormat'));
352
- assert.equal('123', attributes[4].textContent);
353
- });
354
-
355
- it('should ignore undefined attributes in array', function () {
356
- var options = {
357
- cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
358
- key: fs.readFileSync(__dirname + '/test-auth0.key'),
359
- attributes: {
360
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress': 'foo@bar.com',
361
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name': 'Foo Bar',
362
- 'http://example.org/claims/testemptyarray': [], // should dont include empty arrays
363
- 'arrayAttribute': [ 'foo', undefined, 'bar'],
364
- 'urn:test:1:2:3': true,
365
- '123~oo': 123,
366
- 'http://undefinedattribute/ws/com.com': undefined
367
- }
368
- };
369
-
370
- var signedAssertion = saml[createAssertion](options);
371
-
372
- assertSignature(signedAssertion, options);
373
-
374
- var attributes = utils.getAttributes(signedAssertion);
375
- assert.equal(5, attributes.length);
376
- assert.equal('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress', attributes[0].getAttribute('Name'));
377
- assert.equal('urn:oasis:names:tc:SAML:2.0:attrname-format:uri', attributes[0].getAttribute('NameFormat'));
378
- assert.equal('foo@bar.com', attributes[0].textContent);
379
- assert.equal('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name', attributes[1].getAttribute('Name'));
380
- assert.equal('urn:oasis:names:tc:SAML:2.0:attrname-format:uri', attributes[1].getAttribute('NameFormat'));
381
- assert.equal('Foo Bar', attributes[1].textContent);
382
- assert.equal('arrayAttribute', attributes[2].getAttribute('Name'));
383
- assert.equal('urn:oasis:names:tc:SAML:2.0:attrname-format:basic', attributes[2].getAttribute('NameFormat'));
384
- assert.equal('xs:string', attributes[2].firstChild.getAttribute('xsi:type'));
385
- assert.equal(2, attributes[2].childNodes.length);
386
- assert.equal('foo', attributes[2].childNodes[0].textContent);
387
- // undefined should not be here
388
- assert.equal('bar', attributes[2].childNodes[1].textContent);
389
- assert.equal('urn:test:1:2:3', attributes[3].getAttribute('Name'));
390
- assert.equal('urn:oasis:names:tc:SAML:2.0:attrname-format:uri', attributes[3].getAttribute('NameFormat'));
391
- assert.equal('xs:boolean', attributes[3].firstChild.getAttribute('xsi:type'));
392
- assert.equal('true', attributes[3].textContent);
393
- assert.equal('123~oo', attributes[4].getAttribute('Name'));
394
- assert.equal('urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified', attributes[4].getAttribute('NameFormat'));
395
- assert.equal('xs:double', attributes[4].firstChild.getAttribute('xsi:type'));
396
- assert.equal('123', attributes[4].textContent);
397
- });
398
-
399
- it('whole thing with specific authnContextClassRef', function () {
400
- var options = {
401
- cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
402
- key: fs.readFileSync(__dirname + '/test-auth0.key'),
403
- issuer: 'urn:issuer',
404
- lifetimeInSeconds: 600,
405
- audiences: 'urn:myapp',
406
- attributes: {
407
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress': 'foo@bar.com',
408
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name': 'Foo Bar'
409
- },
410
- nameIdentifier: 'foo',
411
- nameIdentifierFormat: 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified',
412
- authnContextClassRef: 'specific'
413
- };
414
-
415
- var signedAssertion = saml[createAssertion](options);
416
- assertSignature(signedAssertion, options);
417
-
418
- var nameIdentifier = utils.getNameID(signedAssertion);
419
- assert.equal('foo', nameIdentifier.textContent);
420
- assert.equal('urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified', nameIdentifier.getAttribute('Format'));
421
-
422
- var attributes = utils.getAttributes(signedAssertion);
423
- assert.equal(2, attributes.length);
424
- assert.equal('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress', attributes[0].getAttribute('Name'));
425
- assert.equal('foo@bar.com', attributes[0].textContent);
426
- assert.equal('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name', attributes[1].getAttribute('Name'));
427
- assert.equal('Foo Bar', attributes[1].textContent);
428
-
429
- assert.equal('urn:issuer', utils.getSaml2Issuer(signedAssertion).textContent);
430
-
431
- var conditions = utils.getConditions(signedAssertion);
432
- assert.equal(1, conditions.length);
433
- var notBefore = conditions[0].getAttribute('NotBefore');
434
- var notOnOrAfter = conditions[0].getAttribute('NotOnOrAfter');
435
- should.ok(notBefore);
436
- should.ok(notOnOrAfter);
437
-
438
- var lifetime = Math.round((moment(notOnOrAfter).utc() - moment(notBefore).utc()) / 1000);
439
- assert.equal(600, lifetime);
440
-
441
- var authnContextClassRef = utils.getAuthnContextClassRef(signedAssertion);
442
- assert.equal('specific', authnContextClassRef.textContent);
443
- });
444
-
445
- assertSignature.it('should place signature where specified', function () {
446
- var options = {
447
- cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
448
- key: fs.readFileSync(__dirname + '/test-auth0.key'),
449
- xpathToNodeBeforeSignature: "//*[local-name(.)='Conditions']",
450
- attributes: {
451
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress': 'foo@bar.com',
452
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name': 'Foo Bar',
453
- 'http://example.org/claims/testemptyarray': [], // should dont include empty arrays
454
- 'http://example.org/claims/testaccent': 'fóo', // should supports accents
455
- 'http://undefinedattribute/ws/com.com': undefined
456
- }
457
- };
458
-
459
- var signedAssertion = saml[createAssertion](options);
460
-
461
- assertSignature(signedAssertion, options);
462
-
463
- var doc = new xmldom.DOMParser().parseFromString(signedAssertion);
464
- var signature = doc.documentElement.getElementsByTagName('Signature');
465
-
466
- assert.equal('saml:Conditions', signature[0].previousSibling.nodeName);
467
- });
468
-
469
- assertSignature.it('should place signature with prefix where specified', function () {
470
- var options = {
471
- cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
472
- key: fs.readFileSync(__dirname + '/test-auth0.key'),
473
- xpathToNodeBeforeSignature: "//*[local-name(.)='Conditions']",
474
- signatureNamespacePrefix: 'anyprefix',
475
- attributes: {
476
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress': 'foo@bar.com',
477
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name': 'Foo Bar',
478
- 'http://example.org/claims/testemptyarray': [], // should dont include empty arrays
479
- 'http://example.org/claims/testaccent': 'fóo', // should supports accents
480
- 'http://undefinedattribute/ws/com.com': undefined
481
- }
482
- };
483
-
484
- var signedAssertion = saml[createAssertion](options);
485
-
486
- assertSignature(signedAssertion, options);
487
-
488
- var doc = new xmldom.DOMParser().parseFromString(signedAssertion);
489
- var signature = doc.documentElement.getElementsByTagName(options.signatureNamespacePrefix + ':Signature');
490
- assert.equal('saml:Conditions', signature[0].previousSibling.nodeName);
491
- });
492
-
493
- assertSignature.it('should place signature with prefix where specified (backwards compat)', function () {
494
- var options = {
495
- cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
496
- key: fs.readFileSync(__dirname + '/test-auth0.key'),
497
- xpathToNodeBeforeSignature: "//*[local-name(.)='Conditions']",
498
- prefix: 'anyprefix',
499
- attributes: {
500
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress': 'foo@bar.com',
501
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name': 'Foo Bar',
502
- 'http://example.org/claims/testemptyarray': [], // should dont include empty arrays
503
- 'http://example.org/claims/testaccent': 'fóo', // should supports accents
504
- 'http://undefinedattribute/ws/com.com': undefined
505
- }
506
- };
507
-
508
- var signedAssertion = saml[createAssertion](options);
509
-
510
- assertSignature(signedAssertion, options);
511
-
512
- var doc = new xmldom.DOMParser().parseFromString(signedAssertion);
513
- var signature = doc.documentElement.getElementsByTagName(options.prefix + ':Signature');
514
- assert.equal('saml:Conditions', signature[0].previousSibling.nodeName);
515
- });
516
-
517
- assertSignature.it('should ignore prefix if not a string', function () {
518
- var options = {
519
- cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
520
- key: fs.readFileSync(__dirname + '/test-auth0.key'),
521
- xpathToNodeBeforeSignature: "//*[local-name(.)='Conditions']",
522
- signatureNamespacePrefix: 123,
523
- attributes: {
524
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress': 'foo@bar.com',
525
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name': 'Foo Bar',
526
- 'http://example.org/claims/testemptyarray': [], // should dont include empty arrays
527
- 'http://example.org/claims/testaccent': 'fóo', // should supports accents
528
- 'http://undefinedattribute/ws/com.com': undefined
529
- }
530
- };
531
-
532
- var signedAssertion = saml[createAssertion](options);
533
-
534
- assertSignature(signedAssertion, options);
535
-
536
- var doc = new xmldom.DOMParser().parseFromString(signedAssertion);
537
- var signature = doc.documentElement.getElementsByTagName('Signature');
538
- assert.equal('saml:Conditions', signature[0].previousSibling.nodeName);
539
- });
540
-
541
-
542
- it('should not include AudienceRestriction when there are no audiences', function () {
543
- var options = {
544
- cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
545
- key: fs.readFileSync(__dirname + '/test-auth0.key'),
546
- xpathToNodeBeforeSignature: "//*[local-name(.)='Conditions']",
547
- signatureNamespacePrefix: 123,
548
- attributes: {
549
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress': 'foo@bar.com',
550
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name': 'Foo Bar',
551
- 'http://example.org/claims/testemptyarray': [], // should dont include empty arrays
552
- 'http://example.org/claims/testaccent': 'fóo', // should supports accents
553
- 'http://undefinedattribute/ws/com.com': undefined
554
- }
555
- };
556
-
557
- var signedAssertion = saml[createAssertion](options);
558
-
559
- assertSignature(signedAssertion, options);
560
-
561
- var doc = new xmldom.DOMParser().parseFromString(signedAssertion);
562
- var audienceRestriction = doc.documentElement.getElementsByTagName('saml:AudienceRestriction');
563
- assert.equal(audienceRestriction.length, 0);
564
- });
565
-
566
- it('should not include AttributeStatement when there are no attributes', function () {
567
- var options = {
568
- cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
569
- key: fs.readFileSync(__dirname + '/test-auth0.key'),
570
- xpathToNodeBeforeSignature: "//*[local-name(.)='Conditions']",
571
- signatureNamespacePrefix: 123
572
- };
573
-
574
- var signedAssertion = saml[createAssertion](options);
575
-
576
- assertSignature(signedAssertion, options);
577
-
578
- var doc = new xmldom.DOMParser().parseFromString(signedAssertion);
579
- var attributeStatement = doc.documentElement.getElementsByTagName('saml:AttributeStatement');
580
- assert.equal(attributeStatement.length, 0);
581
- });
582
-
583
- describe('encryption', function () {
584
-
585
- it('should create a saml 2.0 signed and encrypted assertion', function (done) {
586
- var options = {
587
- cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
588
- key: fs.readFileSync(__dirname + '/test-auth0.key'),
589
- encryptionPublicKey: fs.readFileSync(__dirname + '/test-auth0_rsa.pub'),
590
- encryptionCert: fs.readFileSync(__dirname + '/test-auth0.pem')
591
- };
592
-
593
- saml[createAssertion](options, function (err, encrypted) {
594
- if (err) return done(err);
595
-
596
- var encryptedData = utils.getEncryptedData(encrypted);
597
-
598
- xmlenc.decrypt(encryptedData.toString(), { key: fs.readFileSync(__dirname + '/test-auth0.key') }, function (err, decrypted) {
599
- if (err) return done(err);
600
- assertSignature(decrypted, options);
601
- done();
602
- });
603
- });
604
- });
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
-
648
- it('should set attributes', function (done) {
649
- var options = {
650
- cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
651
- key: fs.readFileSync(__dirname + '/test-auth0.key'),
652
- encryptionPublicKey: fs.readFileSync(__dirname + '/test-auth0_rsa.pub'),
653
- encryptionCert: fs.readFileSync(__dirname + '/test-auth0.pem'),
654
- attributes: {
655
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress': 'foo@bar.com',
656
- 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name': 'Foo Bar',
657
- 'http://example.org/claims/testaccent': 'fóo', // should supports accents
658
- 'http://undefinedattribute/ws/com.com': undefined
659
- }
660
- };
661
-
662
- saml[createAssertion](options, function (err, encrypted) {
663
- if (err) return done(err);
664
-
665
- var encryptedData = utils.getEncryptedData(encrypted);
666
-
667
- xmlenc.decrypt(encryptedData.toString(), { key: fs.readFileSync(__dirname + '/test-auth0.key') }, function (err, decrypted) {
668
- if (err) return done(err);
669
-
670
- assertSignature(decrypted, options);
671
-
672
- var attributes = utils.getAttributes(decrypted);
673
- assert.equal(3, attributes.length);
674
- assert.equal('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress', attributes[0].getAttribute('Name'));
675
- assert.equal('foo@bar.com', attributes[0].textContent);
676
- assert.equal('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name', attributes[1].getAttribute('Name'));
677
- assert.equal('Foo Bar', attributes[1].textContent);
678
- assert.equal('http://example.org/claims/testaccent', attributes[2].getAttribute('Name'));
679
- assert.equal('fóo', attributes[2].textContent);
680
-
681
- done();
682
- });
683
- });
684
- });
685
- });
686
- });
687
- }
688
- });