Reputation: 57
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
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
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
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