身份服务器配置文件服务中的声明更改未反映在身份验证 Cookie 中
Claim change in Identity Server's ProfileService is not reflected in Authentication Cookie
使用 ASP.NET Core 3.1 和 Identity Server 4 我从 SPA 开始登录过程。
登录后,我对 IS4 应用程序身份验证 cookie 有以下声明:
sub 1
AspNet.Identity.SecurityStamp RRHNY65RQMUHTXXSIZKT2YORA3QQ2WAC
role Admin
preferred_username info@example.com
name info@example.com
email info@example.com
email_verified true
amr pwd
idp local
auth_time 1598736198
为什么 name
声明将电子邮件作为其价值?
然后我实现了 ProfileService 以用实际用户名替换 name
声明。
当我检查水疗中心的索赔时,更换已经完成...
但在 IS4 应用程序上,身份验证 Cookie 仍会收到电子邮件,如 name
声明的那样。
为什么?
身份令牌中的声明是否正确?
如果它在 ID-token 中是正确的,那么您可能在 ASP.NET 核心应用程序中实施了一些声明转换。
问题似乎出在 ASP.NET Core 3.1 如何定义声明。
然后我实施 UserClaimsPrincipalFactory
来更新 name
声明:
public class UserClaimsPrincipalFactory : UserClaimsPrincipalFactory<User> {
public UserClaimsPrincipalFactory(UserManager<User> userManager, IOptions<IdentityOptions> optionsAccessor) : base(userManager, optionsAccessor) { }
public async override Task<ClaimsPrincipal> CreateAsync(User user) {
ClaimsPrincipal principal = await base.CreateAsync(user);
ClaimsIdentity identity = (ClaimsIdentity)principal.Identity;
Claim claim = identity.FindFirst("name");
if (claim != null)
identity.RemoveClaim(claim);
identity.AddClaim(new Claim("name", user.Name));
return principal;
}
}
现在身份验证 Cookie 和令牌具有相同的声明。
使用 IdentityServer4 的 ProfileService
仅更改令牌上的声明:
public class ProfileService : IProfileService {
private readonly IUserClaimsPrincipalFactory<User> _claimsFactory;
private readonly UserManager<User> _userManager;
public ProfileService(UserManager<User> userManager, IUserClaimsPrincipalFactory<User> claimsFactory) {
_userManager = userManager;
_claimsFactory = claimsFactory;
}
public async Task GetProfileDataAsync(ProfileDataRequestContext context) {
// Not doing any change here
User user = await _userManager.GetUserAsync(context.Subject);
ClaimsPrincipal principal = await _claimsFactory.CreateAsync(user);
context.IssuedClaims = principal.Claims.ToList();
}
public async Task IsActiveAsync(IsActiveContext context) {
User user = await _userManager.GetUserAsync(context.Subject);
context.IsActive = (user != null) && user.Enabled;
}
}
我想 ProfileService 在不使用 Asp.Net Core Identity 时更有用?
使用 ASP.NET Core 3.1 和 Identity Server 4 我从 SPA 开始登录过程。
登录后,我对 IS4 应用程序身份验证 cookie 有以下声明:
sub 1
AspNet.Identity.SecurityStamp RRHNY65RQMUHTXXSIZKT2YORA3QQ2WAC
role Admin
preferred_username info@example.com
name info@example.com
email info@example.com
email_verified true
amr pwd
idp local
auth_time 1598736198
为什么 name
声明将电子邮件作为其价值?
然后我实现了 ProfileService 以用实际用户名替换 name
声明。
当我检查水疗中心的索赔时,更换已经完成...
但在 IS4 应用程序上,身份验证 Cookie 仍会收到电子邮件,如 name
声明的那样。
为什么?
身份令牌中的声明是否正确?
如果它在 ID-token 中是正确的,那么您可能在 ASP.NET 核心应用程序中实施了一些声明转换。
问题似乎出在 ASP.NET Core 3.1 如何定义声明。
然后我实施 UserClaimsPrincipalFactory
来更新 name
声明:
public class UserClaimsPrincipalFactory : UserClaimsPrincipalFactory<User> {
public UserClaimsPrincipalFactory(UserManager<User> userManager, IOptions<IdentityOptions> optionsAccessor) : base(userManager, optionsAccessor) { }
public async override Task<ClaimsPrincipal> CreateAsync(User user) {
ClaimsPrincipal principal = await base.CreateAsync(user);
ClaimsIdentity identity = (ClaimsIdentity)principal.Identity;
Claim claim = identity.FindFirst("name");
if (claim != null)
identity.RemoveClaim(claim);
identity.AddClaim(new Claim("name", user.Name));
return principal;
}
}
现在身份验证 Cookie 和令牌具有相同的声明。
使用 IdentityServer4 的 ProfileService
仅更改令牌上的声明:
public class ProfileService : IProfileService {
private readonly IUserClaimsPrincipalFactory<User> _claimsFactory;
private readonly UserManager<User> _userManager;
public ProfileService(UserManager<User> userManager, IUserClaimsPrincipalFactory<User> claimsFactory) {
_userManager = userManager;
_claimsFactory = claimsFactory;
}
public async Task GetProfileDataAsync(ProfileDataRequestContext context) {
// Not doing any change here
User user = await _userManager.GetUserAsync(context.Subject);
ClaimsPrincipal principal = await _claimsFactory.CreateAsync(user);
context.IssuedClaims = principal.Claims.ToList();
}
public async Task IsActiveAsync(IsActiveContext context) {
User user = await _userManager.GetUserAsync(context.Subject);
context.IsActive = (user != null) && user.Enabled;
}
}
我想 ProfileService 在不使用 Asp.Net Core Identity 时更有用?