129

I have to implement SSO with SAML for my company's website (as the relying party). An essential part off course is the verification of the signature. Here is the signature part of a sample SAML from our partner company (asserting party):

<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
 <ds:SignedInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
  <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
  <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
  <ds:Reference URI="#_2152811999472b94a0e9644dbc932cc3" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
   <ds:Transforms xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
    <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
     <ec:InclusiveNamespaces PrefixList="ds saml samlp xs" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>
    </ds:Transform>
   </ds:Transforms>
   <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
   <ds:DigestValue xmlns:ds="http://www.w3.org/2000/09/xmldsig#">bW1Os7+WykqRt5h0mdv9o3ZF0JI=</ds:DigestValue>
  </ds:Reference>
 </ds:SignedInfo>
 <ds:SignatureValue xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
cgrAN4T/UmobhrkkTi3miiRfbo0Z7aakSZjXuTWlZlu9jDptxPNbOFw8ZbYKZYyuW544wQqgqpnG
gr5GBWILSngURjf2N45/GDv7HMrv/NRMsRMrgVfFsKbcAovQdLAs24O0Q9CH5UdADai1QtDro3jx
nl4x7HaWIo9F8Gp/H1c=
 </ds:SignatureValue>
 <ds:KeyInfo>
  <ds:X509Data>
   <ds:X509Certificate>MIIElzCCA3+gAwIBAgIQNT2i6HKJtCXFUFRB8qYsZjANBgkqhkiG9w0BAQUFADB3MQswCQYDVQQG
    EwJGUjEOMAwGA1UEBxMFUGFyaXMxDDAKBgNVBAoTA3BzYTEgMB4GA1UECxMXY2VydGlmaWNhdGUg
    YXV0aG9yaXRpZXMxKDAmBgNVBAMTH0FDIFBTQSBQZXVnZW90IENpdHJvZW4gUHJvZ3JhbXMwHhcN
    MDkwODE5MDcxNTE4WhcNMTEwODE5MDcxNTE5WjCBhjELMAkGA1UEBhMCZnIxHzAdBgkqhkiG9w0B
    CQEWEHBhc3NleHRAbXBzYS5jb20xGDAWBgoJkiaJk/IsZAEBEwhtZGVtb2IwMDEMMAoGA1UEChMD
    cHNhMREwDwYDVQQLEwhwcm9ncmFtczEbMBkGA1UEAxMSVGVzdCAtIFBBU1NFWFQgREVWMIGfMA0G
    CSqGSIb3DQEBAQUAA4GNADCBiQKBgQCuY1nrepgACvDSTLWk5A1cFOJSwDbl6CWfYp3cNYR0K3YV
    e07MDZn+Rv4jo3SusHVFds+mzKX2f8AeZjkA3Me/0yiS9UpS9LQZu9mnhFlZRhmUlDDoIZxovLXN
    aOv/YHmPeTQMQmJZu5TjqraUq7La1c187AoJuNfpxt227N1vOQIDAQABo4IBkTCCAY0wDgYDVR0P
    AQH/BAQDAgWgMB8GA1UdIwQYMBaAFLceWtTfVeRuVCTDQWkmwO4U01X/MAwGA1UdEwEB/wQCMAAw
    gbYGA1UdIASBrjCBqzCBqAYKKoF6ARfOEAEBBDCBmTBBBggrBgEFBQcCARY1aHR0cDovL3JldW5p
    cy5pbmV0cHNhLmNvbS9hdXRvcml0ZS9QQy1BQy1Qcm9ncmFtcy5wZGYwVAYIKwYBBQUHAgIwSDAK
    FgNwc2EwAwIBARo6UG9saXRpcXVlIGRlIENlcnRpZmljYXRpb24gQUMgUFNBIFBldWdlb3QgQ2l0
    cm9lbiBQcm9ncmFtczBcBgNVHR8EVTBTMFGgT6BNhktodHRwOi8vaW5mb2NlcnQucHNhLXBldWdl
    b3QtY2l0cm9lbi5jb20vQUMtUFNBLVBldWdlb3QtQ2l0cm9lbi1Qcm9ncmFtcy5jcmwwHQYDVR0l
    BBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBYGA1UdDgQPBA1BVVRPX0dFTkVSQVRFMA0GCSqGSIb3
    DQEBBQUAA4IBAQCvRtP6bFkOUEHcqc6yUX0Q1Gk2WaAcx4ziUB0tw2GR9I0276JRJR0EGuJ/N6Fn
    3FhLQrSPmS97Xvc9XmiI66fQUdg64g9YqBecdiQlUkR20VLgI6Nq8pldQlWjU2iYlkP15U7VF4Qr
    0Pb2QiIljZUCKdv3qdED2Ri33za46LfykrlwZB0uhTVUxI/AEtjkKVFaZaqanJg+vJyZI5b30z7g
    Ff8L3ht4Z7SFKdmY3IQSGzElIAAUfduzTJX0cwnGSU9D4BJu1BS8hWnYPwhk+nBJ7OFhXdwYQFWq
    fhpBLq+ciJti9OMhcdCSIi0PbrOqzqtX7hZUQOvfShhCTJnl5TJJ</ds:X509Certificate>
  </ds:X509Data>
 </ds:KeyInfo>
