示例与排错 开发人员

上次更新:2026年8月6日

示例与排错

片段示例便于对照协议;完整可运行脚本见《Python 最小可运行示例》。请将常量换成你的实际值。

发现文档

curl -sS https://api-passport.swaymoon.com/.well-known/openid-configuration | jq .

请确认 authorization_endpointtoken_endpointuserinfo_endpointjwks_uriid_token_signing_alg_values_supported 等字段。

授权 URL(浏览器跳转)

https://api-passport.swaymoon.com/oauth2/authorize
  ?response_type=code
  &client_id=swm_YOUR_CLIENT_ID
  &redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback
  &scope=openid%20name%20picture%20email
  &state=YOUR_STATE
  &code_challenge=YOUR_CHALLENGE
  &code_challenge_method=S256

拼 URL 时对查询参数只编码一次。若地址栏里出现 redirect_uri=http%253A%252F%252F…,属于双重编码,服务端会按字面值校验并失败。

换取令牌:机密客户端(curl)

ISSUER=https://api-passport.swaymoon.com
CLIENT_ID='swm_YOUR_CLIENT_ID'
CLIENT_SECRET='YOUR_SECRET'
CODE='...'
VERIFIER='...'
REDIRECT='https://app.example.com/callback'

curl -sS -u "$CLIENT_ID:$CLIENT_SECRET" \
  -X POST "$ISSUER/oauth2/token" \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode "grant_type=authorization_code" \
  --data-urlencode "code=$CODE" \
  --data-urlencode "redirect_uri=$REDIRECT" \
  --data-urlencode "code_verifier=$VERIFIER"

换取令牌:非机密客户端(curl)

ISSUER=https://api-passport.swaymoon.com
CLIENT_ID='swm_YOUR_CLIENT_ID'
CODE='...'
VERIFIER='...'
REDIRECT='https://app.example.com/callback'

curl -sS \
  -X POST "$ISSUER/oauth2/token" \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode "grant_type=authorization_code" \
  --data-urlencode "code=$CODE" \
  --data-urlencode "redirect_uri=$REDIRECT" \
  --data-urlencode "client_id=$CLIENT_ID" \
  --data-urlencode "code_verifier=$VERIFIER"

UserInfo(curl)

curl -sS https://api-passport.swaymoon.com/userinfo \
  -H "Authorization: Bearer $ACCESS_TOKEN"

刷新令牌(仅机密客户端)

curl -sS -u "$CLIENT_ID:$CLIENT_SECRET" \
  -X POST "$ISSUER/oauth2/token" \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode "grant_type=refresh_token" \
  --data-urlencode "refresh_token=$REFRESH_TOKEN"

常见问题

现象可能原因处理
授权报错 / 无法跳转至回调地址redirect_uri 与登记值不一致,或双重编码逐字符核对;地址栏不应出现 %253A / %252F
invalid_request / PKCE 相关错误缺少 code_challenge,或 code_challenge_method 不是 S256在授权与换取令牌流程中配套使用 code_verifiercode_challenge
invalid_clientBasic 凭证错误,或对非机密客户端误用了 Basic / secret核对类型;机密核对 client_id/client_secret;非机密改用表单 client_id
invalid_grantcode 已使用或已过期,或 code_verifier 不匹配重新发起授权,不要重复提交同一个 code
同意页未显示预期权限门户未配置该权限,或请求中未包含对应的 scope检查应用的可选权限和 scope 参数
回调 error=invalid_scope授权请求的 scope 超出该客户端已登记范围在门户「功能」中勾选对应权限,或缩小请求中的 scope
UserInfo 没有 email令牌未含 email(用户取消了可选邮箱,或请求未申请)检查令牌响应中的 scope;已授予 email 时应始终有该字段
UserInfo 资料像「空的」未授权资料细项时返回默认占位值(如昵称 摇月用户、头像 ""),不是字段缺失按令牌 scope 判断是否为真实资料;见《令牌与用户信息》
用户选了隐私邮箱email 可能为 @privaterelay.swaymoon.com 中继地址按普通邮箱处理即可;真实邮箱不会提供给你方
sub 与其他应用中的值不一致这是 pairwise 机制的预期行为仅在当前 client_id 或团队范围内使用 sub
ID Token 验签失败未使用 ES256,或缓存的 JWKS 已过期重新获取 /oauth2/jwks,并确认 algES256
前端暴露 client_secret将机密客户端用于纯 SPA改为创建非机密客户端,或仅在后端保存密钥
非机密客户端没有 refresh_token预期行为Access Token 过期后重新走授权码 + PKCE

联调提示

  • 根据发现文档获取端点,避免硬编码路径。
  • 完整本地脚本:《Python 最小可运行示例》。
  • 登录和授权确认在浏览器中完成;机密客户端的换取令牌与 UserInfo 应在服务端进行。
  • 生产环境的 Issuer 和前端域名分别为 api-passport.swaymoon.compassport.swaymoon.com

获取帮助

  • 用户文档:关闭开发人员模式后,查看「指南」和「法律」分类。
  • 开发者门户:develop.swaymoon.com
  • 联系方式:hello@swaymoon.com(请勿通过公共渠道发送明文 client_secret;描述问题时可将其打码)