0

I have an application that uses the Windows Identity Foundation to enable federated single-sign-on from multiple partners (let's call them Org1, Org2, Org3, etc). My WIF configuration, therefore, contains thumbprints of all the partners' certificates - the config looks like this (irrelevant parts omitted for brevity):

<system.identityModel>
<identityConfiguration>    
  <issuerNameRegistry type="System.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry">
    <trustedIssuers>
      <add name="Org1" thumbprint="...certificate1..." />
      <add name="Org2" thumbprint="...certificate2..." />
      <add name="Org3" thumbprint="...certificate3..." />
    </trustedIssuers>
  </issuerNameRegistry>
</identityConfiguration>

However, I don't understand how to determine which of the certificates was actually used when an incoming token was validated. That is, how do I know whether it was Org1, Org2 or Org3 that has sent me the token? I.e., in the following code:

        var authModule = FederatedAuthentication.WSFederationAuthenticationModule;
        var request = new HttpRequestWrapper(Request);

        if (authModule.CanReadSignInResponse(request, true))
        {
            var principal = Thread.CurrentPrincipal;
            var message = authModule.GetSignInResponseMessage(request);
            var token = authModule.GetSecurityToken(request) as SamlSecurityToken;
            //???
        }

... How can I use the principal/message/token variables (or perhaps some other method entirely) to determine whether it was Org1, Org2 or Org3 that has sent me the token? I know about token.Assertion.Issuer, but this seems to come straight from the token, so it seems like e.g. Org1 can issue a token listing Org2 as the issuer, thus resulting in an impersonation attack. Is there a way to identify the issuing organization securely, based on which certificate was used for token validation?

Eugene Osovetsky
  • 6,443
  • 2
  • 38
  • 59

1 Answers1

0

I managed to find 2 solutions:

METHOD 1:

Create a custom IssuerNameRegistry that derives from System.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, and set it as your name registry (e.g. <issuerNameRegistry type="MyNamespace.MyConfigurationBasedIssuerNameRegistry, My.Assembly.Name">).

In your custom registry, override the GetIssuerName overload that takes both a token and a string (which is the token's issuer according to the token itself).

In this override, call the base GetIssuerName method, and you will get back the name property of the <add thumbprint="..." name="..."> statement for the certificate that was actually used to verify the token signature.

At this point, you have all the information you need (who the token claims to be, and who it is actually from). Compare the two, and return null if the token is impersonated (this will cause WIF to reject the token), or return what you got from the base method otherwise.

If your name property in <add> statements is always the intended token issuer URL, then all this becomes very easy:

class ValidatingConfigurationBasedIssuerNameRegistry : ConfigurationBasedIssuerNameRegistry
{
    public override string GetIssuerName(SecurityToken securityToken, string requestedIssuerName)
    {
        var configuredName = base.GetIssuerName(securityToken, requestedIssuerName);
        return (configuredName == requestedIssuerName) ? configuredName : null;
    }
}

METHOD 2:

As stated in the answers here, you can get to the Claims on Thread.CurrentPrincipal as ClaimsPrincipal, and each Claim has an Issuer property. It turns out that this property will always be set to the name property in the <add thumbprint="..." name="..."> statement for the certificate that was actually used to verify the token signature.

This is a bit inconvenient - if you're processing a WS-Federation sign-in response, there's no way of knowing where this particular response's token came from - you're looking at the current Identity where the claims could potentially come from multiple sources. But I think in most realistic scenarios this should be sufficient.

Community
  • 1
  • 1
Eugene Osovetsky
  • 6,443
  • 2
  • 38
  • 59