sso
This commit is contained in:
parent
029fe23657
commit
1876580d86
911 changed files with 160008 additions and 2 deletions
140
node_modules/passport-saml/lib/node-saml/xml.js
generated
vendored
Normal file
140
node_modules/passport-saml/lib/node-saml/xml.js
generated
vendored
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.buildXmlBuilderObject = exports.buildXml2JsObject = exports.parseXml2JsFromString = exports.parseDomFromString = exports.signXml = exports.validateXmlSignatureForCert = exports.decryptXml = exports.xpath = void 0;
|
||||
const util = require("util");
|
||||
const xmlCrypto = require("xml-crypto");
|
||||
const xmlenc = require("xml-encryption");
|
||||
const xmldom = require("xmldom");
|
||||
const xml2js = require("xml2js");
|
||||
const xmlbuilder = require("xmlbuilder");
|
||||
const types_1 = require("./types");
|
||||
const algorithms = require("./algorithms");
|
||||
const selectXPath = (guard, node, xpath) => {
|
||||
const result = xmlCrypto.xpath(node, xpath);
|
||||
if (!guard(result)) {
|
||||
throw new Error("invalid xpath return type");
|
||||
}
|
||||
return result;
|
||||
};
|
||||
const attributesXPathTypeGuard = (values) => {
|
||||
return values.every((value) => {
|
||||
if (typeof value != "object") {
|
||||
return false;
|
||||
}
|
||||
return typeof value.nodeType === "number" && value.nodeType === value.ATTRIBUTE_NODE;
|
||||
});
|
||||
};
|
||||
const elementsXPathTypeGuard = (values) => {
|
||||
return values.every((value) => {
|
||||
if (typeof value != "object") {
|
||||
return false;
|
||||
}
|
||||
return typeof value.nodeType === "number" && value.nodeType === value.ELEMENT_NODE;
|
||||
});
|
||||
};
|
||||
exports.xpath = {
|
||||
selectAttributes: (node, xpath) => selectXPath(attributesXPathTypeGuard, node, xpath),
|
||||
selectElements: (node, xpath) => selectXPath(elementsXPathTypeGuard, node, xpath),
|
||||
};
|
||||
const decryptXml = async (xml, decryptionKey) => util.promisify(xmlenc.decrypt).bind(xmlenc)(xml, { key: decryptionKey });
|
||||
exports.decryptXml = decryptXml;
|
||||
const normalizeNewlines = (xml) => {
|
||||
// we can use this utility before passing XML to `xml-crypto`
|
||||
// we are considered the XML processor and are responsible for newline normalization
|
||||
// https://github.com/node-saml/passport-saml/issues/431#issuecomment-718132752
|
||||
return xml.replace(/\r\n?/g, "\n");
|
||||
};
|
||||
const normalizeXml = (xml) => {
|
||||
// we can use this utility to parse and re-stringify XML
|
||||
// `DOMParser` will take care of normalization tasks, like replacing XML-encoded carriage returns with actual carriage returns
|
||||
return exports.parseDomFromString(xml).toString();
|
||||
};
|
||||
/**
|
||||
* This function checks that the |signature| is signed with a given |cert|.
|
||||
*/
|
||||
const validateXmlSignatureForCert = (signature, certPem, fullXml, currentNode) => {
|
||||
const sig = new xmlCrypto.SignedXml();
|
||||
sig.keyInfoProvider = {
|
||||
file: "",
|
||||
getKeyInfo: () => "<X509Data></X509Data>",
|
||||
getKey: () => Buffer.from(certPem),
|
||||
};
|
||||
const signatureStr = normalizeNewlines(signature.toString());
|
||||
sig.loadSignature(signatureStr);
|
||||
// We expect each signature to contain exactly one reference to the top level of the xml we
|
||||
// are validating, so if we see anything else, reject.
|
||||
if (sig.references.length != 1)
|
||||
return false;
|
||||
const refUri = sig.references[0].uri;
|
||||
const refId = refUri[0] === "#" ? refUri.substring(1) : refUri;
|
||||
// If we can't find the reference at the top level, reject
|
||||
const idAttribute = currentNode.getAttribute("ID") ? "ID" : "Id";
|
||||
if (currentNode.getAttribute(idAttribute) != refId)
|
||||
return false;
|
||||
// If we find any extra referenced nodes, reject. (xml-crypto only verifies one digest, so
|
||||
// multiple candidate references is bad news)
|
||||
const totalReferencedNodes = exports.xpath.selectElements(currentNode.ownerDocument, "//*[@" + idAttribute + "='" + refId + "']");
|
||||
if (totalReferencedNodes.length > 1) {
|
||||
return false;
|
||||
}
|
||||
// normalize XML to replace XML-encoded carriage returns with actual carriage returns
|
||||
fullXml = normalizeXml(fullXml);
|
||||
fullXml = normalizeNewlines(fullXml);
|
||||
return sig.checkSignature(fullXml);
|
||||
};
|
||||
exports.validateXmlSignatureForCert = validateXmlSignatureForCert;
|
||||
const signXml = (xml, xpath, location, options) => {
|
||||
var _a;
|
||||
const defaultTransforms = [
|
||||
"http://www.w3.org/2000/09/xmldsig#enveloped-signature",
|
||||
"http://www.w3.org/2001/10/xml-exc-c14n#",
|
||||
];
|
||||
if (!xml)
|
||||
throw new Error("samlMessage is required");
|
||||
if (!location)
|
||||
throw new Error("location is required");
|
||||
if (!options)
|
||||
throw new Error("options is required");
|
||||
if (!types_1.isValidSamlSigningOptions(options))
|
||||
throw new Error("options.privateKey is required");
|
||||
const transforms = (_a = options.xmlSignatureTransforms) !== null && _a !== void 0 ? _a : defaultTransforms;
|
||||
const sig = new xmlCrypto.SignedXml();
|
||||
if (options.signatureAlgorithm != null) {
|
||||
sig.signatureAlgorithm = algorithms.getSigningAlgorithm(options.signatureAlgorithm);
|
||||
}
|
||||
sig.addReference(xpath, transforms, algorithms.getDigestAlgorithm(options.digestAlgorithm));
|
||||
sig.signingKey = options.privateKey;
|
||||
sig.computeSignature(xml, {
|
||||
location,
|
||||
});
|
||||
return sig.getSignedXml();
|
||||
};
|
||||
exports.signXml = signXml;
|
||||
const parseDomFromString = (xml) => {
|
||||
return new xmldom.DOMParser().parseFromString(xml);
|
||||
};
|
||||
exports.parseDomFromString = parseDomFromString;
|
||||
const parseXml2JsFromString = async (xml) => {
|
||||
const parserConfig = {
|
||||
explicitRoot: true,
|
||||
explicitCharkey: true,
|
||||
tagNameProcessors: [xml2js.processors.stripPrefix],
|
||||
};
|
||||
const parser = new xml2js.Parser(parserConfig);
|
||||
return parser.parseStringPromise(xml);
|
||||
};
|
||||
exports.parseXml2JsFromString = parseXml2JsFromString;
|
||||
const buildXml2JsObject = (rootName, xml) => {
|
||||
const builderOpts = {
|
||||
rootName,
|
||||
headless: true,
|
||||
};
|
||||
return new xml2js.Builder(builderOpts).buildObject(xml);
|
||||
};
|
||||
exports.buildXml2JsObject = buildXml2JsObject;
|
||||
const buildXmlBuilderObject = (xml, pretty) => {
|
||||
const options = pretty ? { pretty: true, indent: " ", newline: "\n" } : {};
|
||||
return xmlbuilder.create(xml).end(options);
|
||||
};
|
||||
exports.buildXmlBuilderObject = buildXmlBuilderObject;
|
||||
//# sourceMappingURL=xml.js.map
|
||||
Loading…
Add table
Add a link
Reference in a new issue