使用 HMAC256 验证 JWT Token 时是不是需要将 ValidateIssuerSigningKey 设置为 true?

Posted

技术标签:

【中文标题】使用 HMAC256 验证 JWT Token 时是不是需要将 ValidateIssuerSigningKey 设置为 true?【英文标题】:Is it necessary to set ValidateIssuerSigningKey to true when using HMAC256 for verifying JWT Token?使用 HMAC256 验证 JWT Token 时是否需要将 ValidateIssuerSigningKey 设置为 true? 【发布时间】:2019-04-23 10:56:50 【问题描述】:

我正在使用 AspNet Core 构建 Web api 和 JWT 令牌来验证用户身份。

我看到TokenValidationParametersValidateIssuerSigningKey 属性的默认值为false。

当使用 HMAC256 对称密钥签署和验证令牌时,如果我们将其设置为 true 会有什么不同(在 RSA 的情况下,令牌中没有添加公钥) )?

    services
        .AddAuthentication(options =>
        
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        )
        .AddJwtBearer(cfg =>
        
            cfg.RequireHttpsMetadata = false;
            cfg.SaveToken = true;
            string jwtIssuer = configuration["JwtIssuer"];
            SymmetricSecurityKey securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["JwtKey"]));
            cfg.TokenValidationParameters = new TokenValidationParameters
            
                ValidIssuer = jwtIssuer,
                ValidAudience = jwtIssuer,
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = securityKey,
                ClockSkew = TimeSpan.Zero
            ;
        );

或者只有在使用 RSA 密钥时才需要将 ValidateIssuerSigningKey 设置为 true?

这是该属性的代码级文档:

    //
    // Summary:
    //     Gets or sets a boolean that controls if validation of the Microsoft.IdentityModel.Tokens.SecurityKey
    //     that signed the securityToken is called.
    //
    // Remarks:
    //     It is possible for tokens to contain the public key needed to check the signature.
    //     For example, X509Data can be hydrated into an X509Certificate, which can be used
    //     to validate the signature. In these cases it is important to validate the SigningKey
    //     that was used to validate the signature.
    [DefaultValue(false)]
    public bool ValidateIssuerSigningKey  get; set; 

【问题讨论】:

当您想要检查/测试令牌是否由允许的服务器颁发时,您验证颁发者,如果您不验证颁发者,任何拥有签名密钥的人都可以创建一个对您有效的令牌服务器 @saj 你说的是ValidateIssuerSigningKey 还是ValidateIssuer 属性?后者默认为true,所以我正在验证发行者。 你发现了吗? 【参考方案1】:

根据查看 Microsoft.IdentityModel.Tokens 源代码,我只能找到一个使用 ValidateIssuerSigningKey 布尔属性的地方,这里:

https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/src/Microsoft.IdentityModel.Tokens/Validators.cs

最终导致执行此代码块的原因:

    X509SecurityKey x509SecurityKey = securityKey as X509SecurityKey;
    if (x509SecurityKey?.Certificate is X509Certificate2 cert)
    
        DateTime utcNow = DateTime.UtcNow;
        var notBeforeUtc = cert.NotBefore.ToUniversalTime();
        var notAfterUtc = cert.NotAfter.ToUniversalTime();

        if (notBeforeUtc > DateTimeUtil.Add(utcNow, validationParameters.ClockSkew))
            throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidSigningKeyException(LogHelper.FormatInvariant(LogMessages.IDX10248, notBeforeUtc, utcNow)));

        LogHelper.LogInformation(LogMessages.IDX10250, notBeforeUtc, utcNow);

        if (notAfterUtc < DateTimeUtil.Add(utcNow, validationParameters.ClockSkew.Negate()))
            throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidSigningKeyException(LogHelper.FormatInvariant(LogMessages.IDX10249, notAfterUtc, utcNow)));

        LogHelper.LogInformation(LogMessages.IDX10251, notAfterUtc, utcNow);
    

即该标志仅与 X509 证书相关,以及它们有效的时间段的测试。所以我怀疑它不会影响使用 HMAC256 验证的令牌...除非 HMAC 密钥是从 X509 证书中获得的!

【讨论】:

以上是关于使用 HMAC256 验证 JWT Token 时是不是需要将 ValidateIssuerSigningKey 设置为 true?的主要内容,如果未能解决你的问题,请参考以下文章

Python JWT 库 PyJWT 使用 HS256 签名时遇到问题 - 使用 SHA-256 哈希算法的 HMAC

HMAC 256 与 HMAC 512 JWT 签名加密

JWT(JSON Web Token) Java与.Net简单编码实现

JWT 签名算法 HS256 与 RS256

实战:你用SpringBoot集成JWT来实现一下token验证,可否?

权限管理的几种方案-写备忘