流程总览

只做「用 X2Post 登录」的接入方,可以直接看《OpenID Connect(OIDC)》:在同样的流程里加 scope=openid 与 nonce,换令牌时会额外拿到可离线验签的 id_token。

第一步:把用户送到授权页

GET https://x2post.com/oauth/authorize
  ?response_type=code
  &client_id=<你的 client_id>
  &redirect_uri=<注册过的回调地址,必须完全一致>
  &scope=profile:read%20posts:read
  &state=<随机串,用于防 CSRF>
  &code_challenge=<PKCE challenge>
  &code_challenge_method=S256

要点:

  • redirect_uri 与注册值精确匹配(含协议、域名、路径、端口),不匹配会直接报错、不回跳;
  • 公共客户端(纯前端/移动端)必须使用 PKCE;机密客户端也建议使用;
  • state 请务必校验:回跳时会原样带回。

第二步:换令牌

curl -X POST https://x2post.com/api/oauth/token \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'grant_type=authorization_code' \
  -d 'client_id=<client_id>' \
  -d 'client_secret=<机密应用的 secret>' \
  -d 'code=<授权码>' \
  -d 'redirect_uri=<与授权时一致>' \
  -d 'code_verifier=<PKCE verifier>'

成功响应:

{
  "access_token": "x2o_...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "x2r_...",
  "scope": "profile:read posts:read"
}

授权码是一次性的:5 分钟内有效、只能兑换一次;重复使用会返回 invalid_grant,并且我们会在检测到复用时撤销该用户在该应用下的全部令牌(防凭据泄漏)。

第三步:调用接口

curl -H 'Authorization: Bearer x2o_...' https://x2post.com/api/open/v1/me

刷新与撤销

刷新(refresh_token 每次刷新都会旋转,旧的立即失效):

curl -X POST https://x2post.com/api/oauth/token \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'grant_type=refresh_token' \
  -d 'client_id=<client_id>' \
  -d 'client_secret=<secret>' \
  -d 'refresh_token=x2r_...'

撤销:

curl -X POST https://x2post.com/api/oauth/revoke \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'token=x2o_...' -d 'client_id=<client_id>' -d 'client_secret=<secret>'

错误码

error HTTP 含义 常见原因
invalid_client 401 客户端认证失败 client_secret 错误/已轮换;应用被停用
invalid_grant 400 授权凭据无效 授权码过期或已用过、code_verifier 不匹配、redirect_uri 与授权时不一致、refresh 已失效
invalid_request 400 参数问题 缺少 grant_type / client_id / code 等
unsupported_grant_type 400 不支持的授权类型 目前只支持 authorization_code 与 refresh_token

安全清单

  • 用 state 防 CSRF,用 PKCE 防授权码拦截;
  • client_secret 只放在服务端,不要下发到浏览器;
  • 刷新后请存新的 refresh_token(旧的立刻作废);
  • 用户取消授权后请清掉本地令牌,并引导其重新授权。