C# 无法验证RS256签名JWT

C# 无法验证RS256签名JWT,c#,.net-core,jwt,keycloak,C#,.net Core,Jwt,Keycloak,我正试图在DotnetWebAPI上实现带签名的JWT(RS256)和KeyClope。在应用程序启动时,我可以看到使用预期的响应内容(如下所示的请求)对KeyClope进行的openid调用 在这里获取jwks_url GET https://localhost:8080/auth/realms/core/.well-known/openid-configuration 从这里拿钥匙 GET https://localhost:8080/auth/realms/core/protocol/o

我正试图在DotnetWebAPI上实现带签名的JWT(RS256)和KeyClope。在应用程序启动时,我可以看到使用预期的响应内容(如下所示的请求)对KeyClope进行的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
然后我通过下面的请求获得一个访问令牌

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,
            };
        });
}
public void配置服务(IServiceCollection服务)
{
services.AddControllers();
var受众=配置[“Jwt:受众”];
var issuer=配置[“Jwt:issuer”];
bool.TryParse(配置[“Jwt:RequireHttpsMetadata”],out var RequireHttpsMetadata);
I配置管理器配置管理器=
新配置管理器(
$“{Configuration[“Jwt:Authority”]}/auth/realms/core/.well-known/openid配置”,
新的OpenIdConnectConfigurationRetriever());
var openIdConfig=
configurationManager.GetConfigurationAsync(CancellationToken.None);
services.AddAuthentication(选项=>
{
options.DefaultAuthenticateScheme=JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme=JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme=JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(选项=>
{
options.SaveToken=true;
options.RequireHttpsMetadata=RequireHttpsMetadata;
options.TokenValidationParameters.IssuerSigningKeys=openIdConfig.SigningKeys;
options.TokenValidationParameters=新的TokenValidationParameters
{
validateisuer=true,
ValidateAudience=true,
ValidateLifetime=true,
ValidisUser=发行人,
勇敢=观众,
ValidateSuersigningKey=true,
};
});
}

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

"The signature key was not found"
签名的验证存在问题

重新检查用户的响应/可访问性

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

使用fiddler,我可以看到正在发出请求,并且响应包含预期的键。我已经验证了访问令牌在jwt.io上是有效的,如果这是你的意思的话。当我之前在jwt.io上检查密钥时,我从未用私钥检查过它。执行此操作后,我收到一条消息,表明这是一个无效的签名。不确定这是否会产生影响,但定义权限(仅用于测试)可能会有所帮助。根据此问题,hm,您可以在分配新实例后尝试设置issuersigningkey(可能会清除)。因此,颠倒这两个选项的顺序。TokenValidationParameters行将issuerSigningKey分配移动到末尾,或移动到TokenValidationParams中,就完成了这一技巧。这不是很明显,因为keydove没有返回观众声明,要求我也必须覆盖
audencevalidator
。谢谢你的帮助!