JwtSecurityTokenHandler ValidateToken:“签名验证失败。没有提供安全密钥来验证签名”

Posted

技术标签:

【中文标题】JwtSecurityTokenHandler ValidateToken:“签名验证失败。没有提供安全密钥来验证签名”【英文标题】:JwtSecurityTokenHandler ValidateToken: "Signature validation failed. No security keys were provided to validate the signature" 【发布时间】:2021-12-17 21:49:07 【问题描述】:

我在运行下面的代码时遇到了奇怪的行为。

如果它通过测试,一切正常,并且通过的令牌得到验证。 但是当它从 Azure FunctionApp 运行时,它会抛出此异常:“签名验证失败。没有提供安全密钥来验证签名”,尽管 validationParameters 包含 IssuerSigningKeys。

在这两种情况下,GetPublicKeysAsync 的结果是相同的。

public async Task<ClaimsPrincipal> GetClaimsPrincipalFromTokenAsync(string accessToken)
           
    TokenValidationParameters validationParameters = await CreateTokenValidationParametersAsync();
    
    JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
    ClaimsPrincipal principal = tokenHandler.ValidateToken(accessToken, validationParameters, out SecurityToken oAuthSecurityToken);
    return principal;


public static async Task<TokenValidationParameters> CreateTokenValidationParametersAsync()

    var keys = await GetPublicKeysAsync();
    List<SecurityKey> securityKeys = new List<SecurityKey>();
    foreach (JWTPublicKey publicKey in keys)
        securityKeys.Add(GenerateJWTSecurityKey(publicKey.key));

     TokenValidationParameters tokenValidationParameters = new TokenValidationParameters
     
         ValidIssuer = "XXX", 
         ValidAudience = "YYY",

         ValidateIssuer = true,
         ValidateAudience = true,
         ValidateLifetime = true,
         ValidateIssuerSigningKey = true,
         IssuerSigningKeys = securityKeys,
     ;
     return tokenValidationParameters;


private static SecurityKey GenerateJWTSecurityKey(string publicKey)

    var rsa = new RSACryptoServiceProvider(2048);
    rsa.ImportRSAPublicKey(Convert.FromBase64String(publicKey), out _);

    return new RsaSecurityKey(rsa);

有人对检查什么有任何指导吗?谢谢。

【问题讨论】:

我实现了基于this solution 的自定义令牌检查作为解决方法 【参考方案1】:

很高兴paolo-crociati 问题在此SO 线程的帮助下得到解决,该线程发布了 cmets 中提供的建议作为帮助面临相关问题的其他社区成员的答案。

以下是指定数据的RSA签名示例代码。

public override bool VerifySignature (byte[] rgbHash, byte[] rgbSignature);

这是一个示例示例,它演示了如何使用验证签名方法,paolo 已通过该方法为自定义令牌实现了工作。

using System;
using System.Security.Cryptography;

class RSASample


    static void Main()
    
        try
        
            //Create a new instance of RSA.
            using (RSA rsa = RSA.Create())
            
                //The hash to sign.
                byte[] hash;
                using (SHA256 sha256 = SHA256.Create())
                
                    byte[] data = new byte[]  59, 4, 248, 102, 77, 97, 142, 201, 210, 12, 224, 93, 25, 41, 100, 197, 213, 134, 130, 135 ;
                    hash = sha256.ComputeHash(data);
                

                //Create an RSASignatureFormatter object and pass it the 
                //RSA instance to transfer the key information.
                RSAPKCS1SignatureFormatter RSAFormatter = new RSAPKCS1SignatureFormatter(rsa);

                //Set the hash algorithm to SHA256.
                RSAFormatter.SetHashAlgorithm("SHA256");

                //Create a signature for HashValue and return it.
                byte[] signedHash = RSAFormatter.CreateSignature(hash);
                //Create an RSAPKCS1SignatureDeformatter object and pass it the  
                //RSA instance to transfer the key information.
                RSAPKCS1SignatureDeformatter RSADeformatter = new RSAPKCS1SignatureDeformatter(rsa);
                RSADeformatter.SetHashAlgorithm("SHA256");
                //Verify the hash and display the results to the console. 
                if (RSADeformatter.VerifySignature(hash, signedHash))
                
                    Console.WriteLine("The signature was verified.");
                
                else
                
                    Console.WriteLine("The signature was not verified.");
                
            
        
        catch (CryptographicException e)
        
            Console.WriteLine(e.Message);
        
    

有关完整信息,请查看Verify Signature 文档。

【讨论】:

以上是关于JwtSecurityTokenHandler ValidateToken:“签名验证失败。没有提供安全密钥来验证签名”的主要内容,如果未能解决你的问题,请参考以下文章

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

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

JwtSecurityTokenHandler 和 TokenValidationParameters

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

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

为啥我们有两个用于 JWT 令牌 JwtSecurityTokenHandler 和 JsonWebTokenHandler 的类?