</ds:Signature>

What I just don't understand is, why is the certificate within the signature?

I mean usually I get a certificate from the company in a secure kind of way, so I know the certificate is from them. And when the verification of the signature succeeds, I know our partner company has signed it.

But when the certificate is within the signature of the SAML-Response, anyone could have sent it! The only thing I know is that the response hasn't been falsified. But the point is, I have no idea who sent the SAML.

Can anyone explain to me, how that works?

1
  • 4
    The public key only allows for verification. You can't sign text with the public cert that's included.
    – AaronF
    Commented Nov 19, 2021 at 23:46

4 Answers 4

72

SAML responses come with a signature and a public key for that signature.

You can use the public key to verify that the content of the SAML response matches the key - in other words - that response definitely came from someone who has the matching private key to the public key in the message, and the response hasn't been tampered with.

I don't know what tech you're working with, but in .Net you can check it like this:

// load a new XML document
var assertion = new XmlDocument { PreserveWhitespace = true };
assertion.LoadXml("The SAML XML that you were sent");

// use a namespace manager to avoid the worst of xpaths
var ns = new XmlNamespaceManager(assertion.NameTable);
ns.AddNamespace("samlp", @"urn:oasis:names:tc:SAML:2.0:protocol");
ns.AddNamespace("asrt", @"urn:oasis:names:tc:SAML:2.0:assertion");
ns.AddNamespace("dsig", @"http://www.w3.org/2000/09/xmldsig#");

// get nodes down to the signature
var responseNode = assertion.SelectSingleNode("/samlp:Response", ns);
var assertionNode = responseNode.SelectSingleNode("asrt:Assertion", ns);
var signNode = assertionNode.SelectSingleNode("dsig:Signature", ns);

// load the XML signature
var signedXml = new SignedXml(assertion.DocumentElement);
signedXml.LoadXml(signNode as XmlElement);

// get the certificate, basically:
//     signedXml.KeyInfo[0].Certificates[0]
// ...but with added casting
var certificate = GetFirstX509Certificate(signedXml);

// check the key and signature match
bool isSigned = signedXml.CheckSignature(certificate, true);

That just checks that the message is from who it says it is. You need an additional check that the message has come from someone that you trust, and this check is slower - it needs to include revocation and may need to verify a whole chain of certificates.

Normally this will be a list of public keys that you would accept SAML responses from.

Then you can check that this message hasn't been tampered with, and is from someone that you trust, so you can authorise the user details supplied in the SAML attributes supplied.

You could already have the public key, meaning that the signature shouldn't need to include the public key again, but you could also have multiple possible known senders, or even a chain of known senders.

For instance you may have two trusted providers - in either case you check that the message has not been tampered with before checking whether you trust either provider. If the key isn't in the signature the assertions can be a little smaller, but now you have to know in advance which identity provider the assertion has come from.

So, really, there are two main reasons that the public key is in the signature:

  1. The tamper check is quicker than the identity check, and can be isolated if the public key is known.
  2. Multiple identities are much easier to support if the key is in the assertion.
16
  • 3
    @svlada the SAML assertion doesn't need it's own encryption, as the text itself can be sent over SSL - the whole user session should be HTTPS. Given that verification that the known, trusted sender signed the assertion and that it hasn't been tampered with is enough.
    – Keith
    Commented Feb 13, 2013 at 8:55
  • 6
    @svlada no HTTP-based authentication (of any kind) should ever be done without SSL. Encrypting the certificate will stop a man in the middle (MitM) from reading it, but it won't stop them from re-using it in a similar way to a cookie based MitM attack.
    – Keith
    Commented Feb 13, 2013 at 9:45
  • 10
    SAML responses do not require including the public key for that signature. Section 5.4.5 of the SAML2 spec states "XML Signature defines usage of the <ds:KeyInfo> element. SAML does not require the use of <ds:KeyInfo>, nor does it impose any restrictions on its use. Therefore, <ds:KeyInfo> MAY be absent." You can verify the signature if the public key has been provided to you through other means, e.g. stored in your local certificate store prior to implementing the SAML consumer.
    – Sam Rueby
    Commented Nov 5, 2014 at 16:01
  • 3
    @Sam.Rueby ah, I will correct it. Every implementation I've seen has included the key.
    – Keith
    Commented Nov 10, 2014 at 10:56
  • 6
    @Jez this whole protocol is as confusing as hell. Basically the assertion is self contained - you can check that it hasn't been tampered with since the private key signed it. You can do this without having that public key yourself (so I know this assertion has come from Dave, and that nobody has tampered with it since Dave signed it, but I might have no idea who Dave is or whether I can trust him). Then, after verifying that, I can check the public key is one I trust. I think this is because there might be a delay on that final check (while I go ask about the office whether anybody knows Dave)
    – Keith
    Commented Feb 12, 2015 at 10:13
67

The reason a public key is specified in the SAML response is because the metadata for an identity provider can specify multiple public keys. This allows the identity provider (asserting party) to specify to the service provider (relying party) the correct public key to use to verify the signature in the SAML response.

