受众无效错误

The audience is invalid error

我有 3 个项目 1- Javascript SPA 2- Web API 项目,3- 带有 EF Core 的 IdentityServer

我开始调试 API 和身份服务器并成功获取 jwt 令牌,但是,当我尝试从具有授权属性的 API 方法获取值时,我收到错误消息:

WWW-Authenticate →Bearer error="invalid_token", error_description="The audience is invalid"

我在身份验证选项中找不到任何关于受众的 属性。这是我在 API 项目

中的配置
app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
        {
            ApiSecret="secret",
            Authority = "http://localhost:5000",
            ApiName="fso.Api",
            RequireHttpsMetadata = false,
        });

还有我的 Config.cs 身份文件

 public class Config
{        
    public static IEnumerable<ApiResource> GetApiResources()
    {
        return new List<ApiResource>
        {                
            new ApiResource()
            {
                Name = "fso.Api",                    
                DisplayName = "feasion API",
                Scopes =
                {
                    new Scope("api1"),
                    new Scope(StandardScopes.OfflineAccess)
                },
                UserClaims =
                {
                    JwtClaimTypes.Subject,
                    JwtClaimTypes.EmailVerified,
                    JwtClaimTypes.Email,
                    JwtClaimTypes.Name, 
                    JwtClaimTypes.FamilyName,
                    JwtClaimTypes.PhoneNumber,
                    JwtClaimTypes.PhoneNumberVerified,
                    JwtClaimTypes.PreferredUserName,
                    JwtClaimTypes.Profile, 
                    JwtClaimTypes.Picture, 
                    JwtClaimTypes.Locale, 
                    JwtClaimTypes.IdentityProvider,
                    JwtClaimTypes.BirthDate, 
                    JwtClaimTypes.AuthenticationTime
                }
            }
        };
    }
    public static List<IdentityResource> GetIdentityResources()
    {
        return new List<IdentityResource>
        {
            new IdentityResources.OpenId(),
            new IdentityResources.Email(),
            new IdentityResources.Profile(),
        };
    }

    // client want to access resources (aka scopes)
    public static IEnumerable<Client> GetClients()
    {
        return new List<Client>
        {
            new Client
            {
                ClientId = "fso.api",
                AllowOfflineAccess=true,
                ClientSecrets =
                {
                    new Secret("secret".Sha256())
                },
                AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,                    
                AllowedScopes =
                {                       
                   StandardScopes.OfflineAccess,                    
                   "api1"
                }
            }
        };
    }
}

有关此声明的内容,请参阅 here

The aud (audience) claim identifies the recipients that the JWT is intended for. Each principal intended to process the JWT MUST identify itself with a value in the audience claim. If the principal processing the claim does not identify itself with a value in the aud claim when this claim is present, then the JWT MUST be rejected....

因此,您的 API 的名称必须存在于 aud 声明中,以便 JWT 在您的 API 中的中间件验证时有效。顺便说一下,您可以使用 jwt.io 查看您的令牌,这有助于理解它。

为了让 IdentityServer 将你的 API 的名字添加到 aud 声明你的客户端代码(它试图从 API 获取资源,因此需要访问令牌)应该从您的 API 请求范围。例如像这样(来自 MVC 客户端):

app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
    Authority = Configuration["IdpAuthorityAddress"],
    ClientId = "my_web_ui_id",
    Scope = { "api1" },

    //other properties removed...
});

为避免错误,应始终在 4 个位置添加受众

  1. 在我的(例如 MVC)客户端中作为自定义范围。
  2. 在 API 应用程序中作为 ApiName
  3. 在 IdentityServer 客户端配置中作为 AllowedScope
  4. 在API资源配置为ApiResource

查看详细信息(以前在 IdentityServer4 wiki 中可用):

在 identityServer4 中配置新的 API 连接时,可能会出现错误:

WWW-Authenticate: Bearer error="invalid_token", 
error_description="The audience is invalid"

为避免错误,应始终在 4 个位置添加受众群体

  1. 在我的(例如 MVC)客户端中作为自定义范围:
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
  Authority = Configuration["IdpAuthorityAddress"],
  ClientId = "my_web_ui_id",
  Scope = { "openid", "profile", "offline_access", "MyApi" },               

//other properties removed for brevity...
});
  1. 在 API 应用程序中作为 ApiName
//Microsoft.AspNetCore.Builder.IdentityServerAuthenticationOptions
var identityServerAuthenticationOptions = new IdentityServerAuthenticationOptions()
{
  Authority = Configuration["Authentication:IdentityServer:Authority"],
  RequireHttpsMetadata = false,
  EnableCaching = false,
  ApiName = "MyApi",
  ApiSecret = "MyApiSecret"
};
  1. 在 IdentityServer 中 \IdentityServerHost\Configuration\Clients.cs (或数据库中相应的客户条目)
var client = new Client
{
  ClientId = clientId,  
  //other properties removed for brevity...   
  AllowedScopes =
  {
    IdentityServerConstants.StandardScopes.OpenId,
    IdentityServerConstants.StandardScopes.Profile,
    //IdentityServerConstants.StandardScopes.Email,
    IdentityServerConstants.StandardScopes.OfflineAccess, "MyApi",
  },
};
  1. 在 IdentityServer \IdentityServerHost\Configuration\Resources.cs(或数据库中相应的 ApiResource 条目)中作为 apiResource.Scopes
var apiResource = new ApiResource
{
  Name = "MyApi",
  ApiSecrets =
  { 
    new Secret("MyApiSecret".Sha256())
  },
  UserClaims =
  {
    JwtClaimTypes.Name,
    JwtClaimTypes.Profile,
  },
};

在 AD 配置部分的应用配置文件中添加“受众”行:

"AzureAd": {
  "Instance": "https://login.microsoftonline.com/",
  "ClientId": "<-- Enter the Client Id -->",
  "Audience": "<-- Enter the Client Id -->",
  "TenantId": "<-- Enter the tenantId here -->"
}

在我的例子中,“ClientId”和“Audience”是相同的。

P.S.: 如果在那之后你会看到

IDW10201: Neither scope or roles claim was found in the bearer token

在 AD 配置中添加另一行:

"AllowWebApiToBeAuthorizedByACL": true

更多

在 IdentityServer 中必须向 jwt 令牌添加声明“aud”。为了在 .AddJwtBearer("Bearer", options => options.Audience="invoice" 下执行此操作并设置 ApiResource

参考Linkhttps://identityserver4.readthedocs.io/en/latest/topics/resources.html#refresources

public static readonly IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
    new ApiResource("invoice", "Invoice API")
    {
        Scopes = { "invoice.read", "invoice.pay", "manage" }
    }        
};
   }