使用身份服务器 4 和客户端凭据授权类型的基于角色的访问

Role based access using identity server 4 and client credentials grant type

我刚开始使用 Identity Server 4。

我正在尝试使用客户端凭据授权类型来保护 API。

我在 IS4 中有一个 API 设置:

    public static IEnumerable<ApiResource> Apis =>
        new List<ApiResource> 
        {
            new ApiResource("myapi", "Test API")
            {
                ApiSecrets = { new Secret("secret".Sha256() )}
            }
        };

我还有以下客户端设置:

    public static IEnumerable<Client> Clients =>
        new List<Client>
        {
            new Client
            {
                ClientId = "testc",
                ClientName= "Test Client",
                AllowedGrantTypes = GrantTypes.ClientCredentials,
                ClientSecrets =
                {
                    new Secret("m2msecret".Sha256())
                },
                AllowedScopes = new List<string>
                {
                    "myapi"
                }
            },
        };

我在 API 中有一个我想保护的控制器:

[Authorize]
public class TestController : ControllerBase {} 

如果我再创建一个令牌请求如下:

        var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
        {
            Address = disco.TokenEndpoint,
            ClientId = "testc",
            ClientSecret = "m2msecret",
            Scope = "myapi",
        });

这允许我调用 API 并访问资源。完美!

但是,我想用一个角色来保护控制器,例如

[Authorize(Roles = "admin")]
public class TestController : ControllerBase {} 

所以我的两个问题是:

1:如何使用客户端凭据设置基于角色的授权?

2:由于客户端凭据不会 link 给用户,我如何保留记录更改的审计跟踪,例如供应商 X 由 userId 5 等更新

谢谢

我明白你的意思了。但是客户不是用户,所以你不能给客户分配角色。

让我们退一步。资源是您要保护的内容。在 IdentityServer 中,你可以给资源一个逻辑名称,逻辑名称是因为你可以有多个 api 作为同一资源的一部分。而且,不太明显的是,该资源至少有一个作用域。在示例中,资源具有名称 'Api1' 和范围 'Api1'。

客户端只有在至少配置了一个允许范围的情况下才能访问资源。因为它是用于访问资源的 api 名称。

要根据范围限制访问,您必须测试令牌中包含的范围。这是关键,而不是使用角色,您应该使用范围匹配的策略。在您的初创公司中:

services.AddAuthorization(option =>
{
    option.AddPolicy("testing", p => p.RequireScope("myapp.test"));
});

在控制器中:

[Authorize("testing")]
public class TestController : ControllerBase {} 

请注意:不受上述策略保护的部分将允许所有至少具有一个资源范围的客户端,无论它是哪个范围。

我建议您将资源分成逻辑部分(范围)并配置客户端以定义哪个客户端可以访问哪个范围(资源的一部分)。

客户的类型无关紧要。这适用于客户端凭据授权类型,也适用于交互式客户端。尽管在那种情况下访问可以通过用户授权来限制。

至于跟踪用户。对于交互式客户端,用户在子声明中可用。通过用户授权,您可以使用角色。

对于客户端凭据流,此类信息应该是请求(数据)的一部分。

对于您的设计,您可以为不同类型的客户端和用户授权使用单独的控制器,它们可以调用相同的服务。

1:如何使用客户端凭据设置基于角色的授权? 2:由于客户端凭据不会 link 给用户,我如何保留记录更改的审计跟踪,例如供应商 X 由 userId 5 等更新

具体而言,用户授权和客户端凭据之间存在差异。用户授权是您的 API 将验证的内容。客户端凭据用于访问其他服务。您不会使用自己的客户端凭据来访问自己的服务。

对于您的具体实施,您可能需要生成大量符合您特定权限情况的策略:

services.AddAuthorization(option =>
{
    option.AddPolicy("PoliyExample", p => p.Require(...));
});

然而,这并不总是最好的。通常,最好将用户身份令牌传递给您的授权服务器以明确处理该验证。这样一来,您就可以避免首先需要 clientId 和 secret。由于您的用户已经通过身份验证,剩下的就是调用执行验证的授权微服务。 (例如,对于 IdentityServer,您可能会使用 PolicyServer or Authress.