Subject: Cannot verify signature of encrypted SAML assertion (when the assertion, not the response, is signed)
Date: 2021-06-02 21:49:26
From: leech
Source: cannot-verify-signature-encrypted-saml-assertion-when-assertion-not-response-signed


I'm using ComponentPro.Saml.dll in a service provider, with Azure as the identity provider, and I cannot verify the signature of an encrypted assertion.

Consider 3 scenarios:

1. A response **is** signed, and the assertion within the response **is** also signed.
2. A response **is** signed, and the assertion within the response is **not** signed.
3. A response is **not** signed, but the assertion within the response **is** signed.

When the assertion is **not** encrypted, in all 3 of the above scenarios, Response.IsSigned() returns true and Response.Validate(X509Certificate2) also returns true.

This is unexpected in scenario 3, because the response is **not** signed - only the assertion is signed. It appears that the ComponentPro.Saml2.Response class exposes the assertion's signature through Response.SignatureElement if no /Response/Signature element exists in the received XML. This is very confusing - when looking at Response.ToString(), I thought that Azure was signing incorrectly; only by pulling the raw SAMLResponse form field from the HttpRequest object did I realize that it's the Response object that is behaving unexpectedly.

When the assertion **is** encrypted, Response.IsSigned() and Response.Validate(X509Certificate2) only return true in scenarios 1 and 2. In scenario 3, Response.IsSigned() returns false. This is the behaviour I actually expected, but there's a problem in that while Response.GetEncryptedAssertion().Decrypt(X509Certificate2).IsSigned() returns true in scenario 3, Response.GetEncryptedAssertion().Decrypt(X509Certificate2).Validate(X509Certificate2) seems to always return false. (And I know that there isn't a problem with the signing/encryption certificates, because I can successfully decrypt the assertion and verify the signature at the SAML response level.)

So unless I've misunderstood something, it appears that there are a couple of bugs:

1. Response.SignatureElement exposes the assertion's signature (and Response.IsSigned() returns true) even when the response itself is **not** signed.

2. Response.GetEncryptedAssertion().Decrypt(X509Certificate2).Validate(X509Certificate2) always returns false, even when an encrypted *assertion* **is** correctly signed in a *response* that is **not** signed.

Issue #2 is most critical, because I cannot find any way to verify the signature of an encrypted assertion when the response itself is not signed. Can you please tell me what I'm doing wrong, or - if it is actually a bug - whether there's a work-around and/or when the issue can be fixed?

P.S. I am aware that I could configure Azure to always sign the response and never sign the assertion, and then I would be able to verify the response's signature regardless of whether the assertion was encrypted or not; however, the identity provider's configuration is not always within my control. I am also aware that encrypting the assertion is not necessary in an HTTPS environment, but, again, whether or not the assertion is encrypted is not always within my control. I really need to be able to verify the signature of an encrypted assertion when the response itself is not signed.


Note: This question has been asked on the Q&A forum of Thang Dang's fraudulent ComponentPro brand
If you purchased anything from ComponentPro, you have been scammed. Contact the payment processor
who sold you the license and ask for your money back.

Back to ComponentPro Q&A Forum Index