应用登录与用户字段映射
把认证中心作为登录提供方时,管理员在「应用接入」、开发者在「我的应用」创建应用,再把配置填入接入方的 OAuth2 / OpenID Connect 设置。最先查看接入方要求的字段格式:字段名、JSONPath 和模板表达式不是同一种语法。
最常用的字段映射
用户信息地址是本站 /oauth/userinfo,请求携带 Authorization: Bearer <access_token>。申请 openid profile email,且在应用允许范围里勾选这三项,重新授权后才能取得以下字段。application_creator 随 openid 始终返回,用于判断当前用户是否为当前应用的创建人。
| 用途 | 字段名 | JSONPath | 类型 | 所需 scope |
|---|---|---|---|---|
| 用户唯一标识 | sub | $.sub | string | openid |
| 当前应用创建人 | application_creator | $.application_creator | boolean | openid |
| 显示名称 / 昵称 | name | $.name | string | profile |
| 邮箱 | email | $.email | string | |
| 邮箱已验证 | email_verified | $.email_verified | boolean |
字段位于 JSON 根对象,没有 data 或 user 包装。若对方要求字段名,填 sub;若要求 JSONPath,填 $.sub。只有对方明确要求其他模板语法时,才使用其模板。
平台内部个人资料的 id、nickname、avatar 不是 OIDC 用户信息字段。当前不返回 picture、avatar、username、preferred_username、手机号或角色。头像映射留空;如接入方要求唯一用户名且允许 UUID,可使用 sub,不要把可重复昵称当作唯一账号。
应用可以在首次登录时把 application_creator=true 的用户设为应用管理员。该声明只回答“此人是否创建了当前 aud 对应的应用”,不会泄露创建人 ID、认证中心管理员身份或其他应用权限。ID Token 中的值必须先通过 JWKS 验签,并校验 iss、aud、exp 和 nonce;不能信任浏览器提交的字段或只解码未验签的 JWT。调用 UserInfo 时必须使用服务端取得的 access token,并核对 sub 与 ID Token 一致。
用户唯一关联应使用发行方 iss 与 sub。邮箱和昵称可以变化;不能仅凭未验证邮箱合并已有账号。
响应示例
以下由接口契约生成,全部为虚构数据,实际字段取决于令牌 scope。
{
"sub": "00000000-0000-4000-8000-000000000001",
"name": "示例用户",
"email": "person@example.test",
"email_verified": false,
"application_creator": true
}
email_verified 是布尔值,可能为 false,不是字符串 "true"。没有申请对应 scope 时字段直接省略。管理员修改应用允许范围不会给旧令牌追加权限,需要重新发起授权。
接入配置
| 接入方设置 | 本平台的值 |
|---|---|
| Issuer / 发行方 | 本站公开根地址,与发现文档 issuer 完全一致 |
| Discovery / 自动发现 | /.well-known/openid-configuration 的完整本站 URL |
| 授权地址 | /oauth/authorize 的完整本站 URL |
| Token 地址 | /oauth/token 的完整本站 URL |
| 用户信息地址 | /oauth/userinfo 的完整本站 URL |
| JWKS 公钥地址 | /.well-known/jwks.json 的完整本站 URL |
| Client ID | 应用记录中的 client_id,不是应用 UUID |
| Client Secret | 创建或重置时显示的 client_secret,仅用于机密客户端服务端 |
| Scope | openid profile email;需要刷新再加 offline_access |
| 回调地址 | 从接入方复制完整回调地址,在本平台精确登记,不使用通配符 |
生产与非回环地址必须使用 HTTPS;仅 localhost、127.0.0.1、[::1] 允许登记 HTTP 回调。APP_ORIGIN 是统一对外地址,不要混用前端、后端端口或不同域名。
授权流程
- 每次登录生成随机
state(16–1024 字符)、nonce(16–512 字符)与code_verifier(43–128 字符)。默认所有客户端都要求 PKCE S256。 - challenge 为 verifier 的 SHA256 经无填充 Base64URL 编码。浏览器访问授权地址,传
response_type=code、client_id、redirect_uri、scope、state、nonce、code_challenge、code_challenge_method=S256。 - 用户同意后,验证回调 state、iss;若回调含 error,按错误处理,不继续交换。
- 60 秒内用 code、同一 redirect_uri 和 verifier POST 表单到 token 地址。机密客户端使用 Basic 或表单 client_secret,公开客户端仅使用 client_id,不能打包 secret。
- ID Token 是 RS256 JWT,必须用 JWKS 验签并校验 iss、aud、exp、nonce。access_token 是不透明字符串,用它请求 UserInfo;UserInfo 的 sub 必须和验签后的 ID Token sub 一致。
- 仅
offline_access返回 refresh_token。刷新需串行执行并原子替换返回值;旧值重放将撤销令牌族。会话撤销或账号停用后令牌也失效。
授权页快捷登录
需要用户交互时,授权页默认显示快捷登录:认证中心小程序二维码位于左侧;浏览器已有有效会话时,右侧同时显示当前账号并可直接继续。浏览器没有有效会话时,快捷登录区只显示二维码。用户也可以切换到账号密码或管理员已启用的 GitHub、微信、QQ、微博等第三方登录,完成后会回到同一条授权请求,不会丢失 state、PKCE、redirect_uri 或待确认的 scope。
二维码是两分钟有效的一次性服务端挑战,不是静态登录链接。它同时绑定原浏览器持有的轮询密钥和完整 OAuth 请求;扫码会先绑定当前小程序会话,必须在手机上核对应用、账号和权限并明确确认,原浏览器才会建立 Web 会话。过期后在电脑端刷新二维码;取消、切换登录方式或成功消费都会使旧挑战失效。prompt=login 要求重新验证,不能由已有会话或扫码快捷登录代替;prompt=none 仍按 OIDC 语义直接返回 login_required 或 consent_required。
ID Token 始终提供 application_creator;profile 只提供 name,email 提供 email/email_verified;没有 picture。完整声明结构、表单参数和错误结构见登录与授权接口参考。
复制调用示例
下面是 POSIX shell 示例,变量由你的服务端安全注入;不要把真实令牌提交或发给 AI。
curl --fail-with-body "$ISSUER/oauth/userinfo" \
-H "Authorization: Bearer $ACCESS_TOKEN"
curl --fail-with-body "$ISSUER/oauth/token" \
-u "$CLIENT_ID:$CLIENT_SECRET" \
--data-urlencode 'grant_type=authorization_code' \
--data-urlencode "code=$CODE" \
--data-urlencode "redirect_uri=$REDIRECT_URI" \
--data-urlencode "code_verifier=$CODE_VERIFIER"
常见问题
| 现象 | 检查方法 |
|---|---|
| 找不到 id / nickname / data.email | 改为根层 sub / name / email;检查对方要求的映射语法 |
| 只有 sub | 实际授权缺少 profile/email;勾选范围并重新授权 |
| invalid_token(401) | 使用 access_token,检查是否过期、撤销或会话/应用停用;不要使用 id_token、API Key 或机器发布令牌 |
| insufficient_scope(403) | 重新申请含 openid 的令牌 |
| invalid_client(401) | 核对 Client ID、密钥、客户端类型和应用启用状态 |
| invalid_grant(400) | code 过期/已用、redirect_uri 不同、verifier 不匹配或刷新令牌重放 |
| 提示缺少 nonce | 升级接入客户端优先;确实无法发送时可对单个机密应用启用缺少 nonce 兼容,公开客户端不允许 |
| 接入方连 PKCE 都不支持 | 仅对能保存 Client Secret 的机密应用,在“应用接入 → 编辑”或“我的应用 → 编辑配置”开启传统 OIDC 客户端兼容;公开客户端不允许 |
| 429 / 503 | 按 HTTP 状态处理;限流中间件可能返回 code/message,OAuth 处理器返回 error |