【问题标题】:How to add additional claims for MVC client with IdentityServer4如何使用 IdentityServer4 为 MVC 客户端添加附加声明
【发布时间】:2020-03-27 10:16:23
【问题描述】:

我正在使用 here 找到的 IdentityServer4 "AspNetCoreAndApis" 示例应用程序

它有一个令牌服务器和一个 MVC 客户端应用程序。

身份服务器项目使用他们的演示服务器设置了一个外部 OIDC 身份验证提供程序 - https://demo.identityserver.io/

在到达MvcClient中的受保护端点后,被重定向到本地身份服务器,选择演示服务器并进行身份验证,然后到达本地身份服务器的ExternalController回调。在这一点上,我想向用户发出额外的声明,并让它们在MvcClient 中可用。

回调中有代码添加additionalLocalClaims 并发出cookie。我尝试添加另一个声明:

var additionalLocalClaims = new List<Claim>();
additionalLocalClaims.Add(new Claim("TestKey", "TestValue"));
await HttpContext.SignInAsync(user.SubjectId, user.Username, provider, localSignInProps, additionalLocalClaims.ToArray());

但是当用户到达HomeControllerMvcClient 时,这个声明已经不存在了。

我想我没有正确理解在哪里使用了哪种身份验证方案,以及相关 cookie 的功能。

编辑:

针对下面的第一条评论,我尝试将声明附加到请求的范围,但仍然没有运气 - 这是内存中的资源存储:

public static IEnumerable<ApiResource> Apis
    {
        get
        {
            var apiResource = new ApiResource("api1", "My API");
            apiResource.UserClaims.Add("TestKey");
            var resources = new List<ApiResource>
            {
                apiResource
            };
            return resources;
        }
    }

MvcClient 被允许使用 api1 范围,并请求它。

【问题讨论】:

  • 应该可以,但是您还必须允许用户通过将其附加到用户请求的范围来接收声明。例如。如果这旨在作为访问令牌声明,您可以将声明类型添加到 api1 ApiResource(假设用户正在请求 api1 范围)。
  • 我真的认为这会奏效,但恐怕它没有。我编辑了我的问题以包含您的建议。
  • 要理解的几件事可能会帮助您解决它:首先是 - 正如我的第一条评论所暗示的那样 - 您可以按照自己的方式添加任何合理数量的声明,但它们应该被视为 可用声明。 发布的实际声明将取决于您的 IS4 配置(范围、API、客户端、身份资源等)。
  • 其次是identity-tokens和access-tokens的区别。第一个由您的 UI 接收,通常以明文 JWT 的形式出现,并且可供您的 UI 使用。第二个是针对您的目标 API 的,通常(或至少应该被视为)对您的 UI 不透明。您只需将其从 UI 传递到 API 即可获得访问权限,而且通常只有 API 才能看到实际声明。如果您正在寻找第一个出现的新声明,则应将其添加到匹配的 IdentityResource,而不是 ApiResource。
  • 顺便说一句,您在添加时也将您的声明称为“TestKey”,但将“CustomKey”添加到 ApiResource...

标签: asp.net-core identityserver4


【解决方案1】:

您的客户端 MVC 可以从 ID 令牌或 UserInfo 端点获取用户的自定义声明。

要向 ID 令牌添加声明,您可以设置客户端的配置 :AlwaysIncludeUserClaimsInIdToken 。但不建议将所有用户声明都包含在 ID Token 中,关注 ID Token 的大小。

更好的解决方案是让您的客户端应用程序从 UserInfo 端点获取用户声明:

public class MyProfileService : IProfileService
{
    public MyProfileService()
    { }

    public Task GetProfileDataAsync(ProfileDataRequestContext context)
    {

        var claims = new List<Claim>()
        {

            new Claim("TestKey", "TestValue")
        };
        context.IssuedClaims.AddRange(claims);
        return Task.CompletedTask;
    }

    public Task IsActiveAsync(IsActiveContext context)
    {
        // await base.IsActiveAsync(context);
        return Task.CompletedTask;
    }
}

在 DI 注册:

services.AddTransient<IProfileService, MyProfileService>();

IProfileService 服务可用于向 ID 令牌、访问令牌和 UserInfo 端点添加声明。默认情况下,自定义声明不会涉及使用 IProfileService 的 ID 令牌事件,原因如上所述 - ID 令牌大小。因此,您可以使用 OIDC 中间件配置让您的客户端应用程序从 UserInfo 端点获取声明:

options.Scope.Add("profile");
options.GetClaimsFromUserInfoEndpoint = true;
options.ClaimActions.MapJsonKey("TestKey", "TestKey");

以上代码会添加 OIDC profile 权限以从端点获取声明,并使用 ID Token 向 connect/userinfo 端点发送请求,并获取声明并将名为 TestKey 的声明映射到您客户的声明原则并保存饼干。现在您可以在 MVC 中使用 User.Claims 获取声明。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-14
    • 2017-07-26
    相关资源
    最近更新 更多