I have an IdP that wants us to use a custom certificate to sign when we perform SP initiated SSO. For IdP initiated SSO could the certificate in the Response (UseEmbeddedCertificate = true) be used? If UseEmbeddedCertificate is enabled, will the certificate obtained from the CertificateManager be used?
Thanks!
The UseEmbeddedCertificate is only meant for testing purposes. In a production environment you should specify which certificate should be used to perform signature verification. The certificate can either be a .CER file or a certificate in the Windows certificate store. The IdP should supply you with their .CER certificate file. You can either use this file directly or import it into the Windows certificate store.
I may not have completely understood your questions. Please feel free to ask again if I didn’t.
I like using the embedded certificate, even in production. Makes things much simpler. I guess my question is around the certificate file AND the embedded. Can both be used? If not, does the certificate do signing verification when receiving SSO and perform signing when initiating SSO as well?
Thanks!
In SP-initiated SSO you have the option of signing the authn request sent to the IdP.
In this case the certificate/private key specified in your SAML configuration section is used to generate the signature. This certificate/private key is yours not the IdP’s.
When verifying the SAML response or assertion signature the IdP’s certificate is used.
If you specify UseEmbeddedCertificate the IdP certificate embedded in the XML signature will be used. This is perfectly valid for testing purposes. However, in a production environment the problem is that you’re not checking who the embedded certificate is issued to. Someone other than the expected IdP could send you a SAML response signed with their own embedded certificate.
It is much better to configure the partner IdP’s certificate. That way if someone attempts to spoof the IdP the signature verification will fail as they shouldn’t have access to the IdP’s private key.
Hmm, then I think I have a problem. I need to be able to sign the AuthnRequest using a custom certificate to be used for a single IdP.
The problem came because we were using a self-signed cert for our SP. Our IdP requested that we either use a 3rd party signed cert or we create a certificate signing request (CSR) and send it to them to sign. It would be great if we could specify a specific cert to be used for a particular IdP. Any way to do that or add that ability?
Yes, that’s possible. You can also specify your local SP certificate on a per partner IdP basis which overrides the setting in the .
In the following example, the specifies the LocalCertificateFile and LocalCertificatePassword.
These will be used for this particular .
The LocalCertificateFile and LocalCertificatePassword in the will be used for all other entries.
<ServiceProvider Name=“http://localhost/ExampleServiceProvider”
AssertionConsumerServiceUrl=“~/SAML/AssertionConsumerService.aspx”
LocalCertificateFile=“sp.pfx”
LocalCertificatePassword=“password”/>
<PartnerIdentityProvider Name=“http://localhost/ExampleIdentityProvider”
SignAuthnRequest=“false”
WantSAMLResponseSigned=“true”
WantAssertionSigned=“false”
WantAssertionEncrypted=“false”
SingleSignOnServiceUrl=“http://localhost/ExampleIdentityProvider/SAML/SSOService.aspx”
SingleLogoutServiceUrl=“http://localhost/ExampleIdentityProvider/SAML/SLOService.aspx”
PartnerCertificateFile=“idp.cer”
LocalCertificateFile=“just-for-this-idp.pfx”
LocalCertificatePassword=“password”/>
Thanks for the reply. I’m using the certificate manager. Is there a way to use that and accomplish the same as using the configuration you’ve described?
Many thanks!
Yes. The ICertificateManager.GetLocalServiceProviderCertificate includes a partnerIdentityProviderName parameter.
If the partnerIdentityProviderName is the one in question then return a certificate specific to the partner IdP. Otherwise, return the SP’s standard certificate.
///
/// The certificate manager manages X.509 certificates.
///
public interface ICertificateManager {
///
/// Gets the local service provider X.509 certificate.
///
/// The partner identity provider name or null if none.
/// The local service provider X.509 certificate.
///
/// Thrown when the X.509 certificate cannot be retrieved.
///
X509Certificate2 GetLocalServiceProviderCertificate(string partnerIdentityProviderName);
Thanks, I had missed the parameter name that indicates it tying a specific IdP.
Here’s what I have for my certificate manager. I store the certificate in a database so I can data drive things and not have to redeploy. I think I may need to tweak it so that I store the public cert to be used for AddPartnerIdentityProviderCertificate and the private cert for AddLocalServiceProviderCertificate. Does that sound about right?
Thanks!
public class SsoCertificateManager : AbstractCertificateManager
{
public void AddIdPCertificate(Organization org, PartnerIdentityProviderConfiguration idpConfig)
{
var cert = new X509Certificate2(org.SsoCertificate, org.SsoCertificatePassword);
AddPartnerIdentityProviderCertificate(idpConfig.Name, cert);
// Add the custom certificate for this SP specifically for this IdP used to sign.
AddLocalServiceProviderCertificate(idpConfig.Name, cert);
}
}
Yes, that looks correct.
I’m getting an error when attempting to verify the SAML response signature.
I have a custom local SP certificate just for the specific IdP. I also have UseEmbeddedCertificate set to “true” and I’m getting an error that the SAML response isn’t signed.
ComponentSpace.SAML2.Exceptions.SAMLSignatureException: The SAML response isn’t signed. at ComponentSpace.SAML2.InternalSAMLServiceProvider.VerifySAMLResponseSignature(XmlElement samlResponseElement) in c:\Sandboxes\ComponentSpace\SAMLv20\Library\InternalSAMLServiceProvider.cs:line 225
I had this configured:
“WantSAMLResponseSigned”: true,
“WantAssertionSigned”: true,
The signature information in the response looks to be correct.
It could be that the SAML assertion is signed but not the SAML response. Typically either the SAML response or SAML assertion is signed but not both.
Try setting WantSAMLResponseSigned to false and keeping WantAssertionSigned set at true.