/
saml-post-signing.ts
46 lines (39 loc) · 1.71 KB
/
saml-post-signing.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import { SignedXml } from "xml-crypto";
import * as algorithms from "./algorithms";
import { SamlOptions, SamlSigningOptions } from "./types";
const authnRequestXPath =
'/*[local-name(.)="AuthnRequest" and namespace-uri(.)="urn:oasis:names:tc:SAML:2.0:protocol"]';
const issuerXPath =
'/*[local-name(.)="Issuer" and namespace-uri(.)="urn:oasis:names:tc:SAML:2.0:assertion"]';
const defaultTransforms = [
"http://www.w3.org/2000/09/xmldsig#enveloped-signature",
"http://www.w3.org/2001/10/xml-exc-c14n#",
];
export function signSamlPost(samlMessage: string, xpath: string, options: SamlSigningOptions) {
if (!samlMessage) throw new Error("samlMessage is required");
if (!xpath) throw new Error("xpath is required");
if (!options) {
options = {} as SamlSigningOptions;
}
if (options.privateCert) {
console.warn("options.privateCert has been deprecated; use options.privateKey instead.");
if (!options.privateKey) {
options.privateKey = options.privateCert;
}
}
if (!options.privateKey) throw new Error("options.privateKey is required");
const transforms = options.xmlSignatureTransforms || defaultTransforms;
const sig = new SignedXml();
if (options.signatureAlgorithm) {
sig.signatureAlgorithm = algorithms.getSigningAlgorithm(options.signatureAlgorithm);
}
sig.addReference(xpath, transforms, algorithms.getDigestAlgorithm(options.digestAlgorithm));
sig.signingKey = options.privateKey;
sig.computeSignature(samlMessage, {
location: { reference: xpath + issuerXPath, action: "after" },
});
return sig.getSignedXml();
}
export function signAuthnRequestPost(authnRequest: string, options: SamlSigningOptions) {
return signSamlPost(authnRequest, authnRequestXPath, options);
}