JwtSecurityTokenHandler 4.0.0突破性变化?

时间:2014-08-31 15:26:56

标签: asp.net-web-api oauth-2.0 jwt

这是Linqpad中JwtSecurityTokenHandler 4.0.0的简化测试。该代码适用于JwtSecurityTokenHandler 3.0.2,生成并验证了令牌。在4.0.0中,经过必要的更改后,我不断收到SecurityTokenSignatureKeyNotFoundException:IDX10500:签名验证失败。无法解析SecurityKeyIdentifier。显然有些事情发生了变化,或者我做错了什么,新版本更严格。有什么建议吗?

string jwtIssuer = "issuer";
string jwtAudience = "audience";

X509Store store = new X509Store(StoreName.My,  StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
X509Certificate2 cert = store.Certificates.OfType<X509Certificate2>().FirstOrDefault( c => c.SubjectName.Name.Equals("CN=DEV_CERT", StringComparison.OrdinalIgnoreCase));
store.Close();
// Token generation and signing
X509SigningCredentials signingCredentials = new X509SigningCredentials(cert);
JwtSecurityTokenHandler jwtHandler = new JwtSecurityTokenHandler();
IList<System.Security.Claims.Claim> payloadClaims = new List<System.Security.Claims.Claim>() { 
    new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Name , "name"), 
};

#if JWT302
    Lifetime lifetime = new Lifetime(DateTime.UtcNow, DateTime.UtcNow.AddSeconds(24*60*60));
    JwtSecurityToken jwt = new JwtSecurityToken( jwtIssuer, jwtAudience, payloadClaims,  lifetime, signingCredentials);
#else
    JwtSecurityToken jwt = new JwtSecurityToken( jwtIssuer, jwtAudience, payloadClaims, DateTime.UtcNow, DateTime.UtcNow.AddSeconds(24*60*60), signingCredentials);
#endif

string token = jwtHandler.WriteToken(jwt); 

// Token validation
var signingToken = new RsaSecurityToken((RSACryptoServiceProvider)cert.PublicKey.Key);

JwtSecurityTokenHandler jwtHandler2 = new JwtSecurityTokenHandler();

#if JWT302
TokenValidationParameters vp = new TokenValidationParameters() {  
                                        AllowedAudience = jwtAudience, 
                                        ValidIssuer = jwtIssuer,
                                        ValidateIssuer = true
                                        ,SigningToken = signingToken 
                                        };

    var principal  = jwtHandler2.ValidateToken(token, vp);
#else
TokenValidationParameters vp = new TokenValidationParameters() { 
                                        ValidAudience = jwtAudience, 
                                        ValidIssuer = jwtIssuer,
                                        ValidateIssuer = true
                                        ,IssuerSigningToken = signingToken 
                                        };

    SecurityToken validatedToken;

    var principal  = jwtHandler2.ValidateToken(token, vp, out validatedToken);
#endif

2 个答案:

答案 0 :(得分:5)

如果出现以下情况,则抛出此异常:

  1. jwt有一个'小孩'
  2. 运行时无法匹配任何SigningTokens。
  3. 我们调查此问题时,您可以使用委托 TokenValidationParameters.IssuerSigningKeyResolver 直接返回签名时使用的签名密钥。

    要实现此设置:TokenValidationParameters.IssuerSigningkeyResolver为一个函数,它将返回您在TokenValidationParameters.SigningToken中设置的相同键。此委托的目的是指示运行时忽略任何“匹配”语义,只需尝试密钥。

    如果签名验证仍然失败,则可能是一个关键问题。

    如果签名验证没有失败,则运行时可能需要修复。

    如果您可以向我们提供使用该公钥签名的jwt,那将有助于我们进行修复。

    感谢您试一试,对不起麻烦。

答案 1 :(得分:2)

抱歉,您遇到了问题。我们将更多地关注上面的内容,看看可能出现的问题。同时,我建议看看https://github.com/AzureADSamples/WebAPI-ManuallyValidateJwt-DotNet,特别是global.asax.cs - 这是我们以JWT处理程序原始使用为特色的示例。 HTH 诉