gpt4 book ai didi

c# - IdentityServer4 + JWT : Define user property for "sub" claim

转载 作者:行者123 更新时间:2023-11-30 18:14:58 25 4
gpt4 key购买 nike

我将 IdentityServer4 与 JWT 和 ASP.NET Core 2 一起用于身份验证。我也在使用 IdentityUser<long> ( long 主键而不是 string )作为用户模型,因为大查询的性能问题。这会产生这样的效果,即我在编码的访问 token 内获得了默认情况下将公开提供给公众的有序用户 ID。使用 GUID 作为默认类型是有原因的,因此我只想向公众提供一个 GUID,而不是一个有序的整数。为此,我有一个额外的 ExternalID GUID 类型的列,将在创建用户时生成一次。

现在我需要替换 sub默认情况下声明整数 Id与我的 ExternalId 一起使用(GUID)。

我尝试使用 ProfileService与以下 GetProfileDataAsync方法

public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var sub = context.Subject.GetSubjectId();
var user = await _userManager.FindByIdAsync(sub);
var principal = await _claimsFactory.CreateAsync(user);

var claims = principal.Claims.Where(
claim =>
claim.Type != "sub" &&
context.RequestedClaimTypes.Contains(claim.Type))
.ToList();

claims.Add(new Claim("sub", user.ExternalId.ToString()));

context.IssuedClaims = claims;
}

启动.cs

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

但这没有任何效果。 IssuedClaims似乎被忽略了。 token 仍然包含 Idsub不 claim ExternalId .

我错过了什么?这是正确的做法吗?

最佳答案

尽管我在上面发表了评论,但我还是能够让它工作,并且没有发现任何副作用。至少我还没有看到。您将需要在两个位置替换子声明。

首先像这样扩展 Microsoft.AspNetCore.Identity.UserClaimsPrincipleFactory。这将在收到 Id token 之前修改声明。

public sealed class MyUserClaimsPrincipalFactory : UserClaimsPrincipalFactory<ApplicationUser, ApplicationRole>
{
public MyUserClaimsPrincipalFactory(UserManager userManager, RoleManager<ApplicationRole> roleManager, IOptions<IdentityOptions> optionsAccessor)
: base(userManager, roleManager, optionsAccessor)
{}

protected override async Task<ClaimsIdentity> GenerateClaimsAsync(ApplicationUser user)
{
var identity = await base.GenerateClaimsAsync(user);
var sub = identity.FindFirst("sub");
if (sub == null)
return identity;

identity.RemoveClaim(sub);
identity.AddClaim(new Claim("sub", user.GlobalUid.ToString()));

return identity;
}
}

第二个像这样扩展 IdentityServer4.Services.DefaultClaimsService。这将解决我在上面评论中提到的问题。

public class MyClaimsService : DefaultClaimsService
{
private readonly UserManager _userManager;

public MyClaimsService(IProfileService profile, ILogger<DefaultClaimsService> logger, UserManager userManager) : base(profile, logger)
{
_userManager = userManager;
}

protected override IEnumerable<Claim> GetStandardSubjectClaims(ClaimsPrincipal subject)
{
var sub = subject.GetSubjectId();
var user = _userManager.FindByIdAsync(sub).GetAwaiter().GetResult();
var claims = new List<Claim>
{
new Claim(JwtClaimTypes.Subject, user?.GlobalUid.ToString() ?? sub),
new Claim(JwtClaimTypes.AuthenticationTime, subject.GetAuthenticationTimeEpoch().ToString(), ClaimValueTypes.Integer),
new Claim(JwtClaimTypes.IdentityProvider, subject.GetIdentityProvider())
};

claims.AddRange(subject.GetAuthenticationMethods());

return claims;
}
}

添加Microsoft.AspNetCore.Identity时,通过身份生成器将UserClaimsPrincipleFactory添加到服务集合

 services.AddIdentity<ApplicationUser, ApplicationRole>(options =>
{
options.User.RequireUniqueEmail = true;
options.SignIn.RequireConfirmedEmail = true;
})
.AddClaimsPrincipalFactory<MyUserClaimsPrincipalFactory>()

然后像这样将 ClaimsService 添加为 transient

services.AddTransient<IClaimsService, MyClaimsService>();    

现在您的所有声明都应该作为您为所有 token 提供的属性返回。如果您对此有任何问题,请告诉我,因为它对我来说仍处于测试阶段。

关于c# - IdentityServer4 + JWT : Define user property for "sub" claim,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49356850/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com