为登录设置 IdentityServer4 Cookies 的正确方法,用于 API 授权的 JWT 令牌

xxS*_*rdy 7 authorization jwt asp.net-core identityserver4

我们有一个应用程序使用 IdentityServer4 cookie 授权方案进行用户登录,如下所示:

services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = "Cookies";
            options.DefaultChallengeScheme = "oidc";
        })
        .AddCookie("Cookies")
        .AddOpenIdConnect("oidc", options =>
        {
            options.SignInScheme = "Cookies";
            options.Authority = <local IDP server with IdentityServer4>;
            options.ClientId = <ClientId>;
            options.ClientSecret = <secret>
            options.ResponseType = "code id_token";
            options.SaveTokens = true;
            options.GetClaimsFromUserInfoEndpoint = true;
            options.Scope.Add("openid");
            options.Scope.Add("profile");
            options.Scope.Add("offline_access");
        })
Run Code Online (Sandbox Code Playgroud)

IDP 上的客户端如下所示:

new Client
{
    ClientId = <ClientID>,
    ClientName = <ClientName>,
    AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
    RequireConsent = true,
    ClientSecrets = { new Secret(<secret>.Sha256()) },
    AllowOfflineAccess = true,
    RedirectUris = { "http://" + ip + "/signin-oidc" },
    PostLogoutRedirectUris = { "http://" + ip + "/signout-callback-oidc" },
    AllowedScopes = {
            IdentityServerConstants.StandardScopes.OpenId,
            IdentityServerConstants.StandardScopes.Profile
        }
};
Run Code Online (Sandbox Code Playgroud)

我们还有一个位于 /api/...

目标是向 API 添加 JWT Bearer Token 授权。为此,我添加了以下代码:

        .AddJwtBearer(jwtOptions =>
        {
            jwtOptions.Authority = <local IDP server with IdentityServer4>;
            jwtOptions.Audience = <ClientID>
            jwtOptions.SaveToken = true;
        })
Run Code Online (Sandbox Code Playgroud)

API受到保护

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
Run Code Online (Sandbox Code Playgroud)

登录后,我得到了令牌

await HttpContext.GetTokenAsync("access_token");
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试使用该令牌访问 API 时,出现以下错误:

AuthenticationFailed: IDX10214: 受众验证失败。受众:'http://localhost:50059/resources'。不匹配:validationParameters.ValidAudience:ClientID 或validationParameters.ValidAudiences:'null'。

实际上,当我使用 jwt.io 解码令牌时,aud设置为http://localhost:50059/resources,而 ClientID 显示为新字段'client_id': '<ClientID>'

到目前为止我发现的内容表明,aud它始终设置<idp>/resources为访问令牌,并且 API 访问是通过令牌内的范围声明来处理的。但是,我不明白如何正确设置。

有谁知道问题出在哪里以及我如何解决它?

xxS*_*rdy 5

事实证明,解决方案非常简单。正如怀疑的那样,它与范围有关。我早些时候试图解决这个问题,但它一直说“无效范围”......因为我从未创建过 API 资源,呃。

  1. 在您的 IDP 服务器中创建新的 API 资源 new ApiResource("api-name", "API Name")
  2. 将新的 API 资源作为 AllowedScope 添加到客户端 client.AllowedScopes.Add("api-name")
  3. 在 OpenIdConnect 身份验证中请求范围 options.Scopes.Add("api-name")
  4. 将 Audience(或 ApiName,如果使用 IdentityServer 身份验证处理程序)设置为 API 资源 options.Audience = "api-name"options.ApiName = "api-name"

有了这个,我现在可以使用访问令牌来访问我的 API。