授权码与 PKCE 开发人员

上次更新:2026年8月6日

授权码与 PKCE

通过门户创建的应用使用 Authorization Code + PKCE(S256) 流程。浏览器仅接收短期有效的授权码 codecode_verifier 须在可信环境中保存并用于换取令牌。机密客户端另需在后端使用 client_secret

下文以生产 Issuer 为例:

ISSUER=https://api-passport.swaymoon.com

实际端点请以 {ISSUER}/.well-known/openid-configuration 返回的发现文档为准。

1. 生成 PKCE

  1. 生成高熵的 code_verifier(43–128 个 URL 安全字符)。
  2. code_challenge = BASE64URL(SHA256(code_verifier))(无填充)。
  3. code_challenge_method = S256

code_verifierstate 存入服务端会话、加密 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. 使用授权码换取令牌

向令牌端点发起 POSTapplication/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_verifierstate
  • 机密客户端:仅在后端使用 client_secret 换取令牌。
  • 非机密客户端:切勿编造或硬编码 client_secret;依赖 PKCE 与登记过的 Redirect URI。
  • 使用 HTTPS 回调与传输。
  • 限制 scope 为最小必要集。
  • 妥善处理错误:invalid_grantinvalid_clientinvalid_request 等。

下一步:阅读《令牌与用户信息》,完成令牌校验和本地用户建档。