---
title: "令牌校验与 claims"
description: "区分 ID token、access token、令牌响应和 Introspection，并按实际 JSON 类型读取组织权限。"
url: "https://auth.kai.com/docs/claims"
language: "zh-CN"
version: "Better Auth 1.7.1"
updated: "2026-09-22"
---

# 令牌校验与 claims

区分 ID token、access token、令牌响应和 Introspection，并按实际 JSON 类型读取组织权限。

## 五个 KAI 扩展字段

| 字段                | JSON 类型                                               | 含义                                 |
| ------------------- | ------------------------------------------------------- | ------------------------------------ |
| `organization_id`   | string                                                  | 应用所属组织 ID                      |
| `project_id`        | string                                                  | 应用所属项目 ID                      |
| `organization_role` | `"owner"`、`"admin"`、`"developer"`、`"member"` 或 null | 用户在应用所属组织中的角色           |
| `access_mode`       | `"members_only"` 或 `"authenticated_users"`             | 应用准入方式                         |
| `access_version`    | number（整数）                                          | 组织访问策略版本；不是字符串或布尔值 |

这五个字段由组织与项目归属、当前成员关系和应用 metadata 计算，出现在成功令牌响应、ID token、JWT access token，以及适用的活跃 Introspection 结果中。无效令牌可能只返回 `{"active": false}`，客户端不能要求错误响应也带齐这些字段。

`authenticated_users` 模式下非成员可以合法登录，`organization_role: null` 是有效值。不要为了通过解析把它改成 `member`。扩展字段描述应用所属租户，不意味着用户有权访问其他租户或任意管理 API。

## JWT 授权与认证凭据

资源 JWT access token 还包含五个由 Auth 维护的内部声明：

| 字段                  | JSON 类型          | 含义                                    |
| --------------------- | ------------------ | --------------------------------------- |
| `kai_consent_id`      | string（UUID）     | 本次令牌所属的原始用户授权              |
| `kai_consent_version` | number（非负整数） | 授权版本；缩减 scope 或 resource 时递增 |
| `kai_auth_revision`   | number（非负整数） | 签发时账号的密码认证修订号              |
| `kai_factor_revision` | number（非负整数） | 签发时账号的安全因子修订号              |
| `kai_policy_revision` | number（非负整数） | 签发时账号的二步验证策略修订号          |

这些字段用于 Auth 的在线校验，不替代标准签名、issuer、audience 和 scope 检查，也不是资源服务器自行授予权限的依据。它们不承诺出现在 ID token 或普通登录资料中。

## 标准字段

| 字段                      | 类型与检查                                                         |
| ------------------------- | ------------------------------------------------------------------ |
| `iss`                     | string；必须等于配置的 issuer                                      |
| `sub`                     | string；用户稳定标识，与已验证 issuer 一起使用                     |
| `aud`                     | string 或 string[]；ID token 面向 client ID，access token 面向资源 |
| `exp`、`iat`、`auth_time` | number；秒级 Unix 时间，auth_time 仅在适用时出现                   |
| `scope`                   | access token / Introspection 中空格分隔的 string                   |
| `nonce`                   | ID token 中与本次授权事务一致的 string                             |
| `sid`                     | 适用时的会话标识，用于退出关联                                     |
| `client_id`、`azp`        | access token / Introspection 中的发放客户端标识                    |

JWT access token 使用 `typ: at+jwt`。API 不得接受 ID token 代替 access token。使用受信任 Discovery 的 `jwks_uri` 验证签名，并检查算法、有效期、issuer、audience 和所需 scope；不从未验证 token 中选择任意远端密钥地址。

## 额外验证结果

使用 `acr_values=urn:kai:acr:step-up` 并完成额外验证后，ID token、适用的 JWT access token 及活跃 access token 的 Introspection 结果包含以下公开字段（不包含 refresh token 自身的 Introspection）：

```json
{
  "acr": "urn:kai:acr:step-up",
  "auth_time": 1790000000,
  "kai_step_up": { "status": "verified" }
}
```

