登录后不包含 IdentityServer AdditionalClaims

IdentityServer AdditionalClaims not included after login

我正在设置一个新的 IdentityServer 实例作为身份提供者。登录时,我想在我的用户对象上设置一些额外的自定义声明。现在,我正在使用以下代码:

[HttpPost]
public async Task<IActionResult> ExecuteLogin(string returnUrl, string loginId)
{
      TestUser user = Config.GetUsers().Find(x => x.SubjectId == loginId);
      if (user != null)
      {
          var identityServerUser = new IdentityServerUser(user.SubjectId)
          {
             AdditionalClaims = user.Claims
          };

          await HttpContext.SignInAsync(identityServerUser);
          return Redirect(returnUrl);
     }
     else
     {
         return Redirect("Login");
     }
}

我希望 AdditionalClaims 出现在接收应用程序的 User.Claims 对象上,我按如下方式使用它:

[Authorize]
public class HomeController : Controller
{
   public IActionResult Index()
   {
      var claims = User.Claims;
      return View(claims);
   }
}

但是,在视图中只有标准声明是可见的。不是我的额外索赔。

在 IdentityServer 的设置中,我指定了一个可以访问这些声明所在范围的客户端,以及一个具有在 TestUser 中指定的声明类型的 IdentityResource。在接收应用程序中,我指定了我想接收该范围。

为什么我的声明在接收申请中不可见?

您需要在您的客户端中明确映射这些额外声明,使用如下代码:

options.ClaimActions.MapUniqueJsonKey("website", "website");
options.ClaimActions.MapUniqueJsonKey("gender", "gender");
options.ClaimActions.MapUniqueJsonKey("birthdate", "birthdate");

还有这个选项可以设置:

options.GetClaimsFromUserInfoEndpoint = true;

没有说明您使用的是哪种类型的身份验证,但我想您想将声明添加到 access_token 中,从那里可以在 API 上读取它们。

AdditionalClaims on IdentityServerUser 仅添加到您客户端的 cookie 中。

您要做的是创建一个配置文件服务(https://docs.identityserver.io/en/latest/reference/profileservice.html)。

最简单的情况是这样的:

public class ProfileService : IProfileService
{
    private UserService _userService;

    public ProfileService(UserService userService)
    {
        _userService = userService;
    }
            
    public Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        var user = await _userService.GetUserByIdAsync(context.Subject.GetSubjectId());
        context.IssuedClaims.AddRange(user.Claims);
        return Task.FromResult(0);
    }

    public Task IsActiveAsync(IsActiveContext context)
    {
        var user = await _userService.GetUserByIdAsync(context.Subject.GetSubjectId());
        context.IsActive = user.IsActive;

        return Task.FromResult(0);
    }
}

并在Startup.cs中注册:

services.AddIdentityServer()
        .AddProfileService<ProfileService>();

然后可以从 API 一侧的 access_token 读取这些内容(如果这是您想要的,因为问题中不清楚):

var user = User.Identity as ClaimsIdentity;
var claims = user.Claims;