C# OpenIddict作用域和声明方法 C#如何配置API资源和身份资源

来源:这里教程网 时间:2026-02-21 17:43:01 作者:

OpenIddict 里 scope 和 claims 的区别在哪

scope 是客户端请求访问权限时声明的“能力范围”,比如

api.read
profile
;claims 是用户身份中实际携带的“属性数据”,比如
name
email
role
。OpenIddict 不自动把 scope 映射成 claims,也不自动发放 claims —— 它只按你配置的 scope 列表决定是否签发 token,而 claims 必须显式添加到
ClaimsPrincipal
或通过
IAuthorizationService
注入。

常见错误是以为只要在 client 配置了

scopes = ["profile"]
,token 就会自动包含
name
email
。不会。必须手动在登录逻辑里把用户信息加进
ClaimsIdentity
,或用
AddClaims
扩展方法补全。

scope 控制“能访问什么”,用于授权决策(如
[Authorize(Policy = "ApiRead")]
claims 控制“是谁、有什么属性”,用于业务逻辑(如
User.FindFirst("role")?.Value
OpenIddict 默认只注入
sub
iat
exp
等基础 claims,其余全靠你填

如何注册 API 资源(Resource Server)

API 资源不是 OpenIddict 自动识别的,而是靠

AddApiScopes
+
AddApiResources
显式定义,并在 API 项目中用
AddAuthentication().AddJwtBearer()
验证 token 中的
aud
scope

关键点:API 项目和授权服务器可以分离,但 scope 名称必须完全一致(大小写敏感),且 API 的

audience
必须匹配授权服务器注册的
ApiResources
名称。

在授权服务器调用
services.AddOpenIddict().AddServer().AddApiScopes("api.read", "api.write")
再调用
AddApiResources("my_api", "My API")
,其中
"my_api"
将成为 JWT 的
aud
在 API 项目中,
JwtBearerOptions.Audience
必须设为
"my_api"
,否则验证失败
scope 检查需配合策略:如
options.AddPolicy("ApiRead", p => p.RequireClaim("scope", "api.read"))

怎么配置 identity resources(如 profile、email)

identity resources 是 OIDC 标准中预定义的用户属性集合,OpenIddict 本身不内置实现,但允许你用

AddIdentityResources
注册名称,并在 token endpoint 返回时手动注入对应 claims。

例如注册

profile
后,客户端带
scope=profile
请求 token,OpenIddict 不会自动返回
name
picture
—— 你需要监听
ProcessSignInContext
事件,在签发前把用户数据塞进去。

注册:
options.AddIdentityResources("profile", "email", "address")
监听事件:
options.AddEventHandler<openiddictserverevents.processsignincontext>(...)</openiddictserverevents.processsignincontext>
在 handler 中判断
context.Request.GetScopes().Contains("profile")
,再调用
context.Principal.AddIdentityTokenClaim(...)
注意:这些 claims 只出现在 ID Token(登录响应)中,不出现在 Access Token,除非你额外往 access token 加

为什么 /connect/token 返回的 access_token 没有 scope 字段

OpenIddict 默认不把 scope 写进 access_token payload,它只在 token 的

scope
响应参数里返回(HTTP body 中),这是 OAuth 2.0 规范行为。access_token 是 opaque 或 JWT,JWT 版本默认也不含
scope
claim —— 因为 scope 是授权上下文信息,不是资源访问所需的凭证内容。

如果你需要在 API 中读取 scope,有两种方式:

解析 JWT 并检查
scope
claim(需手动添加,OpenIddict 不自动加):在
ProcessSignInContext
中调用
context.Principal.AddAccessTokenClaim("scope", string.Join(" ", context.Request.GetScopes()))
更推荐的方式:用 policy +
RequireScope("api.read")
,它底层从
context.User.FindAll("scope")
读取,无需改 token 结构
切勿依赖 access_token 中是否存在
scope
字段做鉴权,应统一走
IAuthorizationService
或策略机制

最易被忽略的是:scope 名称拼写不一致、大小写错位、API 未正确设置 audience、以及忘记在

ProcessSignInContext
中手动注入 identity claims —— 这些都会导致看似配置完整,实则 token 为空或鉴权失败。

相关推荐

热文推荐