For example, the asserting party's Metadata could look like the following:

<KeyDescriptor>
    <ds:KeyInfo>
        <ds:X509Data>
            <ds:X509Certificate>BQUAMCMBgN...XerfXHHEZYZs=</ds:X509Certificate>
        </ds:X509Data>
        <ds:X509Data>
            <ds:X509Certificate>H24a88h7zl...2zo28hH5DK78=</ds:X509Certificate>
        </ds:X509Data>
    </ds:KeyInfo>
</KeyDescriptor>

Although SAML 2.0 does not mandate that the public key be included, I haven't come across any identity providers who do not include the public key in their SAML response. If the public key is not specified with the assertion, then it should be inferable via the identity provider's metadata.

In terms of trusting the public key being sent in the response, the public key must match one that is defined in the identity provider's metadata. These metadata details are usually provided by your customers who want to use SSO to access your application--you will know exactly what public key(s) to be looking for (i.e. you will probably request them to provide you their identity provider's metadata url so you can fetch their metadata and pull down relevant information such as public keys, issuer endpoint, etc).

If the public key supplied with the signature is one that is not specified in the metadata, then the SAML system must generate an error when validating the signature.

8
  • 17
    I think this is an important point, that the certificate in the response must match the certificate in the metadata. Otherwise, I could sign the response with whatever certificate I wanted and send its public key for verification.
    – dana
    Commented Jun 4, 2013 at 19:24
  • 9
    I think this is the best answer, it seems to me the other ones are missing the point that checking the message against the key declared in the message itself isn't giving you any security... You must still check the key in the message is right! (in this case, you must ensure it's in trusted metadata). Commented Jan 29, 2015 at 14:59
  • 5
    Totally agree with the above comments - the certificate passed in the message is worthless by itself because the whole point of signing is to verify that the message is trustworthy. If the message isn't trustworthy, then nor are the bundled certificates.
    – Jez
    Commented Feb 6, 2015 at 12:04
  • @jbindel - thank you! I have a newby question if possible: Does this SAML certificate have to match the current physical certificate, or is it only used to achieve a metadata match? I ask this as I am concerned about the operational impact of an IdP rekeying their certificate - at which point presumably it gets out of sync with the metadata key. If the 2 are tied, then I am concerned re. the operational impact ie. that until both SP and IdP have manually updated the SAML2 key, all SSO will fail, and the consequent impact on SSO users if imperfect technical comms. (apologies if stupid question)
    – Pancho
    Commented Feb 10, 2016 at 11:41
  • 1
    @jbindel, could you please tell me if there exists an official SAML documentation directing how the certificate included in a signature should be validated together with certificates in metadata as you summarized as following: > If the key supplied with the signature is not trusted (not specified in the Metadata in this case), then the SAML system must generate an error when validating the signature.
    – Sam D.
    Commented Feb 5, 2019 at 9:42
9

The public part of the signing certificate is in the SAML message. This is used to check the signature for the token itself, and of course to allow receivers to tell who issued the token and treat it accordingly.

The fact that it's in there is part of the XML digital signature specs, it's not really anything SAML specific. Without the certificate how could you tell where the token came from, and how could you validate it?

XmlDSig does specify other methods, you can identify the signing key by a subject, serial number, hash etc., but this assumes that the receiving party has the public certificate. For SAML this may not be the case, hence the embedding of the public part of the X509 cert.

5
  • 2
    "Without the certificate how could you tell where the token came from, and how could you validate it?" - what are you talking about? In order to trust a signature in a SAML message, you must already have a list of trusted public certificates. You could use the Issuer element and store that issuer's certificate against that, and pick that certificate against which to check the signature for this message.
    – Jez
    Commented Feb 6, 2015 at 12:00
  • 2
    Not true at all Jez. You can trust a certificate issuer, like a CA, without having to trust the individual certificates it issues and without having to keep local copies of every certificate.
    – blowdart
    Commented Feb 17, 2015 at 18:23
  • 5
    blowdart that means you are trusting the saml token signed by any other valid cert issued by CA. It is not impossible to buy one! To ensure your token is coming from the correct source as @Jez mentioned you should already have a list of trusted public certificates.
    – Sun
    Commented Jun 19, 2015 at 12:03
  • 2
    @Sun, incorrect. That's like saying Wells Fargo can impersonate Bank of America if they have the same CA. An X509 certificate has a Subject DN that can be validated for the correct identity. Commented May 11, 2016 at 22:43
  • +1 especially for identifying that this is part of the XML digital signature specification, something that is less than obvious for a novice and crucial for understanding how the messages are actually processed, as pretty much every SAML implementation relies on an XML library to do the heavy lifting.
    – BryKKan
    Commented Apr 4, 2019 at 19:10
0

Identity provider signed the saml response using its own private key. and while registration/SAML metadata exchange phase, Both parties share their public key certificate with each other. Any party can have multiple signing certificate and it is free to use one of them. Corresponding public key already shared with relying party so sharing public key in SAML response is just notification(use this certificate while digital verification) to relying party.

Not the answer you're looking for? Browse other questions tagged or ask your own question.