4

In .net Web API, how can I configure Thinktechture Saml2SecurityTokenHandler to use a X509 Certificate to handle an encrypted SAML2 security token (decrypt it before validating).

The token was encrypted by Identity Server by configuring the RP to use the certificate for encrypting.

Below is the working configuration (without handling an encrypted token) taken from Thinktechture samples:

  #region IdentityServer SAML
  authentication.AddSaml2(
                issuerThumbprint: Constants.IdSrv.SigningCertThumbprint,
                issuerName: Constants.IdSrv.IssuerUri,
                audienceUri: Constants.Realm,
                certificateValidator: X509CertificateValidator.None,
                options: AuthenticationOptions.ForAuthorizationHeader(Constants.IdSrv.SamlScheme),
                scheme: AuthenticationScheme.SchemeOnly(Constants.IdSrv.SamlScheme));
  #endregion
RonyK
  • 2,644
  • 5
  • 32
  • 42
  • have you seen [this](https://github.com/thinktecture/Thinktecture.IdentityModel.45/issues/54#issuecomment-18537067) – itsho Aug 15 '13 at 07:41
  • @itsho: My issue is different than the one discussed in that thread, as I'm trying to handle an encrypted security token. When I disable the encryption in Identity Server, it is handled correctly. Thanks. – RonyK Aug 15 '13 at 07:56

2 Answers2

1

To enable encrypted tokens with Web API, I found this helpful: http://www.alexthissen.nl/blogs/main/archive/2011/07/18/using-active-profile-for.aspx

Towards the end you'll see code setting the ServiceTokenResolver property on the Configuration property of a SecurityTokenHandlerCollection using a X509 certificate from the LocalMachine store. The Configuration property is a SecurityTokenHandlerConfiguration, which is one of the parameters to an overload of the AddSaml2 extension method in AuthenticationConfigurationExtensionsCore.cs from the ThinkTecture.IdentityModel source. The below is what I ended up with.

var registry = new ConfigurationBasedIssuerNameRegistry();
registry.AddTrustedIssuer(Constants.IdSrv.SigningCertThumbprint, Constants.IdSrv.IssuerUri);

var handlerConfig = new SecurityTokenHandlerConfiguration();
handlerConfig.AudienceRestriction.AllowedAudienceUris.Add(new Uri(Constants.Realm));
handlerConfig.IssuerNameRegistry = registry;
handlerConfig.CertificateValidator = GetX509CertificateValidatorSetting();

X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certificates = store.Certificates;
X509Certificate2Collection matchingCertificates = certificates.Find(
    X509FindType.FindBySubjectDistinguishedName,
    "CN=RPTokenCertificate", false);
X509Certificate2 certificate = certificates[0];

List<SecurityToken> serviceTokens = new List<SecurityToken>();
serviceTokens.Add(new X509SecurityToken(certificate));
SecurityTokenResolver serviceResolver =
    SecurityTokenResolver.CreateDefaultSecurityTokenResolver(
        serviceTokens.AsReadOnly(), false);
handlerConfig.ServiceTokenResolver = serviceResolver;

authentication.AddSaml2(handlerConfig, 
    AuthenticationOptions.ForAuthorizationHeader(SamlScheme), 
    AuthenticationScheme.SchemeOnly(SamlScheme));

Hope it helps.

JonathanN
  • 672
  • 7
  • 17
  • There is still something missing for me, when I choose to encrypt the token (by choosing an Encrypting Certificate in the IDP RP Admin page). The mapping between the token handler doesn't occur because the Authorization header of the received request is NULL. The authorization header appears in the invalid headers array of the request http headers property. – RonyK Oct 21 '13 at 14:34
  • Using a System.Net.Http.HttpClient with ThinkTecture.IdentityModel’s SetToken extension method, I get the following Authorization header over the wire: Authorization: SAML – JonathanN Oct 22 '13 at 13:33
  • Solved. It seems that my problem was invalid characters in the encrypted token. After base64 encoding the token (using thinktechture's HeaderEncoding) the solution described in this answer worked like a charm. For a description of the encoding issue see http://stackoverflow.com/questions/19497841/authorization-header-in-null-when-setting-its-value-to-an-encrypted-saml-2-token. – RonyK Oct 22 '13 at 14:35
0

got this answer from someone:

    public ClaimsIdentity DecryptToken(string token)
    {
        XmlReader rdr = XmlReader.Create(new StringReader(token));

        SecurityTokenHandlerConfiguration config = new SecurityTokenHandlerConfiguration();
        config.AudienceRestriction.AllowedAudienceUris.Add(new Uri("urn:yourRP"));
        config.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None;
        config.RevocationMode = X509RevocationMode.NoCheck;

        ConfigurationBasedIssuerNameRegistry inr = new ConfigurationBasedIssuerNameRegistry();
        X509Certificate2 cert = new X509Certificate2(pathToSigningCert);
        inr.AddTrustedIssuer(cert.Thumbprint, "STS Name");

        config.IssuerNameRegistry = inr;
        config.CertificateValidator = System.IdentityModel.Selectors.X509CertificateValidator.None;

        SecurityTokenHandlerCollection handlers = System.IdentityModel.Tokens.SecurityTokenHandlerCollection.CreateDefaultSecurityTokenHandlerCollection(config);

        if (handlers.CanReadToken(rdr))
        {
            var tmpToken = handlers.ReadToken(rdr);
            var claimsIds = handlers.ValidateToken(tmpToken);
            var id = claimsIds.FirstOrDefault();
        }
    }

not sure if this helps.

what did you use as the issuer name? the name of the website you setup in IIS? or the value you entered in the "Site ID" field in the "General Configuration" page of the IdentityServer's Administration section?

Sam
  • 11
  • 3