`kai_step_up.status` 只有 `verified` 和 `password_only` 两个成功值。前者表示完成高等级额外验证，后者只表示完成密码验证；两者不能混用。主动取消通过 OAuth 错误返回；关闭页面或超时可能没有回调，应用应按未完成处理，不存在“未完成但成功发放的证明”。不会对外发放此次验证的具体方式、设备或 `amr`。`acr` 标识 KAI 策略，不表示应用选择了某个具体因子，也不应解读为统一的 MFA 等级。

`acr` 是 string，`auth_time` 是非负整数，单位为 Unix 秒；`kai_step_up` 是 object，其 `status` 是上述两个字符串值之一。缺失字段、未知状态或不同 `acr` 都不能当作成功的额外验证。业务还须检查验证时间与当前业务账号的 `iss` / `sub`，不能仅检查 status。

| 返回位置                           | 是否提供额外验证结果                                  |
| ---------------------------------- | ----------------------------------------------------- |
| 本次授权的 ID token                | 是，先验证签名和标准 OIDC 声明                        |
| 本次授权的 JWT access token        | 是，资源服务器仍需验证自己的 audience 和 scope        |
| 活跃 access token 的 Introspection | 是；JWT 保留已校验声明，opaque token 从原授权记录读取 |
| Token endpoint 响应的 JSON 顶层    | 否，结果位于令牌内                                    |
| refresh token 自身的 Introspection | 否                                                    |
| UserInfo                           | 否，用于读取已授权的用户资料                          |

这些字段来自授权码签发时冻结的证明，refresh 保留原结果与原 `auth_time`。之后浏览器进行其他验证不会升级此前的授权链。普通 OAuth / Device 授权不会因同一个账号做过额外验证就附带成功结果。UserInfo 不提供额外验证结果，不能代替对签名证明的校验。完整请求、回调与结果校验见[额外身份验证](/docs/step-up)。

## 资料字段与 UserInfo

`openid` 提供 OIDC 身份语义，`profile` 和 `email` 控制 UserInfo 可见的资料。客户端以实际返回结果和 scope 为准，不假定 ID token 含 `name`、`picture` 或 `email`。UserInfo 的 `sub` 必须和 ID token 一致。

`email` scope 或显式 claims 请求必须授权对应字段，UserInfo 才会返回已验证的 `email`（string）或 `email_verified`（boolean）。单独请求其中一个字段不会自动获得另一个。仅手机号注册的账号没有已验证邮箱，因此这两个声明会缺省；即使请求了 `email` scope，也不能假定它们存在。Auth 自有的 `/api/me` 与原生会话接口使用 `user.email: null`、`emailVerified: false` 表示这种情况。接入应用应以 issuer 和 `sub` 标识用户。

## 撤销与策略更新

组织暂停后阻止新的访问与令牌操作；恢复组织不会恢复旧 consent 或授权链。成员或应用归属变化也可能使已有授权失效。离线 JWT 验证只观察签名与声明，已签发 JWT 在其剩余有效期内仍可能有效，当前默认上限为五分钟。

Auth 的 UserInfo 和 Introspection 会检查原始 consent、授权版本、scope、audience 和当前来源会话的三项认证修订号。删除 consent、缩减权限，或撤销来源会话后，旧资源 JWT 在这些在线端点失效；重新授权或恢复已删除的权限不会复活旧令牌。

修改密码、安全因子或二步验证策略会撤销已有授权码、Device Code 授权、access token 和 refresh token，包括经验证后保留当前会话的个人安全操作。因子或策略修改保留 consent 与自动登录偏好，但应用需要重新发起授权获取新令牌；密码修改还会清除 consent。普通 RP 重新验证不改变这些修订号，不撤销其他应用的授权。

部署此凭据契约后，未携带上述完整声明的旧资源 JWT 会被在线 UserInfo 和 Introspection 拒绝。若原刷新授权链仍有效，可刷新获得新令牌，否则重新授权。升级不会因此删除账号或浏览器会话；离线验证仍可能接受旧 JWT 直到原 `exp` 到期。

令牌里的 `access_version` 是发行时的策略版本，不会自动更新。若资源服务器要求即时撤销，必须设计在线状态或版本检查，不能只缓存该字段并宣称实时撤销。授权撤销和退出行为见[退出与授权撤销](/docs/logout)。
