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

OpenIddict生成JWT令牌时aud声明为空问题:能否像IdentityServer一样自动关联作用域与受众

OpenIddict自动添加aud声明的实现方式

好问题!OpenIddict完全支持类似IdentityServer那种通过配置API资源和作用域来自动填充aud(受众)声明的功能,完全不需要手动往ClaimsPrincipal里添加。下面我会详细讲怎么配置,以及解决你当前令牌aud为空的问题。

核心思路

和IdentityServer的逻辑一致:你需要先注册API资源,然后将作用域关联到对应的API资源。当客户端请求某个关联了API资源的作用域时,OpenIddict会自动把该API资源的名称作为aud声明加入到令牌中。如果请求的作用域属于多个不同的API资源,aud会是一个包含所有对应资源名称的数组。

具体配置步骤

假设你用的是ASP.NET Core + Entity Framework Core的组合,以下是典型的配置方式:

1. 注册API资源和关联作用域

在Program.cs(或Startup类)中配置OpenIddict服务器时,你可以直接注册API资源并绑定对应的作用域:

builder.Services.AddOpenIddict()
    // 配置OpenIddict核心组件(使用EF存储数据)
    .AddCore(options =>
    {
        options.UseEntityFrameworkCore()
               .UseDbContext<ApplicationDbContext>();
    })
    // 配置OpenIddict服务器
    .AddServer(options =>
    {
        // 启用必要的端点(授权、令牌等)
        options.SetAuthorizationEndpointUris("/connect/authorize")
               .SetTokenEndpointUris("/connect/token");

        // 注册API资源:第一个参数是资源名称(会作为aud的值),第二个是显示名称,第三个是允许的声明
        options.RegisterApiResource("api1", "我的业务API", new[] { "email", "profile" })
               .RegisterApiResource("api2", "后台管理API");

        // 注册作用域
        options.RegisterScopes("api1.read", "api1.write", "api2.admin");

        // 将作用域关联到对应的API资源(关键步骤!)
        options.AddScopedResource("api1.read", "api1");
        options.AddScopedResource("api1.write", "api1");
        options.AddScopedResource("api2.admin", "api2");

        // 配置JWT令牌相关设置
        options.UseJsonWebTokens()
               .AddEphemeralEncryptionKey() // 生产环境建议用持久化密钥
               .AddEphemeralSigningKey();
    });

2. 确保客户端有权请求这些作用域

在注册客户端的时候,需要允许它请求对应的作用域:

options.RegisterClient("my-client")
       .SetClientId("my-client-id")
       .SetClientSecret("my-client-secret")
       .SetAllowedGrantTypes(GrantTypes.ClientCredentials, GrantTypes.AuthorizationCode)
       .SetAllowedScopes("api1.read", "api1.write");

为什么你的令牌aud为空?

大概率是以下原因之一:

  • 你没有注册任何API资源,或者请求的作用域没有关联到任何API资源;
  • 客户端请求的作用域不在其允许的范围内;
  • 你没有在OpenIddict服务器配置中启用API资源的自动关联逻辑。

按照上面的步骤配置后,当客户端请求api1.read作用域时,生成的JWT令牌里就会自动包含"aud": "api1";如果同时请求api1.read和api2.admin,aud会是["api1", "api2"]。

手动处理的场景(不推荐)

虽然不建议,但如果确实需要手动控制aud声明,你可以在令牌生成的事件中添加,比如:

options.AddEventHandler<OpenIddictServerEvents.ApplyTokenContext>(context =>
{
    if (context.TokenType == OpenIddictConstants.TokenTypes.AccessToken)
    {
        context.Context.AddClaim(OpenIddictConstants.Claims.Audience, "custom-audience");
    }
    return default;
});

但这种方式不符合OAuth2.0的规范,优先推荐用API资源+作用域关联的配置方式。

内容的提问来源于stack exchange,提问作者Koppa Péter

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 11:49:07