passport-saml-metadata
Advanced tools
Comparing version 1.4.0 to 1.5.0
{ | ||
"name": "passport-saml-metadata", | ||
"version": "1.4.0", | ||
"version": "1.5.0", | ||
"description": "SAML2 metadata loader", | ||
@@ -9,2 +9,7 @@ "author": { | ||
}, | ||
"contributors": [ | ||
{ | ||
"name": "Ian Cervantez" | ||
} | ||
], | ||
"license": "MIT", | ||
@@ -34,6 +39,6 @@ "keywords": [ | ||
"dependencies": { | ||
"camelcase": "^5.0.0", | ||
"core-js": "^2.5.5", | ||
"debug": "^3.1.0", | ||
"passport-saml": "^0.33.0", | ||
"lodash": "^4.17.10", | ||
"passport-saml": "^0.35.0", | ||
"superagent": "^3.8.2", | ||
@@ -44,5 +49,5 @@ "xmldom": "^0.1.27", | ||
"devDependencies": { | ||
"eslint": "^4.19.1", | ||
"eslint": "^5.4.0", | ||
"mocha": "^5.1.1" | ||
} | ||
} |
# passport-saml-metadata | ||
[![Build Status](https://travis-ci.org/compwright/passport-saml-metadata.svg?branch=master)](https://travis-ci.org/compwright/passport-saml-metadata) | ||
Utilities for reading configuration from SAML 2.0 Metadata XML files, such as those generated by Active Directory Federation Services (ADFS). | ||
@@ -92,4 +94,8 @@ | ||
### new MetadataReader(metadataXml, options = { throwExceptions: false }) | ||
### new MetadataReader(metadataXml, options) | ||
#### Options parameter details: | ||
* `authnRequestBinding`: if set to `HTTP-POST`, will attempt to load identityProviderUrl/logoutUrl via HTTP-POST binding in metadata, otherwise defaults to `HTTP-Redirect` | ||
* `throwExceptions`: if set to `true`, will throw upon exception | ||
Parses metadata XML and extracts the following properties: | ||
@@ -96,0 +102,0 @@ |
const assert = require('assert'); | ||
const { DOMParser } = require('xmldom'); | ||
const xpath = require('xpath'); | ||
const camel = require('camelcase'); | ||
const { | ||
camelCase, | ||
merge, | ||
find, | ||
sortBy | ||
} = require('lodash'); | ||
const debug = require('debug')('passport-saml-metadata'); | ||
const defaultOptions = { | ||
authnRequestBinding: 'HTTP-Redirect', | ||
throwExceptions: false | ||
}; | ||
class MetadataReader { | ||
constructor(metadata, options = {}) { | ||
constructor(metadata, options = defaultOptions) { | ||
assert.equal(typeof metadata, 'string', 'metadata must be an XML string'); | ||
const doc = new DOMParser().parseFromString(metadata); | ||
this.options = options; | ||
this.options = merge({}, defaultOptions, options); | ||
@@ -34,3 +44,7 @@ const select = xpath.useNamespaces({ | ||
} catch (e) { | ||
if (this.options.throwExceptions) throw e; | ||
if (this.options.throwExceptions) { | ||
throw e; | ||
} else { | ||
return undefined; | ||
} | ||
} | ||
@@ -41,5 +55,28 @@ } | ||
try { | ||
return this.query('//md:IDPSSODescriptor/md:SingleSignOnService[@Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"]/@Location')[0].value; | ||
// Get all of the SingleSignOnService elements in the XML, sort them by the index (if provided) | ||
const singleSignOnServiceElements = sortBy(this.query('//md:IDPSSODescriptor/md:SingleSignOnService'), (singleSignOnServiceElement) => { | ||
const indexAttribute = find(singleSignOnServiceElement.attributes, { name: 'index' }); | ||
if (indexAttribute) { | ||
return indexAttribute.value; | ||
} | ||
return 0; | ||
}); | ||
// Find the specified authentication binding, if not available default to the first binding in the list | ||
const singleSignOnServiceElement = find(singleSignOnServiceElements, (element) => { | ||
return find(element.attributes, { | ||
value: `urn:oasis:names:tc:SAML:2.0:bindings:${this.options.authnRequestBinding}` | ||
}); | ||
}) || singleSignOnServiceElements[0]; | ||
// Return the location | ||
return find(singleSignOnServiceElement.attributes, { name: 'Location' }).value; | ||
} catch (e) { | ||
if (this.options.throwExceptions) throw e; | ||
if (this.options.throwExceptions) { | ||
throw e; | ||
} else { | ||
return undefined; | ||
} | ||
} | ||
@@ -50,5 +87,28 @@ } | ||
try { | ||
return this.query('//md:IDPSSODescriptor/md:SingleLogoutService[@Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"]/@Location')[0].value; | ||
// Get all of the SingleLogoutService elements in the XML, sort them by the index (if provided) | ||
const singleLogoutServiceElements = sortBy(this.query('//md:IDPSSODescriptor/md:SingleLogoutService'), (singleLogoutServiceElement) => { | ||
const indexAttribute = find(singleLogoutServiceElement.attributes, { name: 'index' }); | ||
if (indexAttribute) { | ||
return indexAttribute.value; | ||
} | ||
return 0; | ||
}); | ||
// Find the specified authentication binding, if not available default to the first binding in the list | ||
const singleLogoutServiceElement = find(singleLogoutServiceElements, (element) => { | ||
return find(element.attributes, { | ||
value: `urn:oasis:names:tc:SAML:2.0:bindings:${this.options.authnRequestBinding}` | ||
}); | ||
}) || singleLogoutServiceElements[0]; | ||
// Return the location | ||
return find(singleLogoutServiceElement.attributes, { name: 'Location' }).value; | ||
} catch (e) { | ||
if (this.options.throwExceptions) throw e; | ||
if (this.options.throwExceptions) { | ||
throw e; | ||
} else { | ||
return undefined; | ||
} | ||
} | ||
@@ -62,3 +122,7 @@ } | ||
} catch (e) { | ||
if (this.options.throwExceptions) throw e; | ||
if (this.options.throwExceptions) { | ||
throw e; | ||
} else { | ||
return undefined; | ||
} | ||
} | ||
@@ -71,3 +135,7 @@ } | ||
} catch (e) { | ||
if (this.options.throwExceptions) throw e; | ||
if (this.options.throwExceptions) { | ||
throw e; | ||
} else { | ||
return undefined; | ||
} | ||
} | ||
@@ -81,3 +149,7 @@ } | ||
} catch (e) { | ||
if (this.options.throwExceptions) throw e; | ||
if (this.options.throwExceptions) { | ||
throw e; | ||
} else { | ||
return undefined; | ||
} | ||
} | ||
@@ -90,6 +162,10 @@ } | ||
} catch (e) { | ||
if (this.options.throwExceptions) throw e; | ||
if (this.options.throwExceptions) { | ||
throw e; | ||
} else { | ||
return undefined; | ||
} | ||
} | ||
} | ||
get claimSchema() { | ||
@@ -102,6 +178,8 @@ try { | ||
const description = this.query(`//md:IDPSSODescriptor/claim:Attribute[@Name="${name}"]/@FriendlyName`)[0].value; | ||
const camelCase = camel(description); | ||
claims[node.value] = { name, description, camelCase }; | ||
const camelized = camelCase(description); | ||
claims[node.value] = { name, description, camelCase: camelized }; | ||
} catch (e) { | ||
if (this.options.throwExceptions) throw e; | ||
if (this.options.throwExceptions) { | ||
throw e; | ||
} | ||
} | ||
@@ -111,3 +189,5 @@ return claims; | ||
} catch (e) { | ||
if (this.options.throwExceptions) throw e; | ||
if (this.options.throwExceptions) { | ||
throw e; | ||
} | ||
return {}; | ||
@@ -114,0 +194,0 @@ } |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
120
1
1
14571
8
271
+ Addedlodash@^4.17.10
+ Addedpassport-saml@0.35.0(transitive)
- Removedcamelcase@^5.0.0
- Removedcamelcase@5.3.1(transitive)
- Removedpassport-saml@0.33.0(transitive)
Updatedpassport-saml@^0.35.0