基于IdentityServer4模拟登录的refresh token保留actor claim方案咨询
IdentityServer4 refresh token刷新保留actor claim实现方案
核心思路
首次生成refresh token时就把actor claim固化到refresh token的内置声明集合中,刷新token时IdentityServer会自动加载refresh token关联的所有声明到请求上下文,只需在对应逻辑节点将actor claim重新加入新生成的token即可。
实现步骤
步骤1:自定义RefreshTokenService,保存actor到refresh token
重写默认DefaultRefreshTokenService的创建refresh token逻辑,将当前上下文中的actor claim存入refresh token的声明集合:
public class CustomRefreshTokenService : DefaultRefreshTokenService { public CustomRefreshTokenService( IRefreshTokenStore refreshTokenStore, IProfileService profileService, ISystemClock clock, ILogger<DefaultRefreshTokenService> logger) : base(refreshTokenStore, profileService, clock, logger) { } protected override async Task<RefreshToken> CreateRefreshTokenAsync(ClaimsPrincipal subject, Token accessToken, Client client) { var refreshToken = await base.CreateRefreshTokenAsync(subject, accessToken, client); // 提取actor claim存入refresh token var actorClaim = subject.FindFirst("actor"); if (actorClaim != null && !refreshToken.Claims.Any(c => c.Type == "actor")) { refreshToken.Claims.Add(actorClaim); } return refreshToken; } }
在程序入口注册自定义服务,替换默认实现:
// .NET 6+ Program.cs示例 builder.Services.Replace(ServiceDescriptor.Scoped<IRefreshTokenService, CustomRefreshTokenService>());
步骤2:调整ProfileService,刷新时传递actor claim
修改自定义IProfileService的GetProfileDataAsync逻辑,识别刷新token请求场景,将actor claim加入返回的声明列表:
public class CustomProfileService : IProfileService { public Task GetProfileDataAsync(ProfileDataRequestContext context) { // 原有常规用户声明加载逻辑 // ... // 所有场景下只要上下文存在actor claim就加入返回列表 var actorClaim = context.Subject.FindFirst("actor"); if (actorClaim != null) { context.IssuedClaims.Add(actorClaim); } return Task.CompletedTask; } public Task IsActiveAsync(IsActiveContext context) { // 原有用户有效性校验逻辑 // ... return Task.CompletedTask; } }
步骤3:补充资源配置,允许actor claim返回
确认你的IdentityResource(对应id token)和ApiResource(对应access token)的UserClaims配置中包含actor类型,否则声明会被过滤:
// 示例IdentityResource配置 new IdentityResource("openid", new [] { "sub", "actor" }), // 示例ApiResource配置 new ApiResource("your_api", new [] { "actor" })
步骤4(可选):MVC侧同步更新Cookie声明
如果需要同步更新MVC本地Cookie中的actor声明,可在刷新token成功的回调逻辑中,重新构建ClaimsPrincipal并更新Cookie:
// 刷新token成功后示例代码 var newClaims = new List<Claim>(User.Claims); // 替换为新的actor claim var oldActor = newClaims.FirstOrDefault(c => c.Type == "actor"); if (oldActor != null) newClaims.Remove(oldActor); newClaims.Add(new Claim("actor", newActorValueFromNewToken)); var newIdentity = new ClaimsIdentity(newClaims, User.Identity.AuthenticationType); await HttpContext.SignInAsync(new ClaimsPrincipal(newIdentity));
验证
完成以上配置后,首次模拟登录生成的refresh token会携带actor声明,刷新token时会自动将该声明带入新生成的access token、id token中,实现全流程保留。
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

