ASP Core向身份验证令牌添加自定义声明

3
我正在使用openiddict和ASP Identity,尝试在登录时(使用/connect/token端点 - 参见下面我遵循的示例)将"GroupId"作为声明添加到auth token中。 GroupId是我的AplicationUser类中的属性。
我尝试使用IClaimsTransformer,但它似乎很笨重,我无法轻松地从ClaimsTransformationContext获取UserManager。
我应该如何通过DI在我的IClaimsTransformer中获取UserManager或者只是将GroupId添加到在connect/token端点生成的token中?
我遵循了this设置我的网站的示例。这就是我想做的事情:
var groupGuid = User.Claims.FirstOrDefault(c => c.Type == "GroupGuid");
2个回答

7
有几种方法可以实现它:
首先,在您的自定义SignInManager中覆盖CreateUserPrincipalAsync方法:
public override async Task<ClaimsPrincipal> CreateUserPrincipalAsync(ApplicationAdmin user)
{
    var principal = await base.CreateUserPrincipalAsync(user);
    // use this.UserManager if needed
    var identity = (ClaimsIdentity)principal.Identity;
    identity.AddClaim(new Claim("MyClaimType", "MyClaimValue"));            

    return principal;
}

第二种方法是重写自定义的UserClaimsPrincipalFactory的CreateAsync方法:
public override async Task<ClaimsPrincipal> CreateAsync(ApplicationUser user)
{
    var principal = await base.CreateAsync(user);

    var identity = (ClaimsIdentity)principal.Identity;
    identity.AddClaim(new Claim("MyClaimType", "MyClaimValue"));

    return principal;
}

这基本上是相同的,因为SignInManager中的base.CreateUserPrincipalAsync方法内部调用了this.UserClaimsPrincipalFactory()

不要忘记将您的自定义实现添加到服务中:
可以选择:

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddSignInManager<CustomSignInManager>();
}

或者

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, CustomClaimsPrincipalFactory>();
}

1

ASP Core 添加自定义声明到身份验证令牌

在 IdP 签署令牌后,您无法更改令牌,因此无法向令牌添加声明。

我尝试使用 IClaimsTransformer,但这似乎很笨重,我无法轻松地从 ClaimsTransformationContext 访问 UserManager。

我猜你的问题与这个 github issue 有关。总的来说(就我所理解的),如果将 ClaimsTransformer 类注册为单例,并且其中一个依赖项是作用域或瞬态的,则会导致 captive dependency。在这种情况下,您应该使用服务定位器模式来避免俘获依赖项。您的代码可能类似于这样(来自 @PinpointTownes 的评论):

public async Task<ClaimsPrincipal> TransformAsync(ClaimsTransformationContext context) 
{
    var userManager= context.Context.RequestServices.GetRequiredService<UserManager>();
    //
} 

-- 我对你的情况的想法 --

你基本上有两个选项来实现你的目标:

在生成令牌时向令牌添加声明:

大多数情况下,您不需要此方法,但如果您想使用它:

  • 您应该控制IdP,因为这个选项在IdP上是可能的(就我所知,您的IdP和资源服务器相同,因此您可以控制IdP,但这并不总是可能的)。
  • 在使用此选项时,您应注意不一致性,因为声明存储在令牌中,并且不会每次请求都获取。因此,声明的真实值可能与令牌中的声明不同。(我不喜欢用于角色、权限、组等,因为这些声明随时可能更改)。

p.s:我不知道是否可以使用Openiddict向令牌添加声明。

声明转换

实际上,在我发现这种方法之前,我使用HttpContext.Items存储额外的声明,并且它对我很有效。但我认为更好的方法是使用声明转换,它适合您的情况。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接