【问题标题】:Bearer error - invalid_token - The signature key was not found承载错误 - invalid_token - 未找到签名密钥
【发布时间】:2020-02-22 02:37:59
【问题描述】:

我有一个与 .Net Core 2.2 API 后端接口的 Angular 7 应用程序。这是与 Azure Active Directory 的接口。

在 Angular 7 方面,它正在通过 AAD 正确进行身份验证,并且我得到了一个有效的 JWT,正如在 jwt.io 上验证的那样。

在 .Net Core API 方面,我创建了一个简单的测试 API,上面有 [Authorize]

当我从 Angular 调用此方法时,添加 Bearer 令牌后,我得到(如 Chrome 调试工具、网络选项卡、“标题”中所示):

WWW-Authenticate: Bearer error="invalid_token", error_description="The 未找到签名密钥”

带有HTTP/1.1 401 Unauthorized

简单的测试 API 是:

    [Route("Secure")]
    [Authorize]
    public IActionResult Secure() => Ok("Secure works");

Angular 调用代码也很简单:

    let params : any = {
        responseType: 'text',
        headers: new HttpHeaders({
            "Authorization": "Bearer " + token,
            "Content-Type": "application/json"
        })
    }

    this.http
        .get("https://localhost:5001/api/azureauth/secure", params)
        .subscribe(
            data => { },
            error => { console.error(error); }
        );

如果我删除 [Authorize] 属性并将其作为来自 Angular 的标准 GET 请求调用它可以正常工作

我的 Startup.cs 包含:

        services
            .AddAuthentication(AzureADDefaults.AuthenticationScheme)
            .AddAzureADBearer(options => this.Configuration.Bind("AzureAd", options));

所有选项都在 appsettings.json 中正确设置(例如 ClientId、TenantId 等),options 这里按预期填充。

【问题讨论】:

  • 您是如何获得访问令牌的?听起来令牌可能是 Microsoft Graph API 令牌。
  • @juunas 我在 Azure AD 中注册了一个应用程序,并且有一个 ClientID、TenantID 和特定于应用程序的机密,这些机密被传递到 Azure 管理控制台中提供的正确端点。这是一个有效的 JWT。看起来这最终可能会与应用程序中的现有授权方案发生冲突。在这个角度上工作。
  • 运气好吗?我也面临同样的问题。
  • @PatrickI 有同样的问题吗?你找到解决办法了吗?

标签: c# angular asp.net-core jwt azure-active-directory


【解决方案1】:

我的核心 API 使用不同的服务配置(并且可以正常工作:)):

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  .AddJwtBearer(options =>
  {
    Configuration.Bind("JwtBearer", options);
  }

您确定您传递的是访问令牌而不是 id_token?令牌中的aud 声明是否与您的 API 配置的 clientid 完全相同?您可能希望在选项中添加一些事件,以查看您收到的内容以及验证失败的位置。

【讨论】:

  • 访问令牌在 jwt.io 上得到很好的验证......粘贴我的秘密让我得到一个“签名验证”。在那里正确解码。也许我应该改用AddJwtBearer 来尝试这个……我正在使用微软的库和AddAzureADBearer……我假设选项是相同的。除了安全 API 上的默认 [Authorize] 属性之外,您是否指定了任何其他内容?
  • 不,只是授权。我假设您的意思是“粘贴公钥”,而不是“粘贴我的秘密”,对吗?令牌可能具有有效的签名,但不适用于 API - aud 声明是否与您的 API 所期望的相同?
【解决方案2】:

可能有两个原因:

  1. 您可能错过了注册服务:
services.AddAuthorization(auth =>
            {
                auth.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
                    .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme‌​)
                    .RequireAuthenticatedUser().Build());
            });

或者 2. 您可能错过了为“IssuerSigningKey”键赋值,如下所示

validate.TokenValidationParameters = new TokenValidationParameters()
                                        {
                                            ValidateAudience = true,
                                            ValidAudience = "Audience",
                                            ValidateIssuer = true,
                                            ValidIssuer = "http://localhost:5000",
                                            RequireExpirationTime = false,
                                            ValidateIssuerSigningKey = true,
                                            IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("abcdefghi12345"))

                                        });

这解决了我的问题

【讨论】:

  • 第二个解决了我的问题,谢谢
【解决方案3】:

