1

我刚开始使用 Identity Server 4。

我正在尝试使用 Client Credentials 授权类型来保护 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:由于客户端凭据未链接到用户,我如何保持记录更改的审计跟踪,例如供应商 X 由 userId 5 更新,等等。

谢谢

4

2 回答 2

2

我明白你的意思了。但是客户端不是用户,因此您不能将角色分配给客户端。

让我们退后一步。资源是您要保护的。在 IdentityServer 中,您可以给资源一个逻辑名称,因为您可以拥有多个属于同一资源一部分的 api。而且,不太明显的是,该资源至少有一个范围。在示例中,资源具有名称“Api1”和“Api1”范围。

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

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

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

在控制器中:

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

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

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

客户的类型并不重要。这适用于客户端凭据授予类型,但也适用于交互式客户端。虽然在这种情况下,访问可以通过用户授权来限制。

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

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

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

于 2020-06-18T08:19:53.057 回答
1

1:如何使用客户端凭据设置基于角色的授权?2:由于客户端凭据未链接到用户,我如何保持记录更改的审计跟踪,例如供应商 X 由 userId 5 更新,等等。

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

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

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

然而,这并不总是最好的。通常,最好将用户身份令牌传递给您的授权服务器以显式处理该验证。这样一来,您就可以避免首先需要 clientId 和 secret。由于您的用户已经通过身份验证,剩下的就是调用进行验证的授权微服务。(例如,对于 IdentityServer,您可能正在使用PolicyServerAuthress 之类的东西。

于 2020-06-25T17:04:09.317 回答