Certificate issue in SSO

102 Views Asked by At

Im using itfoxtec in order to build a saml identity provider and i copy the code of this repo : https://github.com/ITfoxtec/ITfoxtec.Identity.Saml2/tree/master/test/TestIdPCore

when i use the example on this repo with the project testwebappcore everything works correctly but when i try to configure github enterprise in order to establish an sso mechanism with TestIdPCore idp provider i get an issue this is the github configuration : enter image description here

the certificate is the content of the itfoxtecrootcertificate.crt file in the testwebappcore project

i already add the relying party metadata of the github organization

enter image description here

2

There are 2 best solutions below

0
Joel Coehoorn On

We can see the full code for this issue here:

https://github.com/ITfoxtec/ITfoxtec.Identity.Saml2/blob/master/test/TestIdPCore/Controllers/AuthController.cs

And scrolling down to line 247 we can narrow things down to this excerpt:

if (relyingParty != null) 
{
    rpConfig.SignatureValidationCertificates.AddRange(relyingParty.SignatureValidationCertificates);
    if (relyingParty.EecryptionCertificates?.Count() > 0)
    {
        rpConfig.EncryptionCertificate = relyingParty.EecryptionCertificates.LastOrDefault();
    }
}

We know relyingParty itself is not null, or the code would not have reached the offending line. Therefore, the SignatureValidationCertificates property MUST be null. So we need to either set a valid certificate as part of our relying party configuration, or change this code to do an additional null check.

Looking further near line 48 in the file we see this:

var relyingParty = await ValidateRelyingParty(ReadRelyingPartyFromLoginRequest(httpRequest));
var saml2AuthnRequest = new Saml2AuthnRequest(GetRpSaml2Configuration(relyingParty));

Following the code further, when end up here, near line 257:

private async Task<RelyingParty> ValidateRelyingParty(string issuer)
{
    // Create a cancellation token for each Relying Party call
    await Task.WhenAll(settings.RelyingParties.Select(rp => LoadRelyingPartyAsync(rp, new CancellationTokenSource(1 * 1000))));

    return settings.RelyingParties.Where(rp => rp.Issuer != null && rp.Issuer.Equals(issuer, StringComparison.InvariantCultureIgnoreCase)).Single();
}

So the configuration is provided via the settings object. Going even a little further, this is in turn given as argument to the controller constructor on line 262. I believe this item is included via the appsettings.json file, and going one final level deeper it downloads the it from the relying party's MetaData URL directly.

Therefore, either the Metadata URL is incorrect, GitHub is not providing a signature verification certificate (which is very much NOT good practice), or the certificate is not provided via the metadata.


From here, the correct fix is to find out for certain what certificate GitHub is doing for signature validation, and make sure your IdP is able to know about that. This will likely involve changing the controller code. What that looks like, exactly, is outside of my area, as I've only used this library one time, and then only as relying party instead of an identity provider.

Another option is adding a conditional check around signature validation certificate, similar to the EecryptionCertificates.

Either way, remember this part of the repo is sample code to provide an example of how your own IdP_ might look, and not necessarily a complete IdP to be used verbatim. But the new conditional check, at least, would look something like this:

if (relyingParty != null) 
{
    if (relyingParty.SignatureValidationCertificates?.Count() > 0)
    {
        rpConfig.SignatureValidationCertificates.AddRange(relyingParty.SignatureValidationCertificates);
    }
    if (relyingParty.EecryptionCertificates?.Count() > 0)
    {
        rpConfig.EncryptionCertificate = relyingParty.EecryptionCertificates.LastOrDefault();
    }
}

This should fix the immediate error, but will probably NOT fully solve the problem. I expect there is later code that will also assume the presence of at least one signature validation certificate, where you'll need to add another conditional expression to check for null. But at least know you'll get a new error to show you where that is, and should have some idea on how to work around it.

Additionally, the original code is the way it is for a reason, and again: it's exceptionally poor practice to use unvalidated SAML signatures. You might pursue an option that allows GitHub to include a signature validation certificate.

0
Anders Revsgaard On

The Relying Party SignatureValidationCertificates is read from the relying party metadata in line 280.

rp.SignatureValidationCertificates = entityDescriptor.SPSsoDescriptor.SigningCertificates

I think the relying party metadata do not contain a signing certificate. The signing certificate is only requeued do to logout. Depending on your scenario you can safely change your code to accept an SP/RP metadata without a certificate.