IdentityServer4 LocalApi with custom policy in .NET Core 3.1

自古美人都是妖i 提交于 2021-02-20 05:06:53

问题


I'm trying to use the "LocalApi" feature of IdentityServer4 with some custom Policies.

I have an API (hosted on the same application instance as IdentityServer4) that is divided into three parts (Server, Manager, Product) and for three clients (Server, Manager, Product). Client can only call the devoted part of the API and I would do this with Policies based on scopes.

So I have the following:

Starup:

services.AddLocalApiAuthentication(); // Add API hosted on same application than IdentityServer
services.AddAuthorization(options =>
    {
        options.AddPolicy("Manager", policy =>
        {
            //policy.RequireClaim("scope", configuration.GetValue<string>("EchinoLoginApiManagerScopeOptions:Name"));
            policy.RequireClaim("scope", "local_api_manager_scope");
            policy.RequireClaim("scope", IdentityServerConstants.LocalApi.ScopeName);
        });

        options.AddPolicy("Server", policy =>
        {
            //policy.RequireClaim("scope", configuration.GetValue<string>("EchinoLoginApiServerScopeOptions:Name"));
            policy.RequireClaim("scope", "local_api_server_scope");
            policy.RequireClaim("scope", IdentityServerConstants.LocalApi.ScopeName);
        });

        options.AddPolicy("Product", policy =>
        {
            //policy.RequireClaim("scope", configuration.GetValue<string>("EchinoLoginApiProductScopeOptions:Name"));
            policy.RequireClaim("scope", "local_api_product_scope");
            policy.RequireClaim("scope", IdentityServerConstants.LocalApi.ScopeName);
        });
    });

And my ApiResource

new ApiResource
     {
         Name = IdentityServerConstants.LocalApi.ScopeName,
         Scopes =
         {
             new Scope()
             {
                 Name = IdentityServerConstants.LocalApi.ScopeName,
                 DisplayName = IdentityServerConstants.LocalApi.ScopeName,
             },
             new Scope()
             {
                 Name = "local_api_product_scope",
                 DisplayName = echinoLoginApiProductScopeOptions.DisplayName,
                 UserClaims = echinoLoginApiProductScopeOptions.UserClaims
             },
             new Scope()
             {
                 Name = "local_api_manager_scope",
                 DisplayName = echinoLoginApiManagerScopeOptions.DisplayName,
                 UserClaims = echinoLoginApiManagerScopeOptions.UserClaims
             },
             new Scope()
             {
                 Name = "local_api_server_scope",
                 DisplayName = echinoLoginApiServerScopeOptions.DisplayName,
                 UserClaims = echinoLoginApiServerScopeOptions.UserClaims
             }
         }
     }

And finally my server client

new Client
     {
         ClientId = echinoServerOptions.Id,
         ClientName = echinoServerOptions.Name,

         ClientSecrets =
         {
             new Secret(echinoServerOptions.Secret.Sha256())
         },

         AllowedGrantTypes = GrantTypes.ClientCredentials,
         //AllowedScopes = AddLocalApiScope(echinoServerOptions.AllowedScopes)
         AllowedScopes = { "IdentityServerApi", "server_scope", "local_api_server_scope" }
     },

So in my controller I use [Authorize(Policy = "Server")] but I always have an authentication failed. If I use [Authorize(LocalApi.PolicyName)] it's working but then I don't have my custom policy.

The payload of the JWT token is the following:

{
  "nbf": 1582632694,
  "exp": 1582636294,
  "iss": "https://localhost:44334",
  "aud": [
    "IdentityServerApi",
    "EchinoLoginApi"
  ],
  "client_id": "EchinoServer",
  "scope": [
    "IdentityServerApi",
    "local_api_server_scope",
    "server_scope"
  ]
}

I must be missing something but I can't found what.

Can anybody give me a hand?


回答1:


For local apis, you should use [Authorize(LocalApi.PolicyName)] with your custom policy together.

[Authorize("productpolicy")]
[Authorize(LocalApi.PolicyName)]
[ApiController]
[Route("api/[controller]")]
public class ProductController : ControllerBase
{...

Or you can handle it in another way:

options.AddPolicy(ClientLocalScopes.AuthenticationAuthorization, policy =>
    {
        policy.AddAuthenticationSchemes(IdentityServerConstants.LocalApi.AuthenticationScheme);
        policy.RequireAuthenticatedUser();
// write your code here
    });


来源:https://stackoverflow.com/questions/60394565/identityserver4-localapi-with-custom-policy-in-net-core-3-1

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!