samlify 2.8.1 → 2.8.4

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.
package/src/libsaml.ts CHANGED
@@ -7,9 +7,9 @@
7
7
  import { DOMParser } from '@xmldom/xmldom';
8
8
  import utility, { flattenDeep, isString } from './utility';
9
9
  import { algorithms, wording, namespace } from './urn';
10
- import { select, SelectedValue } from 'xpath';
10
+ import { select } from 'xpath';
11
11
  import { MetadataInterface } from './metadata';
12
- import * as nrsa from 'node-rsa';
12
+ import nrsa, { SigningSchemeHash } from 'node-rsa';
13
13
  import { SignedXml, FileKeyInfo } from 'xml-crypto';
14
14
  import * as xmlenc from '@authenio/xml-encryption';
15
15
  import { extract } from './extractor';
@@ -60,7 +60,7 @@ export interface LoginResponseAttribute {
60
60
 
61
61
  export interface LoginResponseAdditionalTemplates {
62
62
  attributeStatementTemplate?: AttributeStatementTemplate;
63
- attributeTemplate?:AttributeTemplate;
63
+ attributeTemplate?: AttributeTemplate;
64
64
  }
65
65
 
66
66
  export interface BaseSamlTemplate {
@@ -91,7 +91,7 @@ export interface LibSamlInterface {
91
91
  getQueryParamByType: (type: string) => string;
92
92
  createXPath: (local, isExtractAll?: boolean) => string;
93
93
  replaceTagsByValue: (rawXML: string, tagValues: any) => string;
94
- attributeStatementBuilder: (attributes: LoginResponseAttribute[], attributeTemplate : AttributeTemplate, attributeStatementTemplate : AttributeStatementTemplate) => string;
94
+ attributeStatementBuilder: (attributes: LoginResponseAttribute[], attributeTemplate: AttributeTemplate, attributeStatementTemplate: AttributeStatementTemplate) => string;
95
95
  constructSAMLSignature: (opts: SignatureConstructor) => string;
96
96
  verifySignature: (xml: string, opts) => [boolean, any];
97
97
  createKeySection: (use: KeyUse, cert: string | Buffer) => {};
@@ -132,9 +132,9 @@ const libSaml = () => {
132
132
  *
133
133
  */
134
134
  const nrsaAliasMapping = {
135
- 'http://www.w3.org/2000/09/xmldsig#rsa-sha1': 'sha1',
136
- 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256': 'sha256',
137
- 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512': 'sha512',
135
+ 'http://www.w3.org/2000/09/xmldsig#rsa-sha1': 'pkcs1-sha1',
136
+ 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256': 'pkcs1-sha256',
137
+ 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512': 'pkcs1-sha512',
138
138
  };
139
139
  /**
140
140
  * @desc Default login request template
@@ -164,7 +164,7 @@ const libSaml = () => {
164
164
  * @type {AttributeTemplate}
165
165
  */
166
166
  const defaultAttributeTemplate = {
167
- context: '<saml:Attribute Name="{Name}" NameFormat="{NameFormat}"><AttributeValue xmlns:xs="{ValueXmlnsXs}" xmlns:xsi="{ValueXmlnsXsi}" xsi:type="{ValueXsiType}">{Value}</AttributeValue></Attribute>',
167
+ context: '<saml:Attribute Name="{Name}" NameFormat="{NameFormat}"><saml:AttributeValue xmlns:xs="{ValueXmlnsXs}" xmlns:xsi="{ValueXmlnsXsi}" xsi:type="{ValueXsiType}">{Value}</saml:AttributeValue></saml:Attribute>',
168
168
  };
169
169
 
170
170
  /**
@@ -174,7 +174,7 @@ const libSaml = () => {
174
174
  const defaultLoginResponseTemplate = {
175
175
  context: '<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="{ID}" Version="2.0" IssueInstant="{IssueInstant}" Destination="{Destination}" InResponseTo="{InResponseTo}"><saml:Issuer>{Issuer}</saml:Issuer><samlp:Status><samlp:StatusCode Value="{StatusCode}"/></samlp:Status><saml:Assertion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="{AssertionID}" Version="2.0" IssueInstant="{IssueInstant}"><saml:Issuer>{Issuer}</saml:Issuer><saml:Subject><saml:NameID Format="{NameIDFormat}">{NameID}</saml:NameID><saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationData NotOnOrAfter="{SubjectConfirmationDataNotOnOrAfter}" Recipient="{SubjectRecipient}" InResponseTo="{InResponseTo}"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore="{ConditionsNotBefore}" NotOnOrAfter="{ConditionsNotOnOrAfter}"><saml:AudienceRestriction><saml:Audience>{Audience}</saml:Audience></saml:AudienceRestriction></saml:Conditions>{AuthnStatement}{AttributeStatement}</saml:Assertion></samlp:Response>',
176
176
  attributes: [],
177
- additionalTemplates:{
177
+ additionalTemplates: {
178
178
  "attributeStatementTemplate": defaultAttributeStatementTemplate,
179
179
  "attributeTemplate": defaultAttributeTemplate
180
180
  }
@@ -192,14 +192,14 @@ const libSaml = () => {
192
192
  * @param {string} sigAlg signature algorithm
193
193
  * @return {string/null} signing algorithm short-hand for the module node-rsa
194
194
  */
195
- function getSigningScheme(sigAlg?: string): string | null {
195
+ function getSigningScheme(sigAlg?: string): SigningSchemeHash {
196
196
  if (sigAlg) {
197
197
  const algAlias = nrsaAliasMapping[sigAlg];
198
198
  if (!(algAlias === undefined)) {
199
199
  return algAlias;
200
200
  }
201
201
  }
202
- return nrsaAliasMapping[signatureAlgorithms.RSA_SHA1]; // default value
202
+ return nrsaAliasMapping[signatureAlgorithms.RSA_SHA1];
203
203
  }
204
204
  /**
205
205
  * @private
@@ -270,27 +270,25 @@ const libSaml = () => {
270
270
  * @param {AttributeStatementTemplate} attributeStatementTemplate the attributStatement tag template to be used
271
271
  * @return {string}
272
272
  */
273
- attributeStatementBuilder(attributes: LoginResponseAttribute[], attributeTemplate : AttributeTemplate, attributeStatementTemplate : AttributeStatementTemplate): string {
274
- if (!attributeStatementTemplate){
275
- attributeStatementTemplate = defaultAttributeStatementTemplate;
276
- }
277
- if (!attributeTemplate){
278
- attributeTemplate = defaultAttributeTemplate;
279
- }
280
- const attr = attributes.map(({ name, nameFormat, valueTag, valueXsiType, valueXmlnsXs, valueXmlnsXsi }) => {
281
- const defaultValueXmlnsXs = 'http://www.w3.org/2001/XMLSchema';
282
- const defaultValueXmlnsXsi = 'http://www.w3.org/2001/XMLSchema-instance';
283
- let attributeLine = attributeTemplate.context;
284
- attributeLine = attributeLine.replace('{Name}',name);
285
- attributeLine = attributeLine.replace('{NameFormat}',nameFormat);
286
- attributeLine = attributeLine.replace('{ValueXmlnsXs}',valueXmlnsXs ? valueXmlnsXs : defaultValueXmlnsXs);
287
- attributeLine = attributeLine.replace('{ValueXmlnsXsi}',valueXmlnsXsi ? valueXmlnsXsi : defaultValueXmlnsXsi);
288
- attributeLine = attributeLine.replace('{ValueXsiType}',valueXsiType);
289
- attributeLine = attributeLine.replace('{Value}',`{${tagging('attr', valueTag)}}`);
290
- return attributeLine;
291
- }).join('');
292
- return attributeStatementTemplate.context.replace('{Attributes}',attr);
293
- },
273
+ attributeStatementBuilder(
274
+ attributes: LoginResponseAttribute[],
275
+ attributeTemplate: AttributeTemplate = defaultAttributeTemplate,
276
+ attributeStatementTemplate: AttributeStatementTemplate = defaultAttributeStatementTemplate
277
+ ): string {
278
+ const attr = attributes.map(({ name, nameFormat, valueTag, valueXsiType, valueXmlnsXs, valueXmlnsXsi }) => {
279
+ const defaultValueXmlnsXs = 'http://www.w3.org/2001/XMLSchema';
280
+ const defaultValueXmlnsXsi = 'http://www.w3.org/2001/XMLSchema-instance';
281
+ let attributeLine = attributeTemplate.context;
282
+ attributeLine = attributeLine.replace('{Name}', name);
283
+ attributeLine = attributeLine.replace('{NameFormat}', nameFormat);
284
+ attributeLine = attributeLine.replace('{ValueXmlnsXs}', valueXmlnsXs ? valueXmlnsXs : defaultValueXmlnsXs);
285
+ attributeLine = attributeLine.replace('{ValueXmlnsXsi}', valueXmlnsXsi ? valueXmlnsXsi : defaultValueXmlnsXsi);
286
+ attributeLine = attributeLine.replace('{ValueXsiType}', valueXsiType);
287
+ attributeLine = attributeLine.replace('{Value}', `{${tagging('attr', valueTag)}}`);
288
+ return attributeLine;
289
+ }).join('');
290
+ return attributeStatementTemplate.context.replace('{Attributes}', attr);
291
+ },
294
292
 
295
293
  /**
296
294
  * @desc Construct the XML signature for POST binding
@@ -537,12 +535,22 @@ const libSaml = () => {
537
535
  * @param {string} signingAlgorithm signing algorithm
538
536
  * @return {string} message signature
539
537
  */
540
- constructMessageSignature(octetString: string, key: string, passphrase?: string, isBase64?: boolean, signingAlgorithm?: string) {
538
+ constructMessageSignature(
539
+ octetString: string,
540
+ key: string,
541
+ passphrase?: string,
542
+ isBase64?: boolean,
543
+ signingAlgorithm?: string
544
+ ) {
541
545
  // Default returning base64 encoded signature
542
546
  // Embed with node-rsa module
543
- const decryptedKey = new nrsa(utility.readPrivateKey(key, passphrase), {
544
- signingScheme: getSigningScheme(signingAlgorithm),
545
- });
547
+ const decryptedKey = new nrsa(
548
+ utility.readPrivateKey(key, passphrase),
549
+ 'private',
550
+ {
551
+ signingScheme: getSigningScheme(signingAlgorithm),
552
+ }
553
+ );
546
554
  const signature = decryptedKey.sign(octetString);
547
555
  // Use private key to sign data
548
556
  return isBase64 !== false ? signature.toString('base64') : signature;
@@ -555,11 +563,16 @@ const libSaml = () => {
555
563
  * @param {string} verifyAlgorithm algorithm used to verify
556
564
  * @return {boolean} verification result
557
565
  */
558
- verifyMessageSignature(metadata, octetString: string, signature: string | Buffer, verifyAlgorithm?: string) {
566
+ verifyMessageSignature(
567
+ metadata,
568
+ octetString: string,
569
+ signature: string | Buffer,
570
+ verifyAlgorithm?: string
571
+ ) {
559
572
  const signCert = metadata.getX509Certificate(certUse.signing);
560
573
  const signingScheme = getSigningScheme(verifyAlgorithm);
561
- const key = new nrsa(utility.getPublicKeyPemFromCertificate(signCert), { signingScheme });
562
- return key.verify(new Buffer(octetString), signature);
574
+ const key = new nrsa(utility.getPublicKeyPemFromCertificate(signCert), 'public', { signingScheme });
575
+ return key.verify(Buffer.from(octetString), Buffer.from(signature));
563
576
  },
564
577
  /**
565
578
  * @desc Get the public key in string format
@@ -600,12 +613,16 @@ const libSaml = () => {
600
613
  if (assertions.length !== 1) {
601
614
  throw new Error('ERR_MULTIPLE_ASSERTION');
602
615
  }
616
+
603
617
  // Perform encryption depends on the setting, default is false
604
618
  if (sourceEntitySetting.isAssertionEncrypted) {
619
+
620
+ const publicKeyPem = utility.getPublicKeyPemFromCertificate(targetEntityMetadata.getX509Certificate(certUse.encrypt));
621
+
605
622
  xmlenc.encrypt(assertions[0].toString(), {
606
623
  // use xml-encryption module
607
- rsa_pub: Buffer.from(utility.getPublicKeyPemFromCertificate(targetEntityMetadata.getX509Certificate(certUse.encrypt)).replace(/\r?\n|\r/g, '')), // public key from certificate
608
- pem: Buffer.from('-----BEGIN CERTIFICATE-----' + targetEntityMetadata.getX509Certificate(certUse.encrypt) + '-----END CERTIFICATE-----'),
624
+ rsa_pub: Buffer.from(publicKeyPem), // public key from certificate
625
+ pem: Buffer.from(`-----BEGIN CERTIFICATE-----${targetEntityMetadata.getX509Certificate(certUse.encrypt)}-----END CERTIFICATE-----`),
609
626
  encryptionAlgorithm: sourceEntitySetting.dataEncryptionAlgorithm,
610
627
  keyEncryptionAlgorithm: sourceEntitySetting.keyEncryptionAlgorithm,
611
628
  }, (err, res) => {
@@ -8,7 +8,7 @@ import { MetadataIdpOptions, MetadataIdpConstructor } from './types';
8
8
  import { namespace } from './urn';
9
9
  import libsaml from './libsaml';
10
10
  import { isNonEmptyArray, isString } from './utility';
11
- import * as xml from 'xml';
11
+ import xml from 'xml';
12
12
 
13
13
  export interface IdpMetadataInterface extends MetadataInterface {
14
14
 
@@ -8,7 +8,7 @@ import { MetadataSpConstructor, MetadataSpOptions } from './types';
8
8
  import { namespace, elementsOrder as order } from './urn';
9
9
  import libsaml from './libsaml';
10
10
  import { isNonEmptyArray, isString } from './utility';
11
- import * as xml from 'xml';
11
+ import xml from 'xml';
12
12
 
13
13
  export interface SpMetadataInterface extends MetadataInterface {
14
14
 
@@ -129,7 +129,7 @@ declare const _default: {
129
129
  * @param {AttributeStatementTemplate} attributeStatementTemplate the attributStatement tag template to be used
130
130
  * @return {string}
131
131
  */
132
- attributeStatementBuilder(attributes: LoginResponseAttribute[], attributeTemplate: AttributeTemplate, attributeStatementTemplate: AttributeStatementTemplate): string;
132
+ attributeStatementBuilder(attributes: LoginResponseAttribute[], attributeTemplate?: AttributeTemplate, attributeStatementTemplate?: AttributeStatementTemplate): string;
133
133
  /**
134
134
  * @desc Construct the XML signature for POST binding
135
135
  * @param {string} rawSamlMessage request/response xml string
@@ -165,7 +165,7 @@ declare const _default: {
165
165
  * @param {string} signingAlgorithm signing algorithm
166
166
  * @return {string} message signature
167
167
  */
168
- constructMessageSignature(octetString: string, key: string, passphrase?: string | undefined, isBase64?: boolean | undefined, signingAlgorithm?: string | undefined): any;
168
+ constructMessageSignature(octetString: string, key: string, passphrase?: string | undefined, isBase64?: boolean | undefined, signingAlgorithm?: string | undefined): string | Buffer;
169
169
  /**
170
170
  * @desc Verifies message signature
171
171
  * @param {Metadata} metadata metadata object of identity provider or service provider
@@ -174,7 +174,7 @@ declare const _default: {
174
174
  * @param {string} verifyAlgorithm algorithm used to verify
175
175
  * @return {boolean} verification result
176
176
  */
177
- verifyMessageSignature(metadata: any, octetString: string, signature: string | Buffer, verifyAlgorithm?: string | undefined): any;
177
+ verifyMessageSignature(metadata: any, octetString: string, signature: string | Buffer, verifyAlgorithm?: string | undefined): boolean;
178
178
  /**
179
179
  * @desc Get the public key in string format
180
180
  * @param {string} x509Certificate certificate