The 'K' man
The 'K' man

Reputation: 57

IDX11008: This method is not supported to validate a 'jwt' use the method: ValidateToken(String, TokenValidationParameters, out SecurityToken)

This used to work...

Back when... I had a custom securityTokenHandler. I updated to version 3.02 version of this, I was able to remove the custom handler and just reference the JwtSecurityTokenHandler directly.

<securityTokenHandlers>
  <add type="System.IdentityModel.Tokens.JwtSecurityTokenHandler,
             System.IdentityModel.Tokens.Jwt" />
  <securityTokenHandlerConfiguration>
    <certificateValidation certificateValidationMode="PeerTrust" />
  </securityTokenHandlerConfiguration>
</securityTokenHandlers>

That seemed like an improvement. So I've been using that since.

Now I updated to 4.0.0 and I receive this error...

[NotSupportedException: IDX11008: This method is not supported to validate a 'jwt' use the method: ValidateToken(String, TokenValidationParameters, out SecurityToken).]
   System.IdentityModel.Tokens.JwtSecurityTokenHandler.ValidateToken(SecurityToken token) +46
   System.IdentityModel.Tokens.SecurityTokenHandlerCollection.ValidateToken(SecurityToken token) +73
   System.IdentityModel.Services.TokenReceiver.AuthenticateToken(SecurityToken token, Boolean ensureBearerToken, String endpointUri) +120
   System.IdentityModel.Services.WSFederationAuthenticationModule.SignInWithResponseMessage(HttpRequestBase request) +493
   System.IdentityModel.Services.WSFederationAuthenticationModule.OnAuthenticateRequest(Object sender, EventArgs args) +364
   System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +136
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +69

Looking at things, the ValidateToken() method is completely deprecated. So... I'm wondering how do I call ValidateToken(String, TokenValidationParameters, out SecurityToken) through passive redirect from the web.config? Do I have to wrap it in a custom handler again, or do I need to do something different?

Thanks

Upvotes: 0

Views: 1873

Answers (3)

Willy Van den Driessche
Willy Van den Driessche

Reputation: 1759

We had the same problem. We wrapped the standard handler to support the method:

public override ReadOnlyCollection<ClaimsIdentity> ValidateToken( 
                                                      SecurityToken token)
{
   ClaimsPrincipal validated = ValidateToken(token as JwtSecurityToken, 
                                             validationParameters);
   var result = new ReadOnlyCollection<ClaimsIdentity>(
                       validated.Identities.ToList());
   return result;
}

In our case we read the validation parameters from a configuration file. (We did this by overriding public override void LoadCustomConfiguration(XmlNodeList nodeList), in which we defined our own format for the validation parameters. This allows us to put them in the standard System.IdentityModel configurations ...

Upvotes: 0

Mike
Mike

Reputation: 550

I had the same issue. Instead of creating a custom handler, I just reverted back to version 3.0.0.0 of the System.IdentityModel.Tokens.Jwt and everything started working.

Upvotes: 0

Richie
Richie

Reputation: 525

Yes, there are breaking changes. In case anyone else runs into this, as of version 4.0.2.202250711 from Nuget, you'll need to do something similar to the following:

public class CustomTokenSecurityHandler : System.IdentityModel.Tokens.JwtSecurityTokenHandler
{
    private const string KeyName = "http://somesite.com/url";
    private const string ValidIssuerString = "http://somesite.com/url";

    public override System.Collections.ObjectModel.ReadOnlyCollection<System.Security.Claims.ClaimsIdentity> ValidateToken(SecurityToken token)
    {
        var idConfig = System.IdentityModel.Configuration.SystemIdentityModelSection.Current.IdentityConfigurationElements.GetElement("");

         var validationParameters = new TokenValidationParameters()
        {
            ValidAudience = (idConfig.AudienceUris.Cast<AudienceUriElement>().First()).Value
        };

         // set up valid issuers
         if ((validationParameters.ValidIssuer == null) &&
             (validationParameters.ValidIssuers == null || !validationParameters.ValidIssuers.Any()))
         {
             validationParameters.ValidIssuers = new List<string> { ValidIssuerString };
         }
         // and signing token.
         if (validationParameters.IssuerSigningToken == null)
         {
             var resolver = (NamedKeyIssuerTokenResolver)this.Configuration.IssuerTokenResolver;
             if (resolver.SecurityKeys != null)
             {
                 IList<SecurityKey> skeys;
                 if (resolver.SecurityKeys.TryGetValue(KeyName, out skeys))
                 {
                     var tok = new NamedKeySecurityToken(KeyName, "id", skeys);
                     validationParameters.IssuerSigningToken = tok;
                 }
             }
         }

        var tokenString = (token as JwtSecurityToken);
         ClaimsPrincipal validated = base.ValidateToken(tokenString.RawData, validationParameters, out token);
         var result = new ReadOnlyCollection<ClaimsIdentity>(validated.Identities.ToList());
         return result;
    }


}

The key difference to the other provided answer is this

var tokenString = (token as JwtSecurityToken);
ClaimsPrincipal validated = base.ValidateToken(tokenString.RawData, validationParameters, out token);
var result = new ReadOnlyCollection<ClaimsIdentity>(validated.Identities.ToList());

The ValidateToken method now only accepts 3 parameters, not 2. You'll have to provide the actual token string, the validation parameters, and SecurityToken object as reference.

You can also populate the validation parameters by reading directly from the System.Identity config section in the web.config (see code above).

Upvotes: 3

Related Questions