令牌无效 - 观众 'empty' 无效

Invalid Token - The audience 'empty' is invalid

我在 ASP.NET 核心 3.1 项目上有以下 Identity Server 4 配置:

services
  .AddIdentityServer(y => {
    y.Events.RaiseErrorEvents = true;
    y.Events.RaiseInformationEvents = true;
    y.Events.RaiseFailureEvents = true;
    y.Events.RaiseSuccessEvents = true;
  })
  .AddDeveloperSigningCredential()
  .AddInMemoryPersistedGrants()
  .AddInMemoryIdentityResources(Config.IdentityResources())
  .AddInMemoryApiResources(Config.ApiResources())
  .AddInMemoryApiScopes(Config.GetApiScopes())
  .AddInMemoryClients(Config.Clients)
  .AddProfileService<ProfileService>()
  .AddAspNetIdentity<User>();

Config如下:

public static class Config {

  public static List<ApiResource> ApiResources() {
    return new List<ApiResource> { 
      new ApiResource("api", "API Resource")
    };
  }

  public static List<ApiScope> ApiScopes() {
    return new List<ApiScope> { 
      new ApiScope("api", "API Scope") 
    };
  }

  public static List<IdentityResource> IdentityResources() {
    return new List<IdentityResource> { 
      new IdentityResources.OpenId(),
      new IdentityResources.Profile(),
      new IdentityResources.Email() 
    };
  }   

  public static List<Client> Clients() {
    return new List<Client> { 
      new Client {
        ClientId = "mvc",
        ClientName = "MVC Client",
        AllowedGrantTypes = GrantTypes.ClientCredentials,
        ClientSecrets = { new Secret("Secret".Sha256()) }
        AllowedScopes = { 
          IdentityServerConstants.StandardScopes.OpenId,
          IdentityServerConstants.StandardScopes.Profile, 
          IdentityServerConstants.StandardScopes.Email, 
          IdentityServerConstants.StandardScopes.OfflineAccess,
          "api"
        }         
      }
    };
  }

}

在 API 我有:

  services
    .AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
    .AddIdentityServerAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme, x => {
      x.ApiName = "api";
      x.ApiSecret = "Secret"
      x.Authority = Config.AuthorityUrl;
      x.RequireHttpsMetadata = true;
      x.EnableCaching = true;
      x.CacheDuration = TimeSpan.FromMinutes(20);
    });

我使用带 OAuth2 的 Insomnia 客户端调用了一个 API 端点:

我能够获取访问令牌,但是在调用 API 时出现错误:

Bearer error="invalid_token", error_description="The audience 'empty' is invalid"

我使用 JWT 检查了访问令牌,得到以下信息:

页眉

{
  "alg": "HS256",
  "kid": "A1042705E52832C676596F36BB1898AB",
  "typ": "at+jwt"
}

有效载荷

{
  "nbf": 1598478410,
  "exp": 1598482010,
  "iss": "https://localhost:5000",
  "client_id": "mvc",
  "jti": "23525FF997FD4D71E13C786A7AD07B5D",
  "iat": 1598478410,
  "scope": [
    "api"
  ]
}

缺少 aud。但我需要它吗?阅读 IS4 文档后,我尝试添加:

.AddIdentityServer(y => {
  y.EmitStaticAudienceClaim = true;

现在访问令牌有 aud 字段,但它的值不是 api。不应该吗?

"aud": "https://localhost:5000/resources"

调用 API 时出现错误:

Bearer error="invalid_token", error_description="The audience 'https://localhost:5000/resources' is invalid"

我阅读了文档和 IS4 示例,但找不到解决方案。

我错过了什么?

您需要做的是将 ApiScope 与 APIRespource 连接起来,以使 api 成为所需的范围。当范围和 api 未“连接”时,https://localhost:5000/resources aud 声明是一般受众。

在您的 API 定义中,您需要像本例中那样做一些事情(查看下面的作用域 属性)

var invoiceApi = new ApiResource()
{
    Name = "invoice",   //This is the name of the API
    Description = "This is the invoice Api-resource description",
    Enabled = true,
    DisplayName = "Invoice API Service",
    Scopes = new List<string> { "shop.admin", "shop.employee" },
};

有关使用的通用资源范围的详细信息,请参阅此link

它说:

When using the scope-only model, no aud (audience) claim will be added to the token, since this concept does not apply. If you need an aud claim, you can enable the EmitStaticAudience setting on the options. This will emit an aud claim in the issuer_name/resources format. If you need more control of the aud claim, use API resources.

您可以尝试将 EmitStaticAudience 选项设置为 false

你也可以忽略令牌中的两个受众。