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
相关产品推荐
相关产品推荐

