无法验证 RS256 签名的 JWT

Posted

技术标签:

【中文标题】无法验证 RS256 签名的 JWT【英文标题】:Unable to validate RS256 signed JWT 【发布时间】:2021-03-02 01:29:33 【问题描述】:

我正在尝试在 dotnet webapi 上与 KeyCloak 一起实现签名的 JWT (RS256)。在应用启动时,我可以看到对 keycloak 的 openid 调用具有预期的响应内容(请求如下所示)。

在此处获取 jwks_url

GET https://localhost:8080/auth/realms/core/.well-known/openid-configuration

从这里获取密钥

GET https://localhost:8080/auth/realms/core/protocol/openid-connect/certs

然后我得到一个带有以下请求的 access_token

POST https://localhost:8080/auth/realms/core/protocol/openid-connect/token
Content-Type: application/x-www-form-urlencoded

grant_type=password&client_id=admin-cli&username=jim&password=foobar

然后我测试以下端点

[ApiController]
[Route("/")]
public class AppController : ControllerBase

    [Authorize]
    [HttpGet]
    public OkObjectResult Get()
    
        return Ok("This is the secured page");
    

带着这个请求

GET https://localhost:5001
Authorization: Bearer MY_TOKEN 

但我总是收到 401

HTTP/1.1 401 Unauthorized
Content-Length: 0
Date: Wed, 18 Nov 2020 17:41:28 GMT
Server: Kestrel
Www-Authenticate: Bearer error="invalid_token", error_description="The signature key was not found"

签名密钥(第三个“块”)确实存在于令牌中。下面是 JWT 验证代码。我错过了什么吗?

public void ConfigureServices(IServiceCollection services)

    services.AddControllers();

    var audience = Configuration["Jwt:Audience"];
    var issuer = Configuration["Jwt:Issuer"];
    bool.TryParse(Configuration["Jwt:RequireHttpsMetadata"], out var requireHttpsMetadata);

    IConfigurationManager<OpenIdConnectConfiguration> configurationManager =
        new ConfigurationManager<OpenIdConnectConfiguration>(
            $"Configuration["Jwt:Authority"]/auth/realms/core/.well-known/openid-configuration",
            new OpenIdConnectConfigurationRetriever());
    var openIdConfig =
        configurationManager.GetConfigurationAsync(CancellationToken.None).Result;

    services.AddAuthentication(options =>
        
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
        )
        .AddJwtBearer(options =>
        
            options.SaveToken = true;
            options.RequireHttpsMetadata = requireHttpsMetadata;
            options.TokenValidationParameters.IssuerSigningKeys = openIdConfig.SigningKeys;
            options.TokenValidationParameters = new TokenValidationParameters
            
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,

                ValidIssuer = issuer,
                ValidAudience = audience,
                ValidateIssuerSigningKey = true,
            ;
        );

【问题讨论】:

【参考方案1】:

由于 JWT 持有签名(又名第三块),我会解释该消息

"The signature key was not found"

签名验证存在问题。

重新检查响应/可访问性

GET https://localhost:8080/auth/realms/core/protocol/openid-connect/certs

【讨论】:

使用提琴手我可以看到正在发出的请求,并且响应包含预期的键。我已经验证了 access_token 在 jwt.io 上是有效的,如果这就是你的意思的话。 当我之前检查 jwt.io 上的密钥时,我从未使用私钥检查过它。这样做后,我会收到消息说它是一个无效的签名。 不确定它是否会有所作为,但根据这个问题定义权限(仅用于测试)可能会有所帮助***.com/questions/58563661/… hm,您可以在分配新实例后尝试设置 issuersigningkey(可能会被清除)。所以颠倒两个options.TokenValidationParameters行的顺序 将 issuerSigningKey 分配移动到最后,或者移动到 TokenValidationParams 中就可以了。这不是很明显,因为 Keycloak 没有返回受众声明,这要求我还必须覆盖 AudienceValidator。感谢您的帮助!

以上是关于无法验证 RS256 签名的 JWT的主要内容,如果未能解决你的问题,请参考以下文章

在 Knock (rails) 中验证用 RS256 签名的 JWT 令牌

.NET:RS256 签名的 JWT 中的签名无效

Jwt介绍

Jwt介绍

如何在 Azure API 管理中使用 validate-jwt 策略验证使用 RS256 算法签名的 JWT

django rest框架使用jwt RS256解码签名错误