You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 02:42:01