Search code examples
salesforcekentor-authservicessustainsys-saml2

The signature verified correctly with the key contained in the signature, but that key is not trusted


I am trying to configure SAML2 IdP Salesforce as external provider in IdentityServer3. I am using SustainSys/Saml2 library. So for testing purpose I have downloaded SampleIdentityServer3. and configured SAML2 IdP like below

    private void ConfigureSaml2(IAppBuilder app, string signInAsType)
    {
        ServicePointManager.Expect100Continue = true;
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3;

        var options = new Saml2AuthenticationOptions(false)
        {
            SPOptions = new SPOptions
            {
                EntityId = new EntityId("http://localhost:4589/IdSrv3/Saml2"),    
                MinIncomingSigningAlgorithm = "http://www.w3.org/2000/09/xmldsig#rsa-sha1"
            },
            SignInAsAuthenticationType = signInAsType,
            Caption = "SAML2p",

        };

        UseIdSrv3LogoutOnFederatedLogout(app, options);

        options.SPOptions.ServiceCertificates.Add(new X509Certificate2(
            AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "/App_Data/Sustainsys.Saml2.Tests.pfx"));

        var idp = new IdentityProvider(
            new EntityId("https://XXXXXX-dev-ed.my.salesforce.com"),
            options.SPOptions)
        {
            MetadataLocation = "https://XXXXXX-dev-ed.my.salesforce.com/.well-known/samlidp.xml",
            LoadMetadata = true,                
        };

        options.IdentityProviders.Add(idp);
        app.UseSaml2Authentication(options);
    }

Note that if i don't set MinIncomingSigningAlgorithm to sh1 then the SustainSys library throws error.

Sustainsys.Saml2.Exceptions.InvalidSignatureException: The signing algorithm http://www.w3.org/2000/09/xmldsig#rsa-sha1 is weaker than the minimum accepted http://www.w3.org/2001/04/xmldsig-more#rsa-sha256. If you want to allow this signing algorithm, use the minIncomingSigningAlgorithm configuration attribute.

So i set the MinIncomingSigningAlgorithm to "http://www.w3.org/2000/09/xmldsig#rsa-sha1" to get rid of the error.

But then i get different error

Sustainsys.Saml2.Exceptions.InvalidSignatureException: The signature verified correctly with the key contained in the signature, but that key is not trusted.

based on issue #493 #735 the certificate in metadata must match with the certificate in SAML2 response.

In metadata the certificate is (notice start and end values)

  <ds:X509Data>
    <ds:X509Certificate>
       MIIGk... removed from brevity....tmv6J1g==
    </ds:X509Certificate>
  </ds:X509Data>

But in SAML2 response ( the one that is logged by SustainSys library)

<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Destination="http://localhost:4589/IdSrv3/Saml2/Acs" ID="_19fd2d8d9aab0401f56fXXXXXXXXX" InResponseTo="id473a52c49f194bXXXXXXXXX"    IssueInstant="2018-08-27T20:10:04.296Z" Version="2.0">
    <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://XXXXXXX-dev-ed.my.salesforce.com</saml:Issuer>
    <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:SignedInfo>
            <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
            <ds:Reference URI="#_19fd2d8d9aab0401f56f642dXXXXXXXXXXXXX">
                <ds:Transforms>
                    <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
                    <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="ds saml samlp" /></ds:Transform>
                </ds:Transforms>
                <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
                <ds:DigestValue>fQiiyd0T57Ztr5BAfMFe9MTrhY0=</ds:DigestValue>
            </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>
            B6hndlsBgY45J+hm8My2gPVo....removed for brevity....YT88ajt7jQ==
        </ds:SignatureValue>
        <ds:KeyInfo>
            <ds:X509Data>
                <ds:X509Certificate>
                    MIIENz... remove for brevity....y2Ul24Jyc4V/jJN
                </ds:X509Certificate>
            </ds:X509Data>
        </ds:KeyInfo>
        </ds:Signature>
        <samlp:Status>
            <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:AuthnFailed" />
        </samlp:Status>
    </samlp:Response>

looking at X509Certificate value in metadata and in SAML2 response they don't match.

Question
Does the X509Certificate value in SAML2 response supposed to match with X509Certificate value in metadata? If yes, why can't SustainSys library always use the X509Certificate value from SAML2 response?

Update
Just to see if matching the values would work, I saved certificate value from SAML2 response into separate .cer file. and Then in KeyInfoSerializer.cs file i updated ReadX509Certificate method (this is the method that loads the certificate from metadata)

    private static SecurityKeyIdentifierClause ReadX509Certificate(XmlReader reader)
    {
        reader.ReadStartElement("X509Certificate", SignedXml.XmlDsigNamespaceUrl);
        ((XmlDictionaryReader)reader).ReadContentAsString();

        var cer = new X509Certificate2(AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "/App_Data/salesforcepublickey.cer");
        var clause = new X509RawDataKeyIdentifierClause(cer);
        reader.ReadEndElement();
        return clause;
    }

However, it still throws error The signature verified correctly with the key contained in the signature, but that key is not trusted.


Solution

  • Found it.
    It was issue on Salesforce side. In Saleforce, when i check the logs Identity->Identity Provider Event Log i see error Error: User does not have access to this service provider

    For this, the user was not given permission. Even if the user is System Administrator, the access to Connected App is not given by default. To give permission, go to 'Manage Users -> Users' and click edit on the user you are testing.Click profile name link .e.g System Administrator. This takes to profile page. You can scroll below to 'Connected App Access' and you would see that the access is not given. Give the access by clicking edit profile in the top of page.