如果您使用的 SignedOutCallbackPath/SignUpSignInPolicyId 政策 ID 与作为 tfp/acr 在令牌中传递的政策 ID 不同,也会发生这种情况。

【讨论】:

    【解决方案4】:

    我有一个独特的场景,希望这会对某人有所帮助。

    我正在构建一个启用了 Windows 协商身份验证的 API(.NET Core 5.0,从 IIS 运行)并通过不支持协商身份验证的 XUnit 使用 CustomWebApplicationFactory (see documentation for CustomWebApplicationFactory) 对 API 进行单元测试。

    出于单元测试的目的,我告诉CustomWebApplicationFactory 使用“UnitTest”环境(ASPNETCORE_ENVIRONMENT 变量)并专门将逻辑编码到我的应用程序 Startup.cs 文件中,只为“UnitTest”环境添加 JWT 身份验证.

    我遇到了这个错误,因为我的 Startup.cs 配置没有我用来创建令牌的签名密钥(下面的IssuerSigningKey)。

    if (_env.IsEnvironment("UnitTest"))
    {
      // for unit testing, use a mocked up JWT auth, so claims can be overridden
      // for testing specific authentication scenarios
      services.AddAuthentication()
        .AddJwtBearer("UnitTestAuth", opt =>
        {
          opt.Audience = "api://local-unit-test";
          opt.RequireHttpsMetadata = false;
          opt.TokenValidationParameters = new TokenValidationParameters()
          {
            ClockSkew = TokenValidationParameters.DefaultClockSkew,
            ValidateAudience = true,
            ValidateIssuer = true,
            ValidateIssuerSigningKey = true,
            ValidAudience = "api://local-unit-test",
            ValidIssuer = "unit-test",
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("abcdefghijklmnopqrstuvwxyz123456"))
          };
        });
    } else {
      // Negotiate configuration here...
    }
    

    无论ValidateIssuerSigningKeytrue 还是false,我仍然收到“invalid_token”401 响应,与 OP 相同。我什至尝试指定一个自定义 IssuerSigningKeyValidator 委托来始终覆盖结果,但也没有运气。

    WWW-Authenticate: Bearer error="invalid_token", error_description="找不到签名密钥"

    当我将IssuerSigningKey 添加到TokenValidationParameters 对象时(当然匹配我在单元测试中生成令牌时使用的密钥),一切都按预期工作。

    【讨论】:

      【解决方案5】:

      对我来说,出现此错误是因为 appsettings.json 中的 URL 不正确。我修复了它,现在可以正常工作了。

      【讨论】:

        【解决方案6】:

        我遇到了同样的问题。我错过了权限..确保权限和 api 名称现在正确,启动文件中配置服务中的这段代码对我有用:

        services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
                        .AddIdentityServerAuthentication( x =>
                        {
                            x.Authority = "http://localhost:5000"; //idp address
                            x.RequireHttpsMetadata = false;
                            x.ApiName = "api2"; //api name
                        });
        

        【讨论】:

        • 添加 Authority 拯救了我的一天!我使用services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(x => { x.Authority = "<my_authority>"; }),如果没有Authority,它将无法工作。
        • 这不是在 JWT Bearer 设置之上使用 IdentityServer 吗?
        【解决方案7】:
        1. 验证您为请求 jwt 令牌而发送的值(例如:grant_type、client_secret、scope、client_id 等)
        2. 确保您使用的是适当的令牌。就是这样!

        这是我的错误: 我正在使用 Postman,并请求一个令牌并将其设置为变量“Var_Token1”:

        pm.environment.set("Var_Token1", pm.response.json().access_token);
        

        但是当我需要将令牌用于最终请求时,我选择并使用了错误的令牌 (Var_Token2):

        Authorization: Bearer {{Var_Token2}}
        

        【讨论】:

          【解决方案8】:

          我遇到了这个问题,这是由于 jwtOptions.Authority 未在配置中设置造成的。

          如果您正在使用:

          services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
                      .AddIdentityServerAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme,
          

          并且 jwtOptions.Authority 设置为 null 或 "" 你可以得到这个错误信息。

          【讨论】:

            猜你喜欢
            • 2020-10-08
            • 2020-06-04
            • 1970-01-01
            • 1970-01-01
            • 2022-07-27
            • 2018-06-04
            • 1970-01-01
            • 2021-04-06
            • 1970-01-01
            相关资源
            最近更新 更多