Comparing version 2.8.10 to 2.8.11
@@ -29,3 +29,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.setSchemaValidator = exports.ServiceProviderInstance = exports.ServiceProvider = exports.IdentityProviderInstance = exports.IdentityProvider = exports.Extractor = exports.Constants = exports.SamlLib = exports.Utility = exports.SPMetadata = exports.IdPMetadata = void 0; | ||
exports.setDOMParserOptions = exports.setSchemaValidator = exports.ServiceProviderInstance = exports.ServiceProvider = exports.IdentityProviderInstance = exports.IdentityProvider = exports.Extractor = exports.Constants = exports.SamlLib = exports.Utility = exports.SPMetadata = exports.IdPMetadata = void 0; | ||
// version <= 1.25 | ||
@@ -52,5 +52,6 @@ var entity_idp_1 = __importStar(require("./src/entity-idp")); | ||
exports.Extractor = Extractor; | ||
// exposed methods for customising samlify | ||
// exposed methods for customizing samlify | ||
var api_1 = require("./src/api"); | ||
Object.defineProperty(exports, "setSchemaValidator", { enumerable: true, get: function () { return api_1.setSchemaValidator; } }); | ||
Object.defineProperty(exports, "setDOMParserOptions", { enumerable: true, get: function () { return api_1.setDOMParserOptions; } }); | ||
//# sourceMappingURL=index.js.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.setSchemaValidator = exports.getContext = void 0; | ||
exports.setDOMParserOptions = exports.setSchemaValidator = exports.getContext = void 0; | ||
var xmldom_1 = require("@xmldom/xmldom"); | ||
var context = { | ||
validate: undefined | ||
validate: undefined, | ||
dom: new xmldom_1.DOMParser() | ||
}; | ||
@@ -19,2 +21,7 @@ function getContext() { | ||
exports.setSchemaValidator = setSchemaValidator; | ||
function setDOMParserOptions(options) { | ||
if (options === void 0) { options = {}; } | ||
context.dom = new xmldom_1.DOMParser(options); | ||
} | ||
exports.setDOMParserOptions = setDOMParserOptions; | ||
//# sourceMappingURL=api.js.map |
@@ -18,7 +18,6 @@ "use strict"; | ||
exports.extract = exports.logoutResponseFields = exports.logoutRequestFields = exports.loginResponseFields = exports.logoutResponseStatusFields = exports.loginResponseStatusFields = exports.loginRequestFields = void 0; | ||
var xmldom_1 = require("@xmldom/xmldom"); | ||
var xpath_1 = require("xpath"); | ||
var utility_1 = require("./utility"); | ||
var api_1 = require("./api"); | ||
var camelcase_1 = __importDefault(require("camelcase")); | ||
var dom = xmldom_1.DOMParser; | ||
function buildAbsoluteXPath(paths) { | ||
@@ -200,3 +199,4 @@ return paths.reduce(function (currentPath, name) { | ||
function extract(context, fields) { | ||
var rootDoc = new dom().parseFromString(context); | ||
var dom = (0, api_1.getContext)().dom; | ||
var rootDoc = dom.parseFromString(context); | ||
return fields.reduce(function (result, field) { | ||
@@ -218,3 +218,3 @@ var _a, _b, _c, _d, _e, _f; | ||
if (shortcut) { | ||
targetDoc = new dom().parseFromString(shortcut); | ||
targetDoc = dom.parseFromString(shortcut); | ||
} | ||
@@ -267,3 +267,3 @@ // special case: multiple path | ||
var childAttributes = parentNodes.map(function (node) { | ||
var nodeDoc = new dom().parseFromString(node.toString()); | ||
var nodeDoc = dom.parseFromString(node.toString()); | ||
if (attributes.length === 0) { | ||
@@ -321,3 +321,3 @@ var childValues = (0, xpath_1.select)(fullChildXPath_1, nodeDoc).map(function (n) { return n.nodeValue; }); | ||
var attributeValues = baseNode.map(function (node) { | ||
var nodeDoc = new dom().parseFromString(node); | ||
var nodeDoc = dom.parseFromString(node); | ||
var values = (0, xpath_1.select)(childXPath_1, nodeDoc).reduce(function (r, n) { | ||
@@ -324,0 +324,0 @@ r[(0, camelcase_1.default)(n.name, { locale: 'en-us' })] = n.value; |
@@ -70,3 +70,2 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var xmldom_1 = require("@xmldom/xmldom"); | ||
var utility_1 = __importStar(require("./utility")); | ||
@@ -81,2 +80,3 @@ var urn_1 = require("./urn"); | ||
var api_1 = require("./api"); | ||
var xml_escape_1 = __importDefault(require("xml-escape")); | ||
var signatureAlgorithms = urn_1.algorithms.signature; | ||
@@ -86,3 +86,2 @@ var digestAlgorithms = urn_1.algorithms.digest; | ||
var urlParams = urn_1.wording.urlParams; | ||
var dom = xmldom_1.DOMParser; | ||
var libSaml = function () { | ||
@@ -209,2 +208,8 @@ /** | ||
} | ||
function escapeTag(text) { | ||
return function (match, quote) { | ||
// not having a quote means this interpolation isn't for an attribute, and so does not need escaping | ||
return quote ? "".concat(quote).concat((0, xml_escape_1.default)(text || '')) : text; | ||
}; | ||
} | ||
return { | ||
@@ -227,3 +232,3 @@ createXPath: createXPath, | ||
Object.keys(tagValues).forEach(function (t) { | ||
rawXML = rawXML.replace(new RegExp("{".concat(t, "}"), 'g'), tagValues[t]); | ||
rawXML = rawXML.replace(new RegExp("(\"?)\\{".concat(t, "\\}"), 'g'), escapeTag(tagValues[t])); | ||
}); | ||
@@ -302,3 +307,4 @@ return rawXML; | ||
var _this = this; | ||
var doc = new dom().parseFromString(xml); | ||
var dom = (0, api_1.getContext)().dom; | ||
var doc = dom.parseFromString(xml); | ||
// In order to avoid the wrapping attack, we have changed to use absolute xpath instead of naively fetching the signature element | ||
@@ -513,3 +519,4 @@ // message signature (logout response / saml response) | ||
var targetEntityMetadata = targetEntity.entityMeta; | ||
var doc = new dom().parseFromString(xml); | ||
var dom = (0, api_1.getContext)().dom; | ||
var doc = dom.parseFromString(xml); | ||
var assertions = (0, xpath_1.select)("//*[local-name(.)='Assertion']", doc); | ||
@@ -541,3 +548,3 @@ if (!Array.isArray(assertions) || assertions.length === 0) { | ||
var encAssertionPrefix = sourceEntitySetting.tagPrefix.encryptedAssertion; | ||
var encryptAssertionDoc = new dom().parseFromString("<".concat(encAssertionPrefix, ":EncryptedAssertion xmlns:").concat(encAssertionPrefix, "=\"").concat(urn_1.namespace.names.assertion, "\">").concat(res, "</").concat(encAssertionPrefix, ":EncryptedAssertion>")); | ||
var encryptAssertionDoc = dom.parseFromString("<".concat(encAssertionPrefix, ":EncryptedAssertion xmlns:").concat(encAssertionPrefix, "=\"").concat(urn_1.namespace.names.assertion, "\">").concat(res, "</").concat(encAssertionPrefix, ":EncryptedAssertion>")); | ||
doc.documentElement.replaceChild(encryptAssertionDoc.documentElement, rawAssertionNode); | ||
@@ -568,3 +575,4 @@ return resolve(utility_1.default.base64Encode(doc.toString())); | ||
var hereSetting = here.entitySetting; | ||
var doc = new dom().parseFromString(entireXML); | ||
var dom = (0, api_1.getContext)().dom; | ||
var doc = dom.parseFromString(entireXML); | ||
var encryptedAssertions = (0, xpath_1.select)("/*[contains(local-name(), 'Response')]/*[local-name(.)='EncryptedAssertion']", doc); | ||
@@ -588,3 +596,3 @@ if (!Array.isArray(encryptedAssertions) || encryptedAssertions.length === 0) { | ||
} | ||
var rawAssertionDoc = new dom().parseFromString(res); | ||
var rawAssertionDoc = dom.parseFromString(res); | ||
doc.documentElement.replaceChild(rawAssertionDoc.documentElement, encAssertionNode); | ||
@@ -591,0 +599,0 @@ return resolve([doc.toString(), res]); |
@@ -14,4 +14,4 @@ // version <= 1.25 | ||
// exposed methods for customising samlify | ||
import { setSchemaValidator } from './src/api'; | ||
// exposed methods for customizing samlify | ||
import { setSchemaValidator, setDOMParserOptions } from './src/api'; | ||
@@ -27,3 +27,4 @@ export { | ||
// set context | ||
setSchemaValidator | ||
setSchemaValidator, | ||
setDOMParserOptions | ||
}; |
{ | ||
"name": "samlify", | ||
"version": "2.8.10", | ||
"version": "2.8.11", | ||
"description": "High-level API for Single Sign On (SAML 2.0)", | ||
@@ -43,2 +43,3 @@ "main": "build/index.js", | ||
"xml-crypto": "^3.0.1", | ||
"xml-escape": "^1.1.0", | ||
"xpath": "^0.0.32" | ||
@@ -45,0 +46,0 @@ }, |
# samlify · | ||
[![Build Status](https://travis-ci.org/tngan/samlify.svg?branch=master)](https://travis-ci.org/tngan/samlify) | ||
[![npm version](https://img.shields.io/npm/v/samlify.svg?style=flat)](https://www.npmjs.com/package/samlify) | ||
[![NPM](https://img.shields.io/npm/dm/samlify.svg)](https://www.npmjs.com/package/samlify) | ||
[![Coverage Status](https://img.shields.io/coveralls/tngan/samlify/master.svg)](https://coveralls.io/github/tngan/samlify?branch=master) | ||
[![Build Status](https://img.shields.io/circleci/build/github/tngan/samlify?style=for-the-badge&logo=circleci)](https://app.circleci.com/pipelines/github/tngan/samlify) | ||
[![npm version](https://img.shields.io/npm/v/samlify.svg?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/samlify) | ||
[![NPM](https://img.shields.io/npm/dm/samlify.svg?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/samlify) | ||
[![Coverage Status](https://img.shields.io/coveralls/tngan/samlify/master.svg?style=for-the-badge&logo=coveralls)](https://coveralls.io/github/tngan/samlify?branch=master) | ||
@@ -8,0 +8,0 @@ Highly configuarable Node.js SAML 2.0 library for Single Sign On |
@@ -0,3 +1,5 @@ | ||
import { DOMParser as dom, Options as DOMParserOptions } from '@xmldom/xmldom'; | ||
// global module configuration | ||
interface Context extends ValidatorContext {} | ||
interface Context extends ValidatorContext, DOMParserContext {} | ||
@@ -8,4 +10,9 @@ interface ValidatorContext { | ||
interface DOMParserContext { | ||
dom: dom; | ||
} | ||
const context: Context = { | ||
validate: undefined | ||
validate: undefined, | ||
dom: new dom() | ||
}; | ||
@@ -27,1 +34,5 @@ | ||
} | ||
export function setDOMParserOptions(options: DOMParserOptions = {}) { | ||
context.dom = new dom(options); | ||
} |
@@ -1,6 +0,5 @@ | ||
import { DOMParser } from '@xmldom/xmldom'; | ||
import { select, SelectedValue } from 'xpath'; | ||
import { uniq, last, zipObject, notEmpty } from './utility'; | ||
import { getContext } from './api'; | ||
import camelCase from 'camelcase'; | ||
const dom = DOMParser; | ||
@@ -201,5 +200,5 @@ interface ExtractorField { | ||
export function extract(context: string, fields) { | ||
const { dom } = getContext(); | ||
const rootDoc = dom.parseFromString(context); | ||
const rootDoc = new dom().parseFromString(context); | ||
return fields.reduce((result: any, field) => { | ||
@@ -222,3 +221,3 @@ // get essential fields | ||
if (shortcut) { | ||
targetDoc = new dom().parseFromString(shortcut); | ||
targetDoc = dom.parseFromString(shortcut); | ||
} | ||
@@ -278,3 +277,3 @@ | ||
const childAttributes = parentNodes.map(node => { | ||
const nodeDoc = new dom().parseFromString(node.toString()); | ||
const nodeDoc = dom.parseFromString(node.toString()); | ||
if (attributes.length === 0) { | ||
@@ -340,3 +339,3 @@ const childValues = select(fullChildXPath, nodeDoc).map((n: Node) => n.nodeValue); | ||
const attributeValues = baseNode.map((node: string) => { | ||
const nodeDoc = new dom().parseFromString(node); | ||
const nodeDoc = dom.parseFromString(node); | ||
const values = select(childXPath, nodeDoc).reduce((r: any, n: Attr) => { | ||
@@ -343,0 +342,0 @@ r[camelCase(n.name, {locale: 'en-us'})] = n.value; |
@@ -7,3 +7,2 @@ /** | ||
import { DOMParser } from '@xmldom/xmldom'; | ||
import utility, { flattenDeep, isString } from './utility'; | ||
@@ -19,2 +18,3 @@ import { algorithms, wording, namespace } from './urn'; | ||
import { getContext } from './api'; | ||
import xmlEscape from 'xml-escape'; | ||
@@ -25,3 +25,2 @@ const signatureAlgorithms = algorithms.signature; | ||
const urlParams = wording.urlParams; | ||
const dom = DOMParser; | ||
@@ -99,3 +98,3 @@ export interface SignatureConstructor { | ||
constructSAMLSignature: (opts: SignatureConstructor) => string; | ||
verifySignature: (xml: string, opts) => [boolean, any]; | ||
verifySignature: (xml: string, opts: SignatureVerifierOptions) => [boolean, any]; | ||
createKeySection: (use: KeyUse, cert: string | Buffer) => {}; | ||
@@ -247,2 +246,9 @@ constructMessageSignature: (octetString: string, key: string, passphrase?: string, isBase64?: boolean, signingAlgorithm?: string) => string; | ||
function escapeTag(text: string): (...args: string[]) => string { | ||
return (match: string, quote?: string) => { | ||
// not having a quote means this interpolation isn't for an attribute, and so does not need escaping | ||
return quote ? `${quote}${xmlEscape(text || '')}` : text; | ||
} | ||
} | ||
return { | ||
@@ -267,3 +273,6 @@ | ||
Object.keys(tagValues).forEach(t => { | ||
rawXML = rawXML.replace(new RegExp(`{${t}}`, 'g'), tagValues[t]); | ||
rawXML = rawXML.replace( | ||
new RegExp(`("?)\\{${t}\\}`, 'g'), | ||
escapeTag(tagValues[t]) | ||
); | ||
}); | ||
@@ -364,4 +373,4 @@ return rawXML; | ||
verifySignature(xml: string, opts: SignatureVerifierOptions) { | ||
const doc = new dom().parseFromString(xml); | ||
const { dom } = getContext(); | ||
const doc = dom.parseFromString(xml); | ||
// In order to avoid the wrapping attack, we have changed to use absolute xpath instead of naively fetching the signature element | ||
@@ -614,3 +623,4 @@ // message signature (logout response / saml response) | ||
const targetEntityMetadata = targetEntity.entityMeta; | ||
const doc = new dom().parseFromString(xml); | ||
const { dom } = getContext(); | ||
const doc = dom.parseFromString(xml); | ||
const assertions = select("//*[local-name(.)='Assertion']", doc) as Node[]; | ||
@@ -645,3 +655,3 @@ if (!Array.isArray(assertions) || assertions.length === 0) { | ||
const { encryptedAssertion: encAssertionPrefix } = sourceEntitySetting.tagPrefix; | ||
const encryptAssertionDoc = new dom().parseFromString(`<${encAssertionPrefix}:EncryptedAssertion xmlns:${encAssertionPrefix}="${namespace.names.assertion}">${res}</${encAssertionPrefix}:EncryptedAssertion>`); | ||
const encryptAssertionDoc = dom.parseFromString(`<${encAssertionPrefix}:EncryptedAssertion xmlns:${encAssertionPrefix}="${namespace.names.assertion}">${res}</${encAssertionPrefix}:EncryptedAssertion>`); | ||
doc.documentElement.replaceChild(encryptAssertionDoc.documentElement, rawAssertionNode); | ||
@@ -671,3 +681,4 @@ return resolve(utility.base64Encode(doc.toString())); | ||
const hereSetting = here.entitySetting; | ||
const doc = new dom().parseFromString(entireXML); | ||
const { dom } = getContext(); | ||
const doc = dom.parseFromString(entireXML); | ||
const encryptedAssertions = select("/*[contains(local-name(), 'Response')]/*[local-name(.)='EncryptedAssertion']", doc) as Node[]; | ||
@@ -692,3 +703,3 @@ if (!Array.isArray(encryptedAssertions) || encryptedAssertions.length === 0) { | ||
} | ||
const rawAssertionDoc = new dom().parseFromString(res); | ||
const rawAssertionDoc = dom.parseFromString(res); | ||
doc.documentElement.replaceChild(rawAssertionDoc.documentElement, encAssertionNode); | ||
@@ -695,0 +706,0 @@ return resolve([doc.toString(), res]); |
@@ -9,3 +9,3 @@ import IdentityProvider, { IdentityProvider as IdentityProviderInstance } from './src/entity-idp'; | ||
import * as Extractor from './src/extractor'; | ||
import { setSchemaValidator } from './src/api'; | ||
export { Constants, Extractor, IdentityProvider, IdentityProviderInstance, ServiceProvider, ServiceProviderInstance, setSchemaValidator }; | ||
import { setSchemaValidator, setDOMParserOptions } from './src/api'; | ||
export { Constants, Extractor, IdentityProvider, IdentityProviderInstance, ServiceProvider, ServiceProviderInstance, setSchemaValidator, setDOMParserOptions }; |
@@ -1,2 +0,3 @@ | ||
interface Context extends ValidatorContext { | ||
import { DOMParser as dom, Options as DOMParserOptions } from '@xmldom/xmldom'; | ||
interface Context extends ValidatorContext, DOMParserContext { | ||
} | ||
@@ -6,4 +7,8 @@ interface ValidatorContext { | ||
} | ||
interface DOMParserContext { | ||
dom: dom; | ||
} | ||
export declare function getContext(): Context; | ||
export declare function setSchemaValidator(params: ValidatorContext): void; | ||
export declare function setDOMParserOptions(options?: DOMParserOptions): void; | ||
export {}; |
@@ -71,3 +71,3 @@ /** | ||
constructSAMLSignature: (opts: SignatureConstructor) => string; | ||
verifySignature: (xml: string, opts: any) => [boolean, any]; | ||
verifySignature: (xml: string, opts: SignatureVerifierOptions) => [boolean, any]; | ||
createKeySection: (use: KeyUse, cert: string | Buffer) => {}; | ||
@@ -74,0 +74,0 @@ constructMessageSignature: (octetString: string, key: string, passphrase?: string, isBase64?: boolean, signingAlgorithm?: string) => string; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
496461
9129
11
+ Addedxml-escape@^1.1.0
+ Addedxml-escape@1.1.0(transitive)