是什么原因导致JwtSecurityTokenHandler.ValidateToken抛出“ IDX10503:签名验证失败”。密钥何时有效?

时间:2019-05-23 12:21:26

标签: asp.net-core jwt-auth

我有一个暴露API端点的ASP.NET core 2.2应用程序。该端点受一个简单的JWT令牌保护,该令牌仅关心主题,过期和签名(使用共享机密的SHA256)。

当我从.net核心客户端调用终结点时,它工作正常。

我现在正试图从Delphi客户端调用相同的代码,但是服务器拒绝了这些令牌,我无法弄清原因:这两个令牌看起来和我一样,并且都通过了jwt.io的验证测试

服务器端令牌验证代码:

    private static TokenValidationParameters GetValidationParameters(byte[] key)
    {
        return new TokenValidationParameters()
        {
            ValidateLifetime = true,
            LifetimeValidator = (DateTime? notBefore, DateTime? expires, SecurityToken securityToken, TokenValidationParameters validationParameters) =>
            {
                // Cutom validity validation
                DateTime current = DateTime.UtcNow; // get a single value for "now"
                // check if the token expiration is valid and if it doesn't expire 
                bool value = (expires.HasValue) && (notBefore.HasValue) && // both "expires" and "notBefore" must be set
                              (expires >= current) && // "expires" must not be in the past
                              (expires <= current.AddMinutes(5)) && // "expires" must not be any further than 5 minutes in the future
                              (notBefore <= current); // notBefore must be in the past or present
                return value;
            },
            RequireExpirationTime = true, 
            // the token has no audience or issuer so ignore these
            ValidateAudience = false, 
            ValidateIssuer = false,   
            IssuerSigningKey = new SymmetricSecurityKey(key)
        };
    }

    private bool ValidateToken(string authToken, byte[] key)
    {
        var tokenHandler = new JwtSecurityTokenHandler();
        var validationParameters = GetValidationParameters(key);

        // This will raise an exception if the security token is invalid
        try
        {
            tokenHandler.ValidateToken(authToken, validationParameters, out SecurityToken validatedToken);
        }
        catch (SecurityTokenException e) // this will happen if the token is properly formated but invalid (signature, validity)
        {
            logger.LogInformation("Invalid token received: {1}", e.Message);
            return false;
        }
        return true;
    }

错误发生在tokenHandler.ValidateToken调用上。永远不会调用令牌到期验证代码。

样本令牌

通过C#应用程序(通过验证):

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2NjM2MDQ1My1CMDJCLUU5MTEtODM5Qy1BMEE4Q0QzQUNCRjgiLCJuYmYiOjE1NTg2MTMzOTQsImV4cCI6MTU1ODYxMzY5NCwiaWF0IjoxNTU4NjEzMzk0fQ.nso4xnllNc-rXfn5riOWv5fZjNeJMgoQbyXeOltDYb0

在我的Delphi应用程序中(失败):

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI2NjM2MDQ1My1CMDJCLUU5MTEtODM5Qy1BMEE4Q0QzQUNCRjgiLCJpYXQiOjE1NTg2MTYxNTgsIm5iZiI6MTU1ODYxNjE1OCwiZXhwIjoxNTU4NjE2NDU4fQ.vB_gotDk1JGiiDWPT0t6TR471Av4r-LXSgc3zab7EaU

报告的错误:

IDX10503: Signature validation failed. Keys tried: 'Microsoft.IdentityModel.Tokens.SymmetricSecurityKey , KeyId: 
'.
Exceptions caught:
 ''.
token: '{"typ":"JWT","alg":"HS256"}.{"sub":"66360453-B02B-E911-839C-A0A8CD3ACBF8","iat":1558616158,"nbf":1558616158,"exp":1558616458}'.

两个令牌都受到相同的共享机密(b64编码)保护:

NdFCOQReqUk0mxTqI7psd9JrVjgE7bdPVfjILEa4dzE=

(所有这些数据均来自本地测试应用程序,因此,毫无疑问会产生此问题)

2 个答案:

答案 0 :(得分:0)

我找到了问题,而问题出在我自己身上。

简短的回答:Delphi令牌无效,因为生成签名的代码已被窃听。

我没有注意到这一点,因为每次更改密钥时,JWT.IO都会重新生成令牌签名,因此它始终显示“签名已验证”,因为我的测试例程是“从VisualStudio复制令牌,将其粘贴到JTW调试器中,然后粘贴密钥”,该密钥实际上从未真正验证过原始令牌。

答案 1 :(得分:0)

我得到了这个确切的错误,并花了很长时间试图找出原因。

这是我为仍在寻找它的人提供的正式答案。

在 C# 或 VB 中进行验证时,您必须考虑各种编码。

Dim symmetricKey = (New Guid(secret)).ToByteArray() 'This array encoding is used by .NET

Dim symmetricKeyUTF8 = (Text.Encoding.UTF8.GetBytes(secret)) 'This is used by Javascript and our Postman example

Dim issuerSigningKeys = New List(Of SecurityKey) From {New SymmetricSecurityKey(symmetricKey), New SymmetricSecurityKey(symmetricKeyUTF8)}

还要始终检查秘密是否相同,无论它多么明显。