JwtSecurityTokenHandler 4.0.0 重大变化?

Posted

技术标签:

【中文标题】JwtSecurityTokenHandler 4.0.0 重大变化?【英文标题】:JwtSecurityTokenHandler 4.0.0 Breaking Changes? 【发布时间】:2014-10-24 22:48:46 【问题描述】:

这是 Linqpad 中 JwtSecurityTokenHandler 4.0.0 的简化测试。该代码适用于 JwtSecurityTokenHandler 3.0.2,生成并验证了令牌。在 4.0.0 中,经过必要的更改后,我不断收到 SecurityTokenSignatureKeyNotFoundException: IDX10500: Signature validation failed。无法解析 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

【问题讨论】:

【参考方案1】:

在以下情况下会引发此异常:

    jwt 有一个“孩子” 运行时无法匹配任何 SigningToken。

在我们调查该问题时,您可以使用委托 TokenValidationParameters.IssuerSigningKeyResolver 直接返回签名密钥以在检查签名时使用。

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

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

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

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

感谢您试一试,麻烦您了。

【讨论】:

在审查中,如果 jwt 中存在“孩子”,新的匹配算法将不会验证签名。由于您使用 X509 签名,因此 jwt 中将出现 x5t。这将与 RSA 密钥不匹配。而是尝试添加 X509SecurityKey 或 X509SecurityToken。 我尝试添加一个孩子无济于事.. 将重复测试。我可以提供我正在使用的证书、令牌和代码(作为 Linqpad 脚本或控制台应用程序,让我知道)。您可以通过 gmail 直接给我发电子邮件给 rmbrunet。 这是添加小孩后的全部例外 SecurityTokenSignatureKeyNotFoundException:IDX10500:签名验证失败。无法解析 SecurityKeyIdentifier: 'SecurityKeyIdentifier (IsReadOnly = False, Count = 2, Clause[0] = X509ThumbprintKeyIdentifierClause(Hash = 0x6A780AF6E7838FF74783ACA9487DDB6433A98DD2), Clause[1] = System.IdentityModel.Tokens.NamedKeySecurityKeyIdentifierClause )' :"JWT","alg":"RS256","kid":"6A780AF6E7838FF74783ACA9487DDB6433A98DD2","x5t":"angK9ueDj_dHg6ypSH3bZDOpjdI"."unique_name":"name","iss":"issuer","aud" :"audience","exp":1409757052,"nbf":1409670652 使用 X509SecurityKey 而不是 RsaSecurityToken(如您所建议的)验证通过。【参考方案2】:

抱歉,您遇到了问题。我们将更多地关注上面的内容,看看可能出了什么问题。同时,我建议查看https://github.com/AzureADSamples/WebAPI-ManuallyValidateJwt-DotNet,尤其是 global.asax.cs - 这是我们使用 JWT 处理程序的原始使用的示例。 高温高压 五、

【讨论】:

我打开了这个问题:github.com/AzureAD/…我们会看看。

以上是关于JwtSecurityTokenHandler 4.0.0 重大变化?的主要内容,如果未能解决你的问题,请参考以下文章

JwtSecurityTokenHandler 返回小写声明类型

JWTSecurityTokenHandler.ValidateToken() 啥时候真正有效?

JwtSecurityTokenHandler().WriteToken(token) 在托管环境中抛出错误

JwtSecurityTokenHandler 和 TokenValidationParameters

JwtSecurityTokenHandler.ValidateToken 抛出 Lifetime 验证失败异常

JwtSecurityTokenHandler().ValidateToken() :: 签名验证失败...在此上下文中不支持 sha256