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

如何在Duende的Client Credential Flow中自定义Token的Claim

基于Duende IdentityServer扩展Client Credential Flow的JWT声明

是的,基于ITokenResponseGenerator扩展是Client Credential Flow下自定义客户端JWT声明的正确方案——这个接口负责生成令牌响应,完全覆盖客户端凭证模式的令牌生成流程,能满足你添加、移除自定义声明的需求。

实现步骤

1. 自定义TokenResponseGenerator实现类

继承Duende提供的默认TokenResponseGenerator,重写GenerateAsync方法,在该方法中修改JWT声明:

using Duende.IdentityServer.Models;
using Duende.IdentityServer.Services;
using Duende.IdentityServer.Validation;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using System.IdentityModel.Tokens.Jwt;

public class CustomClientTokenGenerator : TokenResponseGenerator
{
    public CustomClientTokenGenerator(ISystemClock clock, ITokenService tokenService, IResourceStore resourceStore, IClientStore clientStore)
        : base(clock, tokenService, resourceStore, clientStore)
    {
    }

    public override async Task<TokenResponse> GenerateAsync(TokenRequestValidationResult validationResult)
    {
        // 获取原始令牌响应
        var originalResponse = await base.GenerateAsync(validationResult);
        
        // 从请求中提取自定义GUID:支持form参数或请求头两种方式
        var customGuid = validationResult.ValidatedRequest.Raw.Get("custom_guid") 
                         ?? validationResult.ValidatedRequest.HttpContext.Request.Headers["X-Custom-Guid"].FirstOrDefault();

        if (!string.IsNullOrWhiteSpace(customGuid))
        {
            // 解析原始JWT的声明集合
            var jwtHandler = new JwtSecurityTokenHandler();
            var originalJwt = jwtHandler.ReadJwtToken(originalResponse.AccessToken);
            var updatedClaims = new List<Claim>(originalJwt.Claims);

            // 1. 添加基于GUID的自定义声明
            updatedClaims.Add(new Claim("custom_identifier", customGuid));

            // 2. 移除指定的现有声明(示例为移除"example_claim_to_remove"类型的声明)
            updatedClaims.RemoveAll(claim => claim.Type == "example_claim_to_remove");

            // 重新生成包含修改后声明的JWT令牌
            var newAccessToken = await TokenService.CreateAccessTokenAsync(new TokenCreationRequest
            {
                Subject = new ClaimsPrincipal(new ClaimsIdentity(updatedClaims)),
                ValidatedRequest = validationResult.ValidatedRequest,
                Resources = validationResult.ValidatedResources
            });

            // 更新响应中的AccessToken
            originalResponse.AccessToken = newAccessToken;
        }

        return originalResponse;
    }
}

2. 替换DI容器中的默认实现

在IdentityServer的服务配置中,将默认的ITokenResponseGenerator替换为自定义实现:

// 在Program.cs或Startup.cs的服务注册阶段
builder.Services.AddTransient<ITokenResponseGenerator, CustomClientTokenGenerator>();

补充说明

  • GUID传递方式:客户端请求令牌时,可通过POST表单参数(custom_guid)或自定义请求头(X-Custom-Guid)传入GUID,根据业务场景选择即可。
  • 声明修改限制:避免移除JWT的核心必要声明(如iss、exp、client_id),否则会导致令牌验证失败。
  • 可选优化:如果需要先验证GUID的合法性,可额外实现ICustomTokenRequestValidator,在令牌请求验证阶段完成GUID校验,再在生成器中直接使用校验后的GUID。

内容的提问来源于stack exchange,提问作者Konrad Viltersten

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 19:17:44