授权码与 PKCE 开发人员
上次更新:2026年8月6日
授权码与 PKCE
通过门户创建的应用使用 Authorization Code + PKCE(S256) 流程。浏览器仅接收短期有效的授权码 code;code_verifier 须在可信环境中保存并用于换取令牌。机密客户端另需在后端使用 client_secret。
下文以生产 Issuer 为例:
ISSUER=https://api-passport.swaymoon.com
实际端点请以 {ISSUER}/.well-known/openid-configuration 返回的发现文档为准。
1. 生成 PKCE
- 生成高熵的
code_verifier(43–128 个 URL 安全字符)。 code_challenge = BASE64URL(SHA256(code_verifier))(无填充)。code_challenge_method = S256。
将 code_verifier 和 state 存入服务端会话、加密 Cookie,或非机密客户端可用的安全会话存储;避免将其泄露给第三方脚本。
2. 引导用户授权
构造并重定向到授权端点,例如:
GET /oauth2/authorize?
response_type=code
&client_id=swm_xxxxxxxx
&redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback
&scope=openid%20name%20picture%20email
&state=RANDOM_STATE
&code_challenge=CHALLENGE
&code_challenge_method=S256
Host: api-passport.swaymoon.com
| 参数 | 要求 |
|---|---|
response_type | 固定 code |
client_id | 由开发者门户发放 |
redirect_uri | 必须已登记且完全一致 |
scope | 空格分隔;至少 openid |
state | 用于防止 CSRF;回调时须校验其是否与原值一致 |
code_challenge / code_challenge_method | 必填,S256 |
用户将在 passport.swaymoon.com 完成登录(如有需要)和授权确认。成功后,浏览器将跳转至:
https://app.example.com/callback?code=...&state=...
如果用户取消授权,应用通常不会收到可用的 code,应按照返回的错误或取消参数进行处理。
3. 使用授权码换取令牌
向令牌端点发起 POST(application/x-www-form-urlencoded)。
机密客户端
在后端使用 HTTP Basic:
POST /oauth2/token
Host: api-passport.swaymoon.com
Authorization: Basic BASE64(urlencode(client_id):urlencode(client_secret))
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=AUTHORIZATION_CODE
&redirect_uri=https://app.example.com/callback
&code_verifier=VERIFIER
非机密客户端
不要发送 Basic 或 client_secret。在表单中携带 client_id:
POST /oauth2/token
Host: api-passport.swaymoon.com
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=AUTHORIZATION_CODE
&redirect_uri=https://app.example.com/callback
&client_id=swm_xxxxxxxx
&code_verifier=VERIFIER
说明:
redirect_uri必须与授权请求中的值一致。code_verifier必须与授权时提交的code_challenge对应。- 授权码只能使用一次,且有效期较短。
成功响应(字段以实际为准)示例:
{
"access_token": "...",
"refresh_token": "...",
"id_token": "...",
"token_type": "Bearer",
"expires_in": 300,
"scope": "openid name picture email"
}
- 机密客户端通常会收到
refresh_token。请安全存储所有令牌,不要将client_secret或 Refresh Token 下发至不可信的前端环境。 - 非机密客户端响应中没有
refresh_token。Access Token 过期后,请重新发起授权码 + PKCE 流程。
4. 刷新访问令牌(仅机密客户端)
Access Token 过期后:
POST /oauth2/token
Authorization: Basic ...
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token
&refresh_token=REFRESH_TOKEN
刷新成功后,请使用新的 access_token,以及响应中可能轮换的 refresh_token。在令牌轮换策略下,旧的 Refresh Token 可能立即失效,请始终以最新响应为准。
非机密客户端不支持此步骤。
5. 用户体验要点
- 未登录用户会先进入通行账户登录页,再进入授权确认流程。
- 敏感操作可能触发再次登录(step-up authentication),这是正常的安全机制。
- 同意页文案与可选权限勾选见《权限与同意》。
6. 安全清单
- 始终保存并校验
code_verifier和state。 - 机密客户端:仅在后端使用
client_secret换取令牌。 - 非机密客户端:切勿编造或硬编码
client_secret;依赖 PKCE 与登记过的 Redirect URI。 - 使用 HTTPS 回调与传输。
- 限制
scope为最小必要集。 - 妥善处理错误:
invalid_grant、invalid_client、invalid_request等。
下一步:阅读《令牌与用户信息》,完成令牌校验和本地用户建档。