diff --git a/README.md b/README.md
index 70d9cfa9..0e0896fe 100644
--- a/README.md
+++ b/README.md
@@ -126,6 +126,7 @@ type Profile = {
- `additionalParams`: dictionary of additional query params to add to all requests; if an object with this key is passed to `authenticate`, the dictionary of additional query params will be appended to those present on the returned URL, overriding any specified by initialization options' additional parameters (`additionalParams`, `additionalAuthorizeParams`, and `additionalLogoutParams`)
- `additionalAuthorizeParams`: dictionary of additional query params to add to 'authorize' requests
- `identifierFormat`: optional name identifier format to request from identity provider (default: `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress`)
+- `wantAssertionsSigned`: if truthy, add `WantAssertionsSigned="true"` to the metadata, to specify that the IdP should always sign the assertions.
- `acceptedClockSkewMs`: Time in milliseconds of skew that is acceptable between client and server when checking `OnBefore` and `NotOnOrAfter` assertion condition validity timestamps. Setting to `-1` will disable checking these conditions entirely. Default is `0`.
- `attributeConsumingServiceIndex`: optional `AttributeConsumingServiceIndex` attribute to add to AuthnRequest to instruct the IDP which attribute set to attach to the response ([link](http://blog.aniljohn.com/2014/01/data-minimization-front-channel-saml-attribute-requests.html))
- `disableRequestedAuthnContext`: if truthy, do not request a specific authentication context. This is [known to help when authenticating against Active Directory](https://github.com/node-saml/passport-saml/issues/226) (AD FS) servers.
diff --git a/src/passport-saml/saml.ts b/src/passport-saml/saml.ts
index 579aa7c3..247641e6 100644
--- a/src/passport-saml/saml.ts
+++ b/src/passport-saml/saml.ts
@@ -147,6 +147,7 @@ class SAML {
ctorOptions.identifierFormat === undefined
? "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
: ctorOptions.identifierFormat,
+ wantAssertionsSigned: ctorOptions.wantAssertionsSigned ?? false,
authnContext: ctorOptions.authnContext ?? [
"urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport",
],
@@ -789,7 +790,10 @@ class SAML {
}
if (assertions.length == 1) {
- if (!validSignature && !this.validateSignature(xml, assertions[0], certs)) {
+ if (
+ (this.options.wantAssertionsSigned || !validSignature) &&
+ !this.validateSignature(xml, assertions[0], certs)
+ ) {
throw new Error("Invalid signature");
}
return await this.processValidlySignedAssertionAsync(
@@ -820,7 +824,7 @@ class SAML {
if (decryptedAssertions.length != 1) throw new Error("Invalid EncryptedAssertion content");
if (
- !validSignature &&
+ (this.options.wantAssertionsSigned || !validSignature) &&
!this.validateSignature(decryptedXml, decryptedAssertions[0], certs)
) {
throw new Error("Invalid signature from encrypted assertion");
@@ -1423,6 +1427,10 @@ class SAML {
metadata.EntityDescriptor.SPSSODescriptor.NameIDFormat = this.options.identifierFormat;
}
+ if (this.options.wantAssertionsSigned) {
+ metadata.EntityDescriptor.SPSSODescriptor["@WantAssertionsSigned"] = true;
+ }
+
metadata.EntityDescriptor.SPSSODescriptor.AssertionConsumerService = {
"@index": "1",
"@isDefault": "true",
diff --git a/src/passport-saml/types.ts b/src/passport-saml/types.ts
index eacd63a1..420fd871 100644
--- a/src/passport-saml/types.ts
+++ b/src/passport-saml/types.ts
@@ -64,6 +64,7 @@ export interface SamlOptions extends SamlSigningOptions, MandatorySamlOptions {
idpIssuer?: string;
audience?: string;
scoping?: SamlScopingConfig;
+ wantAssertionsSigned?: boolean;
// InResponseTo Validation
validateInResponseTo: boolean;
diff --git a/test/static/signatures/invalid/response.root-signed.assertion-invalidly-signed-encrypted.xml b/test/static/signatures/invalid/response.root-signed.assertion-invalidly-signed-encrypted.xml
new file mode 100644
index 00000000..e1f4fa51
--- /dev/null
+++ b/test/static/signatures/invalid/response.root-signed.assertion-invalidly-signed-encrypted.xml
@@ -0,0 +1,16 @@
+
+
+ https://evil-corp.com
+
+
+ xa3vNTi+LNOhWxNoA+Hew8cIAqY=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
+
+
\ No newline at end of file
diff --git a/test/static/signatures/invalid/response.root-signed.assertion-invalidly-signed.xml b/test/static/signatures/invalid/response.root-signed.assertion-invalidly-signed.xml
new file mode 100644
index 00000000..4efb92b3
--- /dev/null
+++ b/test/static/signatures/invalid/response.root-signed.assertion-invalidly-signed.xml
@@ -0,0 +1,47 @@
+
+
+ https://evil-corp.com
+
+
+ BbH821SAM/jagHd7Pql43JU71Do=W+ALJZHsfn7ZXGBx9wqgFsO8lAi80+908NddeL32g0hknAM9bDLmEXzGacscbs9g4XeIZyO+wPC28Y2MA0VXv/E13VOm54MxJdXiqF1wqfHnYHFP1TsyAR6CIJuux8yhijopoh1cJXWTzbUWRDDcgmTnUwA6ZBKl491hxuhWvN4dsLg3M0n0R2hPuZf1ywCVBR9vo4w7Hssw4hfSEDTyGDw0WTDnh8Xzaw6dzrKFbsIlVKRDWwG2FKpIdMJhoyMf4/947JhIWPE4T0EB73+/Mv7/LmJlimQTK2kbMSainQtZrdsVXYH7ErxMsYmRPiaXd33YrxOVaK7IML8PI9xe1Q==
+MIIDtTCCAp2gAwIBAgIJAKg4VeVcIDz1MA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMTUwODEzMDE1NDIwWhcNMTUwOTEyMDE1NDIwWjBFMQswCQYDVQQGEwJVUzETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxG3ouM7U+fXbJt69X1H6d4UNg/uRr06pFuU9RkfIwNC+yaXyptqB3ynXKsL7BFt4DCd0fflRvJAx3feJIDp16wN9GDVHcufWMYPhh2j5HcTW/j9JoIJzGhJyvO00YKBt+hHy83iN1SdChKv5y0iSyiPP5GnqFw+ayyHoM6hSO0PqBou1Xb0ZSIE+DHosBnvVna5w2AiPY4xrJl9yZHZ4Q7DfMiYTgstjETio4bX+6oLiBnYktn7DjdEslqhffVme4PuBxNojI+uCeg/sn4QVLd/iogMJfDWNuLD8326Mi/FE9cCRvFlvAiMSaebMI3zPaySsxTK7Zgj5TpEbmbHI9wIDAQABo4GnMIGkMB0GA1UdDgQWBBSVGgvoW4MhMuzBGce29PY8vSzHFzB1BgNVHSMEbjBsgBSVGgvoW4MhMuzBGce29PY8vSzHF6FJpEcwRTELMAkGA1UEBhMCVVMxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAKg4VeVcIDz1MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAJu1rqs+anD74dbdwgd3CnqnQsQDJiEXmBhG2leaGt3ve9b/9gKaJg2pyb2NyppDe1uLqh6nNXDuzg1oNZrPz5pJL/eCXPl7FhxhMUi04TtLf8LeNTCIWYZiFuO4pmhohHcv8kRvYR1+6SkLTC8j/TZerm7qvesSiTQFNapa1eNdVQ8nFwVkEtWl+JzKEM1BlRcn42sjJkijeFp7DpI7pU+PnYeiaXpRv5pJo8ogM1iFxN+SnfEs0EuQ7fhKIG9aHKi7bKZ7L6SyX7MDIGLeulEU6lf5D9BfXNmcMambiS0pXhL2QXajt96UBq8FT2KNXY8XNtR4y6MyyCzhaiZZcc8=
+
+
+
+
+ https://evil-corp.com
+
+
+ frcmIha8lU6d04GedZS99GMSZr0=Cc6ARuJvTbrP9/3JieRPQD0I5bj2WGzSByswheohtwEjQxCviMBLIqfAL92E+BMi3DRqbFFL0upuFpSXbZiLUyrAWaGCs0yvHEF1w7q9i/EdCRND33IbyJCluCBkNmOmduP1hF3+Duf/MduL2FShV3INsynl5awW1aLNYZo1sBk0dFuJVTLjJIhoqihhD6yqXSZhmyI7lWWBnrUyXR0SKyrmrLfgjhZsNobibC8xqHTgeXsDiWJeHGHyaU0uRk3P0vUAJsjy0RA9J5rEkpLhMQ3T0G/0QODVhf+IPImwR6Aasw7kUXYL4v/iO2RQEM0i+l/UrM2mj55oDyrky5jRYw==
+MIIDtTCCAp2gAwIBAgIJAKg4VeVcIDz1MA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMTUwODEzMDE1NDIwWhcNMTUwOTEyMDE1NDIwWjBFMQswCQYDVQQGEwJVUzETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxG3ouM7U+fXbJt69X1H6d4UNg/uRr06pFuU9RkfIwNC+yaXyptqB3ynXKsL7BFt4DCd0fflRvJAx3feJIDp16wN9GDVHcufWMYPhh2j5HcTW/j9JoIJzGhJyvO00YKBt+hHy83iN1SdChKv5y0iSyiPP5GnqFw+ayyHoM6hSO0PqBou1Xb0ZSIE+DHosBnvVna5w2AiPY4xrJl9yZHZ4Q7DfMiYTgstjETio4bX+6oLiBnYktn7DjdEslqhffVme4PuBxNojI+uCeg/sn4QVLd/iogMJfDWNuLD8326Mi/FE9cCRvFlvAiMSaebMI3zPaySsxTK7Zgj5TpEbmbHI9wIDAQABo4GnMIGkMB0GA1UdDgQWBBSVGgvoW4MhMuzBGce29PY8vSzHFzB1BgNVHSMEbjBsgBSVGgvoW4MhMuzBGce29PY8vSzHF6FJpEcwRTELMAkGA1UEBhMCVVMxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAKg4VeVcIDz1MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAJu1rqs+anD74dbdwgd3CnqnQsQDJiEXmBhG2leaGt3ve9b/9gKaJg2pyb2NyppDe1uLqh6nNXDuzg1oNZrPz5pJL/eCXPl7FhxhMUi04TtLf8LeNTCIWYZiFuO4pmhohHcv8kRvYR1+6SkLTC8j/TZerm7qvesSiTQFNapa1eNdVQ8nFwVkEtWl+JzKEM1BlRcn42sjJkijeFp7DpI7pU+PnYeiaXpRv5pJo8ogM1iFxN+SnfEs0EuQ7fhKIG9aHKi7bKZ7L6SyX7MDIGLeulEU6lf5D9BfXNmcMambiS0pXhL2QXajt96UBq8FT2KNXY8XNtR4y6MyyCzhaiZZcc8=
+
+ vincent.vega@hacker-corp.com
+
+
+
+
+
+
+
+
+ urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
+
+
+
+
+
+
+ vincent.vega@evil-corp.com
+
+
+
+ Vincent
+
+
+
+ VEGA
+
+
+
+
+
\ No newline at end of file
diff --git a/test/static/signatures/valid/response.root-signed.assertion-unsigned-encrypted.xml b/test/static/signatures/valid/response.root-signed.assertion-unsigned-encrypted.xml
new file mode 100644
index 00000000..4030b18e
--- /dev/null
+++ b/test/static/signatures/valid/response.root-signed.assertion-unsigned-encrypted.xml
@@ -0,0 +1,16 @@
+
+
+ https://evil-corp.com
+
+
+ qFEvXFTMcZweXH2ex4ZNhRlBRNA=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
+
+
\ No newline at end of file
diff --git a/test/test-signatures.spec.ts b/test/test-signatures.spec.ts
index 8bf8f7b8..caae2df8 100644
--- a/test/test-signatures.spec.ts
+++ b/test/test-signatures.spec.ts
@@ -1,22 +1,25 @@
import { SAML } from "../lib/passport-saml/index.js";
import * as fs from "fs";
import * as sinon from "sinon";
+import { SamlConfig } from "../lib/passport-saml/types.js";
import assert = require("assert");
const cert = fs.readFileSync(__dirname + "/static/cert.pem", "ascii");
describe("Signatures", function () {
const INVALID_SIGNATURE = "Invalid signature",
+ INVALID_ENCRYPTED_SIGNATURE = "Invalid signature from encrypted assertion",
createBody = (pathToXml: string) => ({
SAMLResponse: fs.readFileSync(__dirname + "/static/signatures" + pathToXml, "base64"),
}),
testOneResponseBody = async (
samlResponseBody: Record,
shouldErrorWith: string | false | undefined,
- amountOfSignatureChecks = 1
+ amountOfSignatureChecks = 1,
+ options: Partial = {}
) => {
//== Instantiate new instance before every test
- const samlObj = new SAML({ cert });
+ const samlObj = new SAML({ cert, ...options });
//== Spy on `validateSignature` to be able to count how many times it has been called
const validateSignatureSpy = sinon.spy(samlObj, "validateSignature");
@@ -30,11 +33,17 @@ describe("Signatures", function () {
testOneResponse = (
pathToXml: string,
shouldErrorWith: string | false,
- amountOfSignaturesChecks: number | undefined
+ amountOfSignaturesChecks: number | undefined,
+ options?: Partial
) => {
//== Create a body based on an XML and run the test
return async () =>
- await testOneResponseBody(createBody(pathToXml), shouldErrorWith, amountOfSignaturesChecks);
+ await testOneResponseBody(
+ createBody(pathToXml),
+ shouldErrorWith,
+ amountOfSignaturesChecks,
+ options
+ );
};
describe("Signatures on saml:Response - Only 1 saml:Assertion", () => {
@@ -73,6 +82,47 @@ describe("Signatures", function () {
"R1A - asrt signed => error",
testOneResponse("/invalid/response.root-unsigned.assertion-signed.xml", INVALID_SIGNATURE, 2)
);
+ it(
+ "R1A - root signed - wantAssertionsSigned=true => error",
+ testOneResponse("/valid/response.root-signed.assertion-unsigned.xml", INVALID_SIGNATURE, 2, {
+ wantAssertionsSigned: true,
+ })
+ );
+ it(
+ "R1A - root signed - asrt unsigned encrypted -wantAssertionsSigned=true => error",
+ testOneResponse(
+ "/valid/response.root-signed.assertion-unsigned-encrypted.xml",
+ INVALID_ENCRYPTED_SIGNATURE,
+ 2,
+ {
+ decryptionPvk: fs.readFileSync(__dirname + "/static/testshib encryption pvk.pem"),
+ wantAssertionsSigned: true,
+ }
+ )
+ );
+ it(
+ "R1A - root signed - asrt invalidly signed wantAssertionsSigned=true => error",
+ testOneResponse(
+ "/invalid/response.root-signed.assertion-invalidly-signed.xml",
+ INVALID_SIGNATURE,
+ 2,
+ {
+ wantAssertionsSigned: true,
+ }
+ )
+ );
+ it(
+ "R1A - root signed - asrt invalidly signed encrypted wantAssertionsSigned=true => error",
+ testOneResponse(
+ "/invalid/response.root-signed.assertion-invalidly-signed-encrypted.xml",
+ INVALID_ENCRYPTED_SIGNATURE,
+ 2,
+ {
+ decryptionPvk: fs.readFileSync(__dirname + "/static/testshib encryption pvk.pem"),
+ wantAssertionsSigned: true,
+ }
+ )
+ );
});
describe("Signatures on saml:Response - 1 saml:Assertion + 1 saml:Advice containing 1 saml:Assertion", () => {
diff --git a/test/tests.spec.ts b/test/tests.spec.ts
index fbe25f4e..63652f03 100644
--- a/test/tests.spec.ts
+++ b/test/tests.spec.ts
@@ -424,6 +424,25 @@ describe("passport-saml /", function () {
metadata.should.containEql(samlConfig.logoutCallbackUrl);
});
+ it("generateServiceProviderMetadata contains WantAssertionsSigned", function () {
+ const samlConfig = {
+ cert: TEST_CERT,
+ issuer: "http://example.serviceprovider.com",
+ callbackUrl: "http://example.serviceprovider.com/saml/callback",
+ identifierFormat: "urn:oasis:names:tc:SAML:2.0:nameid-format:transient",
+ decryptionPvk: fs.readFileSync(__dirname + "/static/testshib encryption pvk.pem"),
+ wantAssertionsSigned: true,
+ };
+
+ const samlObj = new SAML(samlConfig);
+ const decryptionCert = fs.readFileSync(
+ __dirname + "/static/testshib encryption cert.pem",
+ "utf-8"
+ );
+ const metadata = samlObj.generateServiceProviderMetadata(decryptionCert);
+ metadata.should.containEql('WantAssertionsSigned="true"');
+ });
+
it("#certToPEM should generate valid certificate", function () {
const samlConfig = {
entryPoint: "https://app.onelogin.com/trust/saml2/http-post/sso/371755",