Fusion OAuth / 文档中心
登录

接入文档

适用于 Web 站点、Android / iOS 客户端与单页应用 · 最后更新 2026-11-12

V1 接口即将停用,请尽快适配 V2 V1(/token.php、/api/*、/v1/*)进入维护冻结期,后续不再新增能力,并将在正式停用前保留一段过渡期。 V2 提供全部 V1 能力,并新增细粒度错误码、API KEY 轮换与过期机制。 迁移方式非常简单:只需把接口路径中的前缀改为 /v2/,请求参数与响应字段完全兼容。

概述

Fusion OAuth 提供标准 OAuth 2.0 授权码模式与 OpenID Connect 能力。第三方应用通过授权码换取 Access Token,再调用 UserInfo 获取用户身份,即可完成「使用本站账号登录」。

V2 服务端点(全部位于 /v2/ 前缀下):

Issuer                 https://auth.401522.xyz
Authorization Endpoint https://auth.401522.xyz/v2/authorize.php
Token Endpoint         https://auth.401522.xyz/v2/token.php
UserInfo Endpoint      https://auth.401522.xyz/v2/userinfo.php
User Endpoint          https://auth.401522.xyz/v2/user.php
Refresh Endpoint       https://auth.401522.xyz/v2/refresh.php
Revocation Endpoint    https://auth.401522.xyz/v2/revoke.php
Introspection Endpoint https://auth.401522.xyz/v2/introspect.php
API KEY Endpoint       https://auth.401522.xyz/v2/keys.php
Verify Endpoint        https://auth.401522.xyz/v2/verify.php
Discovery              https://auth.401522.xyz/v2/.well-known/openid-configuration
Asset Links            https://auth.401522.xyz/.well-known/assetlinks.json

V1 → V2 迁移

V2 是 V1 的超集,迁移成本极低。核心变化只有三点:

项目V1V2
接口路径/token.php、/api/userinfo.php …/v2/token.php、/v2/userinfo.php …
请求参数完全一致,无需修改
成功响应字段完全一致(V2 额外附带 api_version 与 request_id)
错误响应仅 error + error_description额外提供 error_code(细粒度业务码)、error_title、http_status
API KEY仅支持「有效 / 无效」支持轮换与有效期,失效原因可区分

最小改动示例:

// 迁移前(V1)
POST https://auth.401522.xyz/token.php

// 迁移后(V2)
POST https://auth.401522.xyz/v2/token.php
迁移建议
  • 建议按「先 UserInfo、再 Token、最后授权页」的顺序灰度迁移:UserInfo 是最常调用、最容易观测到错误码变化的端点。
  • V1 与 V2 可同时运行,互不影响,随时可回退。

快速开始

  1. 登录控制台,在「我的应用」中创建应用,选择客户端类型(Web 应用 / 移动应用 / SPA)。
  2. 填写回调地址。移动端可填自定义 Scheme,例如 myapp://oauth/callback;选择「移动应用」时必须填写 Android 包名。
  3. 保存后获得 client_id 与 client_secret(公共客户端可只使用 client_id + PKCE)。
  4. 按下方流程引导用户授权,并用授权码换取令牌。

Web 授权码流程

1. 引导用户授权

GET https://auth.401522.xyz/v2/authorize.php
  ?response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=https%3A%2F%2Fyour-site.com%2Fcallback
  &scope=openid%20profile%20email
  &state=RANDOM_STATE

2. 回调换取令牌

POST https://auth.401522.xyz/v2/token.php
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=RETURNED_CODE
&redirect_uri=https://your-site.com/callback
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET

也支持 Authorization: Basic base64(client_id:client_secret) 的机密客户端认证方式。

3. 获取用户信息

GET https://auth.401522.xyz/v2/userinfo.php
Authorization: Bearer ACCESS_TOKEN

PKCE 接入(移动端 / SPA 必选)

移动应用与单页应用无法安全保存 client_secret,必须使用 PKCE(RFC 7636)。在创建应用时将客户端类型设为「移动应用」或「SPA」,服务端会强制校验 code_challenge。

// 1. 生成随机 verifier(43-128 位)
verifier  = base64url(random(32 bytes))

// 2. 计算 challenge
challenge = base64url(sha256(verifier))

// 3. 授权请求附带
GET /v2/authorize.php?response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=myapp://oauth/callback
  &code_challenge=CHALLENGE
  &code_challenge_method=S256
  &state=STATE

// 4. 换取令牌时回传 verifier
POST /v2/token.php
grant_type=authorization_code&code=CODE
  &client_id=YOUR_CLIENT_ID
  &code_verifier=VERIFIER
  &redirect_uri=myapp://oauth/callback

Token 端点同时支持 application/x-www-form-urlencoded 与 application/json 请求体,并返回 CORS 头,可直接在 App 原生网络库中调用。

Android 客户端接入

回调地址的三种写法

  • 自定义 Scheme:myapp://oauth/callback,最简单,在 AndroidManifest.xml 中声明 intent-filter 即可。
  • App Links(推荐):https://auth.401522.xyz/android/callback,通过 assetlinks.json 校验后可直接唤端,无选择弹窗。
  • intent://:intent://oauth/callback#Intent;scheme=myapp;package=com.example.app;end,可精确指定 package。

Manifest 示例


  
    
    
    
    
  

唤起流程

授权成功后,服务端不会直接 302 到自定义 Scheme(浏览器会拦截),而是先跳到站内中间页 /app_redirect.php,由页面通过 JS 唤起 App,并提供「打开应用」按钮兜底。App 只需处理回调 URL 中的 code 与 state。

myapp://oauth/callback?code=XXXX&state=YYYY

建议使用 Custom Tabs(androidx.browser)打开授权页,以共享浏览器登录态:

CustomTabsIntent.Builder()
    .build()
    .launchUrl(context, Uri.parse(authUrl));

网页唤起安卓验证

除「标准授权码」外,本站还提供一条网页 → intent → 安卓客户端 → 验证 → 回传网页的完整链路,适合「点击按钮直接用本站账号免密登录」这类场景。

整体流程

① 网页   POST /v2/verify.php  action=ticket
         → 得到 ticket(一次性,5 分钟有效)
② 网页   用 intent:// 或 App Links 唤起安卓客户端,携带 ticket
③ 客户端 用 Custom Tabs 打开 /v2/authorize.php 完成登录授权
         → 拿到 code → 换 access_token
④ 客户端 POST /v2/verify.php  action=verify  ticket + access_token
         → 服务端生成 assertion(身份断言,120 秒有效)
⑤ 网页   GET /v2/verify.php  action=status  轮询拿到 assertion
⑥ 网页后端 POST /v2/verify.php  action=check  校验 assertion
         → 得到用户身份(sub / username / email)

唤起协议

# 自定义 Scheme(无需域名校验)
intent://oauth/verify?S.ticket=TICKET#Intent;
  scheme=fusionoauth;package=xyz.uoxvx.fusionoauth;end

# App Links(推荐,系统校验通过后免选择弹窗)
https://auth.401522.xyz/android/verify.php?ticket=TICKET

安卓客户端源码见交付包中的 android-client/ 目录(Kotlin + Gradle)。详细的接口参数见下方 安卓唤起验证端点 一节。

安全提示 票据一次性且 5 分钟过期;断言有效期仅 120 秒并绑定 client_id 与 state。 网页服务端务必自行校验 state,并通过 action=check 换取用户身份,切勿直接信任前端传来的用户信息。

Web 调用官方客户端登录 推荐

网页端与安卓客户端是两套独立前端,各自持有独立登录态、互不内嵌。当网页需要登录时,可发起一次标准 OAuth 授权码 + PKCE 流程,把「用户认证」这一步交给已登录的官方安卓客户端确认,随后网页在自己上下文完成同意页、授权码与令牌兑换。因为发起方是平台内置客户端,授权页会显示「官方」标记,但流程本身与普通 OAuth 完全一致。

整体流程

① 网页   GET /oauth_login.php?redirect=/dashboard.php
         → 生成 state + PKCE,302 到 /v2/authorize.php(prompt=app)
② 授权端点 未登录且为官方客户端 → 创建一次性授权请求,渲染等待页
         等待页用 intent:// 唤起官方客户端,浏览器同时轮询状态端点
③ 客户端 用本地登录态(Bearer mobile access_token)确认请求
④ 网页   GET /app_auth_status.php?request=... 轮询到 approved
         → 在浏览器会话建立 Web 登录态,回跳不带 prompt=app 的授权端点
⑤ 网页   显示普通同意页(带「官方」标记)→ 用户同意
         → 302 回 /oauth_callback.php?code=...&state=...
⑥ 网页后端 用 code + code_verifier 兑换标准 access_token / id_token
         → 写入 Web 会话,登录完成

端点一览

端点方法作用
/oauth_login.phpGET网页端发起登录(RP 入口),生成 state 与 PKCE
/v2/authorize.phpGET标准授权端点;prompt=app 且为官方客户端时进入等待页
/app_auth_status.phpGET浏览器轮询;approved 时建立 Web 会话并返回回跳地址
/api/mobile/authorize.phpPOST官方客户端确认 / 拒绝请求,需 Authorization: Bearer mat_…
/android/authorize.phpGETApp Links 落地点;安卓 UA 下 302 到 intent://
/oauth_callback.phpGET标准回调,服务端用 code + PKCE 兑换令牌

关键参数

参数位置说明
prompt=app授权端点仅官方网页客户端可用;第三方客户端即使携带,也仍被导向密码登录页
code_challenge
code_challenge_method=S256
授权端点PKCE,全流程强制
state / nonce授权端点CSRF 与重放防护,回调时原样校验
request轮询 / 确认一次性授权请求 ID,5 分钟过期,绑定 client_id、redirect_uri、state 与 PKCE
approve客户端确认true 确认、false 拒绝;同一请求只能处理一次
official响应字段布尔值,标识该应用 / 授权记录属于平台官方客户端

唤起协议

# 自定义 Scheme(等待页自动生成)
intent://oauth/authorize?S.request=REQUEST_ID#Intent;
  scheme=fusionoauth;package=xyz.uoxvx.fusionoauth;end

# App Links 落地点(安卓 UA 下由服务端 302 到上面的 intent)
https://auth.401522.xyz/android/authorize.php?request=REQUEST_ID
与旧版「网页唤起安卓验证」的区别 旧链路签发私有 ticket / assertion,由网页后端 action=check 换取身份;新链路最终产物是标准 oauth_auth_codes 授权码与 oauth_access_tokens,可直接用 /api/userinfo.php 校验。App 只证明「当前用户是谁」,不签发令牌、不建立 Web 会话、不替网页输入密码。旧链路仍保留兼容,新接入建议使用本节流程。

GET /v2/authorize.php

#

OAuth 2.0 授权码模式的起点。用户在此页面登录并确认授权后,服务端将授权码通过 redirect_uri 返回给客户端。公共客户端(移动应用 / SPA)必须携带 code_challenge,否则返回 invalid_request。

鉴权无需凭据;由浏览器会话携带登录态。
完整地址https://auth.401522.xyz/v2/authorize.php

请求参数

名称类型属性说明
response_type
QUERY
string可选授权类型,仅支持 code;缺省按 code 处理
默认值 code
client_id
QUERY
string必填应用 ID,控制台「我的应用」中获取
redirect_uri
QUERY
string必填回调地址,必须与应用后台登记的地址完全一致(协议、路径、参数均需一致)
scope
QUERY
string可选权限范围,空格分隔。可选值:openid、profile、email、basic
默认值 openid profile email
state
QUERY
string可选防 CSRF 随机串,授权后原样回传;强烈建议校验
nonce
QUERY
string可选混入 ID Token 的随机串,用于防重放
prompt
QUERY
string可选设为 none 时静默授权:未登录返回 login_required,未授权返回 consent_required
code_challenge
QUERY
string可选PKCE 挑战值。公共客户端(移动应用 / SPA)必填
code_challenge_method
QUERY
string可选PKCE 方法,仅支持 S256 与 PLAIN
默认值 S256

请求示例

GET https://auth.401522.xyz/v2/authorize.php
  ?response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=https%3A%2F%2Fyour-site.com%2Fcallback
  &scope=openid%20profile%20email
  &state=RANDOM_STATE
  &code_challenge=BASE64URL_SHA256_OF_VERIFIER
  &code_challenge_method=S256

响应示例

HTTP/1.1 302 Found
Location: https://your-site.com/callback?code=AUTHORIZATION_CODE&state=RANDOM_STATE

响应字段

字段类型说明
codestring授权码,有效期 10 分钟,仅可使用一次(出现在 Location 回跳地址中)
statestring原样回传的 state 参数
errorstring授权失败时的 OAuth2 标准错误码
error_descriptionstring授权失败原因说明
移动端说明:当 redirect_uri 为自定义 Scheme 或 intent:// 时,浏览器无法直接 302 唤起 App,服务端会先跳转到站内中间页 /app_redirect.php,由页面负责唤起 App 并提供「打开应用」按钮兜底。App 只需从回调中解析 code 与 state。

错误响应

error_codeHTTP含义与处理建议
invalid_request400公共客户端未携带 code_challenge、code_challenge_method 不支持或 challenge 长度非法
unauthorized_client403应用尚未通过审核或已被封禁,无法发起授权
login_required401prompt=none 且用户未登录
consent_required401prompt=none 且用户尚未授权该应用
access_denied403用户在同意页点击了「取消」

POST /v2/token.php

#

颁发令牌对。支持两种 grant_type:authorization_code(用授权码换令牌)与 refresh_token(用刷新令牌换新令牌对)。refresh_token 为严格一次性凭据,刷新后旧令牌立即失效。

鉴权机密客户端:Authorization: Basic base64(client_id:client_secret),或在请求体携带 client_id + client_secret。
公共客户端(移动应用 / SPA):仅需 client_id,但必须携带 code_verifier。
完整地址https://auth.401522.xyz/v2/token.php

请求参数

名称类型属性说明
grant_type
BODY
string必填授权类型。可选值:authorization_code、refresh_token
code
BODY
string条件必填授权码。grant_type=authorization_code 时必填
redirect_uri
BODY
string条件必填必须与授权时使用的完全一致。grant_type=authorization_code 时若在授权请求中携带过,则此处必填
code_verifier
BODY
string条件必填PKCE 校验串。公共客户端必填,需为 43~128 位 [A-Za-z0-9-._~] 字符
client_id
BODY
string必填应用 ID
client_secret
BODY
string条件必填应用密钥。机密客户端必填;公共客户端不可携带
refresh_token
BODY
string条件必填刷新令牌。grant_type=refresh_token 时必填

请求示例

POST https://auth.401522.xyz/v2/token.php
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=AUTHORIZATION_CODE
&redirect_uri=https://your-site.com/callback
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&code_verifier=YOUR_CODE_VERIFIER

响应示例

{
  "api_version": "v2",
  "request_id": "req_1a2b3c4d5e6f7a8b",
  "access_token": "a1b2c3d4e5f6…",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "r1e2f3a4b5c6…",
  "scope": "openid profile email",
  "id_token": "eyJhbGciOiJIUzI1NiIs…"
}

响应字段

字段类型说明
api_versionstring固定为 v2,用于区分 V1 响应
request_idstring本次请求的追踪 ID,排查问题时请一并提供
access_tokenstring访问令牌,放入 Authorization: Bearer 请求头使用
token_typestring令牌类型,固定为 Bearer
expires_ininteger访问令牌有效期(秒),默认 3600
refresh_tokenstring刷新令牌,用于换取新的令牌对
scopestring实际授予的权限范围
id_tokenstringID Token(JWT)。仅当 scope 含 openid 时返回
校验顺序:服务端会先完成全部校验再消费授权码(RFC 6749 §4.1.3)。因此 redirect_uri 写错或 code_verifier 传错时,授权码不会被作废,修正后仍可继续兑换。

错误响应

error_codeHTTP含义与处理建议
missing_parameter400缺少 client_id、grant_type、code 或 refresh_token 等必要参数
unsupported_grant_type400grant_type 不是 authorization_code 或 refresh_token
client_secret_invalid401client_secret 不正确
client_pending_review403应用尚未通过管理员审核
client_banned403应用已被封禁
code_invalid400授权码不存在
code_expired400授权码已过期(有效期 10 分钟)
code_used400授权码已被使用,每个授权码只能兑换一次
redirect_uri_mismatch400redirect_uri 与授权时不一致
pkce_required400公共客户端未携带 code_verifier
pkce_failed400code_verifier 缺失、格式非法或摘要不匹配
refresh_token_invalid400refresh_token 不存在
refresh_token_expired400refresh_token 已过期
refresh_token_used400refresh_token 已被使用,请重新授权
user_banned403用户账号已被封禁
user_not_approved403用户账号尚未通过审核

GET /v2/userinfo.php

#

OIDC 标准 UserInfo 端点。根据访问令牌返回用户身份信息,返回字段受 scope 控制。用户被封禁时返回 user_banned。

鉴权Authorization: Bearer ACCESS_TOKEN(也可用 access_token 查询参数传递,不推荐)。
完整地址https://auth.401522.xyz/v2/userinfo.php

请求参数

名称类型属性说明
access_token
HEADER
string可选访问令牌,推荐通过 Authorization: Bearer 请求头传递

请求示例

GET https://auth.401522.xyz/v2/userinfo.php
Authorization: Bearer ACCESS_TOKEN

响应示例

{
  "api_version": "v2",
  "request_id": "req_1a2b3c4d5e6f7a8b",
  "sub": "1",
  "name": "username",
  "preferred_username": "username",
  "email": "user@example.com",
  "email_verified": true,
  "role": "user",
  "created_at": "2025-01-01 10:00:00"
}

响应字段

字段类型说明
api_versionstring固定为 v2
request_idstring本次请求的追踪 ID
substring用户唯一标识(用户 ID 的字符串形式)
namestring用户名。scope 含 openid / profile / basic 时返回
preferred_usernamestring首选用户名。同上 scope 条件下返回
rolestring用户角色。同上 scope 条件下返回
created_atstring账号创建时间。同上 scope 条件下返回
emailstring邮箱地址。scope 含 email 时返回
email_verifiedboolean邮箱是否已验证。scope 含 email 时返回

错误响应

error_codeHTTP含义与处理建议
invalid_token401访问令牌不存在或格式错误
token_expired401访问令牌已过期,请用 refresh_token 刷新
token_revoked401访问令牌已被撤销,请重新授权
user_banned403用户账号已被封禁
user_not_approved403用户账号尚未通过审核

GET /v2/user.php

#

供服务端后台使用的应用级接口。与 UserInfo 不同,本接口必须同时携带 API KEY 与访问令牌,且令牌必须属于同一个 client_id,返回字段固定完整(不受 scope 控制)。

鉴权查询参数携带 client_id + api_key,请求头携带 Authorization: Bearer ACCESS_TOKEN。
完整地址https://auth.401522.xyz/v2/user.php

请求参数

名称类型属性说明
client_id
QUERY
string必填应用 ID
api_key
QUERY
string必填应用级 API KEY,可在控制台「我的应用 → 编辑应用」查看
access_token
HEADER
string必填访问令牌,且必须属于该 client_id

请求示例

GET https://auth.401522.xyz/v2/user.php?client_id=YOUR_CLIENT_ID&api_key=YOUR_API_KEY
Authorization: Bearer ACCESS_TOKEN

响应示例

{
  "api_version": "v2",
  "request_id": "req_1a2b3c4d5e6f7a8b",
  "id": 1,
  "sub": "1",
  "username": "username",
  "name": "username",
  "email": "user@example.com",
  "email_verified": true,
  "role": "user",
  "created_at": "2025-01-01 10:00:00"
}

响应字段

字段类型说明
api_versionstring固定为 v2
request_idstring本次请求的追踪 ID
idinteger用户数字 ID
substring用户唯一标识(字符串形式)
usernamestring用户名
namestring显示名
emailstring邮箱地址
email_verifiedboolean邮箱是否已验证
rolestring用户角色
created_atstring账号创建时间

错误响应

error_codeHTTP含义与处理建议
missing_parameter400缺少 client_id 参数
api_key_missing401缺少 api_key 参数
api_key_invalid401API KEY 不正确
api_key_expired401API KEY 已过期,请在控制台重新生成
api_key_revoked401API KEY 已被轮换或作废,请使用新 KEY
api_key_mismatch401API KEY 与 client_id 不匹配
client_pending_review403应用尚未通过管理员审核
client_banned403应用已被封禁
invalid_token401访问令牌无效,或不属于该 client_id
user_banned403用户账号已被封禁

POST /v2/refresh.php

#

使用 refresh_token 换取新的令牌对。严格一次性轮换:刷新成功后旧 refresh_token 与旧 access_token 立即失效,若重复使用将返回 refresh_token_used。

鉴权client_id + client_secret(机密客户端),或 client_id + api_key(应用级调用),或仅 client_id(公共客户端)。也支持 Authorization: Basic。
完整地址https://auth.401522.xyz/v2/refresh.php

请求参数

名称类型属性说明
client_id
BODY
string必填应用 ID
refresh_token
BODY
string必填要刷新的 refresh_token
client_secret
BODY
string可选应用密钥。机密客户端必填(若未携带 api_key)
api_key
BODY
string可选应用级 API KEY,与 client_secret 二选一

请求示例

POST https://auth.401522.xyz/v2/refresh.php
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&refresh_token=YOUR_REFRESH_TOKEN
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET

响应示例

{
  "api_version": "v2",
  "request_id": "req_1a2b3c4d5e6f7a8b",
  "access_token": "n1e2w3t4k5j6…",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "n1r2e3f4r5e6…",
  "scope": "openid profile email"
}

响应字段

字段类型说明
api_versionstring固定为 v2
request_idstring本次请求的追踪 ID
access_tokenstring新的访问令牌
token_typestring固定为 Bearer
expires_ininteger访问令牌有效期(秒)
refresh_tokenstring新的刷新令牌,请立即替换本地副本
scopestring实际授予的权限范围
注意:用户被封禁时,服务端会在消费 refresh_token 之前就拒绝本次刷新,因此封号用户不会白白消耗掉刷新令牌。

错误响应

error_codeHTTP含义与处理建议
missing_parameter400缺少 client_id 或 refresh_token
client_secret_invalid401client_secret 不正确
api_key_expired401API KEY 已过期
api_key_revoked401API KEY 已被轮换或作废
refresh_token_invalid400refresh_token 不存在
refresh_token_expired400refresh_token 已过期,请重新授权
refresh_token_used400refresh_token 已被使用(一次性凭据),请重新授权
invalid_grant400refresh_token 与 client_id 不匹配
user_banned403用户账号已被封禁

POST /v2/revoke.php

#

撤销访问令牌或刷新令牌(RFC 7009)。符合规范:无论令牌是否存在、是否已被撤销,均返回 200,通过响应字段区分结果。

鉴权client_id + client_secret,或 client_id + api_key。也支持 Authorization: Basic。
完整地址https://auth.401522.xyz/v2/revoke.php

请求参数

名称类型属性说明
token
BODY
string必填要撤销的访问令牌或刷新令牌
client_id
BODY
string必填应用 ID
client_secret
BODY
string可选应用密钥。机密客户端必填(若未携带 api_key)
api_key
BODY
string可选应用级 API KEY,与 client_secret 二选一

请求示例

POST https://auth.401522.xyz/v2/revoke.php
Content-Type: application/x-www-form-urlencoded

token=TOKEN_TO_REVOKE
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET

响应示例

{
  "api_version": "v2",
  "request_id": "req_1a2b3c4d5e6f7a8b",
  "revoked": true,
  "changed": true,
  "status": "revoked"
}

响应字段

字段类型说明
api_versionstring固定为 v2
request_idstring本次请求的追踪 ID
revokedboolean该令牌当前是否处于失效状态(不存在时为 false)
changedboolean本次请求是否实际执行了撤销操作
statusstring撤销结果:revoked(本次撤销成功)/ already_revoked(此前已撤销)/ not_found(令牌不属于该应用)

错误响应

error_codeHTTP含义与处理建议
missing_parameter400缺少 token 或 client_id
client_secret_invalid401client_secret 不正确
api_key_invalid401API KEY 不正确
client_banned403应用已被封禁

POST /v2/introspect.php

#

查询令牌当前状态(RFC 7662)。同时支持访问令牌与刷新令牌;令牌不存在时返回 active: false 而非报错。

鉴权client_id + client_secret,或 client_id + api_key。也支持 Authorization: Basic。
完整地址https://auth.401522.xyz/v2/introspect.php

请求参数

名称类型属性说明
token
BODY
string必填要查询的访问令牌或刷新令牌
client_id
BODY
string必填应用 ID
client_secret
BODY
string可选应用密钥。机密客户端必填(若未携带 api_key)
api_key
BODY
string可选应用级 API KEY,与 client_secret 二选一

请求示例

POST https://auth.401522.xyz/v2/introspect.php
Content-Type: application/x-www-form-urlencoded

token=TOKEN_TO_INTROSPECT
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET

响应示例

{
  "api_version": "v2",
  "request_id": "req_1a2b3c4d5e6f7a8b",
  "active": true,
  "scope": "openid profile email",
  "client_id": "fusion_xxx",
  "username": "username",
  "token_type": "Bearer",
  "exp": 1735660800,
  "iat": 1735574400,
  "sub": "1",
  "status": "active"
}

响应字段

字段类型说明
api_versionstring固定为 v2
request_idstring本次请求的追踪 ID
activeboolean令牌当前是否有效
scopestring令牌携带的权限范围
client_idstring令牌所属应用
usernamestring令牌所属用户名(仅访问令牌返回)
token_typestring令牌类型:Bearer 或 refresh_token
expinteger过期时间(Unix 时间戳)
iatinteger签发时间(Unix 时间戳)
substring用户唯一标识
statusstring令牌状态:active / revoked / expired / not_found

错误响应

error_codeHTTP含义与处理建议
missing_parameter400缺少 token 或 client_id
client_secret_invalid401client_secret 不正确
api_key_invalid401API KEY 不正确
client_banned403应用已被封禁

GETPOST /v2/keys.php

#

查询 API KEY 状态、轮换(生成新 KEY,旧 KEY 立即失效)或作废(不生成新 KEY)。轮换时可选设置新 KEY 的有效期(天)。

鉴权client_id + api_key(自身凭据),或 client_id + client_secret(机密客户端可在服务端执行轮换)。也支持 Authorization: Basic。
完整地址https://auth.401522.xyz/v2/keys.php

请求参数

名称类型属性说明
client_id
QUERY
string必填应用 ID
api_key
QUERY
string条件必填API KEY。与 client_secret 二选一
client_secret
QUERY
string条件必填应用密钥。与 api_key 二选一
action
BODY
string可选POST 时的操作:rotate(轮换)/ revoke(作废)。缺省为 rotate
默认值 rotate
ttl_days
BODY
integer可选新 KEY 的有效期(天)。0 或不传表示永不过期

请求示例

# 查询状态
GET https://auth.401522.xyz/v2/keys.php?client_id=YOUR_CLIENT_ID&api_key=YOUR_API_KEY

# 轮换(30 天后过期)
POST https://auth.401522.xyz/v2/keys.php?client_id=YOUR_CLIENT_ID&api_key=YOUR_API_KEY
Content-Type: application/x-www-form-urlencoded

action=rotate&ttl_days=30

# 仅作废
POST https://auth.401522.xyz/v2/keys.php?client_id=YOUR_CLIENT_ID&api_key=YOUR_API_KEY
Content-Type: application/x-www-form-urlencoded

action=revoke

响应示例

{
  "api_version": "v2",
  "request_id": "req_1a2b3c4d5e6f7a8b",
  "rotated": true,
  "api_key": "sk_NEW_KEY_ONLY_SHOWN_ONCE",
  "api_key_masked": "sk_9f2c…7b41",
  "previous_key_revoked_at": 1730000000,
  "expires_at": 1732592000,
  "expires_in": 2592000,
  "notice": "新 API KEY 仅在本次响应中返回,请立即保存。旧 API KEY 已立即失效。"
}

响应字段

字段类型说明
api_versionstring固定为 v2
request_idstring本次请求的追踪 ID
rotatedboolean(轮换响应)是否已轮换
api_keystring(轮换响应)新 KEY,仅本次返回
api_key_maskedstring掩码后的 KEY,用于展示
previous_key_revoked_atinteger(轮换响应)旧 KEY 作废时间戳
expires_atinteger到期时间戳;null 表示永不过期
expires_ininteger剩余有效秒数
noticestring操作提示文案
statusstring(查询响应)KEY 状态:active / expired
client_namestring(查询响应)应用名称
created_atstring(查询响应)KEY 创建时间
ttl_daysinteger(查询响应)当前有效期设置(天)
轮换行为说明
  • 新 KEY 在响应中仅返回一次,请立即保存到服务端环境变量或密钥管理服务中。
  • 旧 KEY 立即失效,此时使用旧 KEY 调用将收到 api_key_revoked,能明确区分「KEY 被轮换」与「KEY 填错」。
  • ttl_days 为可选参数,指定新 KEY 的有效期(天);不传或传 0 表示永不过期。
  • 轮换操作不影响已签发的 Access Token / Refresh Token,它们各自独立到期。

错误响应

error_codeHTTP含义与处理建议
api_key_missing401缺少 api_key 或 client_secret
api_key_invalid401API KEY 不正确
api_key_expired401API KEY 已过期
api_key_revoked401API KEY 已被轮换或作废
api_key_mismatch401API KEY 与 client_id 不匹配
client_banned403应用已被封禁
unsupported_method405请求方法不是 GET 或 POST
invalid_request400action 不在 rotate / revoke 范围内,或该应用已无可用 KEY

GETPOST /v2/verify.php

#

支撑「网页 → intent → 安卓客户端 → 验证 → 回传网页」链路。共 4 个 action:ticket 申请一次性票据、verify 客户端提交令牌、status 网页轮询结果、check 网页服务端校验断言。

鉴权ticket / verify / check 需携带 client_id;verify 另需客户端持有的 access_token;status 需携带 ticket。
完整地址https://auth.401522.xyz/v2/verify.php

请求参数

名称类型属性说明
action
BODY
string必填操作类型:ticket / verify / status / check
client_id
BODY
string必填应用 ID
redirect_uri
BODY
string条件必填发起方网页回调地址,必须在该应用登记的白名单内。action=ticket 时必填
state
BODY
string可选防 CSRF 随机串,验证成功后随断言回传
nonce
BODY
string可选防重放随机串
scope
BODY
string可选请求的权限范围
ticket
BODY
string条件必填一次性票据。action=verify / status 时必填
access_token
BODY
string条件必填客户端通过授权流程获得的访问令牌。action=verify 时必填
assertion
BODY
string条件必填服务端签发的身份断言。action=check 时必填

请求示例

# ① 网页申请一次性票据
POST https://auth.401522.xyz/v2/verify.php
Content-Type: application/x-www-form-urlencoded

action=ticket&client_id=YOUR_CLIENT_ID
&redirect_uri=https://your-site.com/verify-callback
&state=RANDOM_STATE&nonce=RANDOM_NONCE

# ② 唤起安卓客户端(网页侧发起)
intent://oauth/verify?S.ticket=TICKET#Intent;
  scheme=fusionoauth;package=xyz.uoxvx.fusionoauth;end

# ③ 客户端提交令牌完成验证
POST https://auth.401522.xyz/v2/verify.php
Content-Type: application/x-www-form-urlencoded

action=verify&client_id=YOUR_CLIENT_ID
&ticket=TICKET&access_token=ACCESS_TOKEN

# ④ 网页服务端校验断言
POST https://auth.401522.xyz/v2/verify.php
Content-Type: application/x-www-form-urlencoded

action=check&client_id=YOUR_CLIENT_ID
&assertion=ASSERTION_FROM_STATUS

响应示例

{
  "api_version": "v2",
  "request_id": "req_1a2b3c4d5e6f7a8b",
  "ticket": "9f3c…7b41",
  "expires_in": 300,
  "intent_url": "intent://oauth/verify?S.ticket=9f3c…#Intent;scheme=fusionoauth;package=xyz.uoxvx.fusionoauth;end",
  "app_links_url": "https://your-host/android/verify.php?ticket=9f3c…"
}

响应字段

字段类型说明
api_versionstring固定为 v2
request_idstring本次请求的追踪 ID
ticketstring一次性票据,有效期 5 分钟,成功验证后立即作废
expires_ininteger票据剩余有效秒数
intent_urlstring唤起安卓客户端的 intent URL
app_links_urlstringApp Links 形式的唤起地址(推荐,系统校验通过后免选择弹窗)
verifiedboolean(verify / status 响应)验证是否已完成
assertionstring(status 响应)身份断言,供网页服务端调用 action=check 校验
substring(check 响应)用户唯一标识
usernamestring(check 响应)用户名
emailstring(check 响应)邮箱地址
安全模型:票据一次性、5 分钟过期;断言(assertion)有效期 120 秒且绑定 client_id(audience)与 state,网页服务端必须自行校验 state 并通过 action=check 换取用户身份,切勿直接信任前端传来的用户信息。

错误响应

error_codeHTTP含义与处理建议
missing_parameter400缺少 action、client_id 等必要参数
invalid_request400action 取值不在支持范围内
ticket_invalid400票据不存在或已被消费
ticket_expired400票据已过期(有效期 5 分钟)
ticket_consumed400票据已被使用,请重新申请
assertion_invalid400断言签名不匹配、已过期或 audience 不符
redirect_uri_mismatch400redirect_uri 未在应用登记的白名单内
invalid_token401客户端提交的 access_token 无效
client_banned403应用已被封禁
user_banned403用户账号已被封禁

GET /api/mobile/captcha.php

#

获取无状态图形验证码。返回签名令牌与图片,登录时需一并回传。令牌一次性使用,5 分钟过期。

鉴权无需鉴权
完整地址https://auth.401522.xyz/api/mobile/captcha.php

请求示例

GET https://auth.401522.xyz/api/mobile/captcha.php

响应示例

{
  "api_version": "mobile",
  "captcha_token": "eyJjIjoi…",
  "image": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0…",
  "svg": "<svg xmlns=…</svg>",
  "expires_in": 300
}

响应字段

字段类型说明
captcha_tokenstring签名令牌。载荷只含随机盐与 HMAC,不含明文答案
imagestring验证码图片的 Data URI(SVG)
svgstring验证码图片的 SVG 源码
expires_ininteger有效期(秒),固定 300
令牌中不携带明文答案,客户端无法通过解码绕过人机验证;同一令牌仅可成功消费一次。

错误响应

error_codeHTTP含义与处理建议
unsupported_method405请求方法不是 GET

POST /api/mobile/login.php

#

使用用户名或邮箱 + 密码换取移动端令牌对。成功后令牌可用于调用全部移动端接口。

鉴权无需鉴权
完整地址https://auth.401522.xyz/api/mobile/login.php

请求参数

名称类型属性说明
account
BODY
string必填用户名或邮箱
password
BODY
string必填登录密码
captcha_token
BODY
string可选图形验证码令牌(平台开启人机验证时必填)
captcha
BODY
string可选用户输入的验证码字符
device
BODY
string可选设备标识,写入登录日志便于识别

请求示例

POST https://auth.401522.xyz/api/mobile/login.php
Content-Type: application/json

{
  "account": "yourname",
  "password": "your-password",
  "captcha_token": "eyJjIjoi…",
  "captcha": "A7K2",
  "device": "android/34 Pixel 8"
}

响应示例

{
  "api_version": "mobile",
  "access_token": "mat_9f3c7b41…",
  "refresh_token": "mrt_2e8d4a10…",
  "token_type": "Bearer",
  "expires_in": 2592000,
  "expires_at": 1793548800,
  "user": {
    "id": 12,
    "username": "yourname",
    "email": "you@example.com",
    "email_verified": true,
    "role": "user",
    "created_at": "2026-01-02 10:30:00",
    "is_admin": false
  }
}

响应字段

字段类型说明
access_tokenstring访问令牌,后续接口通过 Authorization: Bearer 携带
refresh_tokenstring刷新令牌,用于换取新的访问令牌
token_typestring固定为 Bearer
expires_ininteger访问令牌有效期(秒),固定 30 天
expires_atinteger访问令牌过期时间戳
userobject当前账号信息
user.idinteger账号 ID
user.usernamestring用户名
user.emailstring邮箱地址
user.email_verifiedboolean邮箱是否已验证
user.rolestring账号角色(user / admin)
user.is_adminboolean是否管理员(移动端不开放管理功能)
限流:同一 IP 每分钟 20 次、同一账号每分钟 10 次,超出返回 rate_limited。移动端令牌独立于 OAuth access_token,不会出现在「我的授权」列表中。

错误响应

error_codeHTTP含义与处理建议
missing_parameter400缺少 account 或 password
captcha_required400平台开启了人机验证但未提交验证码
captcha_invalid400验证码错误、已被使用或令牌签名不合法
captcha_expired400验证码已过期(有效期 5 分钟)
invalid_credentials401账号或密码错误(不区分具体原因,避免账号枚举)
account_disabled403账号已被停用
rate_limited429尝试过于频繁(同 IP 20 次/分钟,同账号 10 次/分钟)

POST /api/mobile/refresh.php

#

使用刷新令牌换取新的访问令牌。旧访问令牌立即失效。

鉴权无需鉴权(凭 refresh_token 换取)
完整地址https://auth.401522.xyz/api/mobile/refresh.php

请求参数

名称类型属性说明
refresh_token
BODY
string必填登录时获得的刷新令牌

请求示例

POST https://auth.401522.xyz/api/mobile/refresh.php
Content-Type: application/json

{
  "refresh_token": "mrt_2e8d4a10…"
}

响应示例

{
  "api_version": "mobile",
  "access_token": "mat_c8a0f180…",
  "token_type": "Bearer",
  "expires_in": 2592000,
  "expires_at": 1793548800
}

响应字段

字段类型说明
access_tokenstring新的访问令牌
token_typestring固定为 Bearer
expires_ininteger访问令牌有效期(秒)
expires_atinteger过期时间戳
刷新后旧访问令牌立即失效,客户端需同步替换本地存储的令牌。

错误响应

error_codeHTTP含义与处理建议
missing_parameter400缺少 refresh_token
refresh_token_invalid400刷新令牌无效或已被注销
refresh_token_expired400刷新令牌已过期,需重新登录

GET /api/mobile/dashboard.php

#

一次获取账号信息、统计数字、系统公告与最近应用,供客户端控制台首页渲染。

鉴权Bearer Token
完整地址https://auth.401522.xyz/api/mobile/dashboard.php

请求示例

GET https://auth.401522.xyz/api/mobile/dashboard.php
Authorization: Bearer mat_9f3c7b41…

响应示例

{
  "api_version": "mobile",
  "user": {
    "id": 12, "username": "yourname", "email": "you@example.com",
    "email_verified": true, "role": "user",
    "created_at": "2026-01-02 10:30:00", "is_admin": false
  },
  "stats": {
    "app_count": 3, "authorization_count": 12,
    "active_count": 9, "revoked_count": 3
  },
  "apps": [ { "id": 1, "name": "我的应用", "client_id": "fusion_…", "status_label": "正常" } ],
  "announcements": [
    { "title": "系统维护通知", "content": "本周六 02:00-04:00 进行维护。", "created_at": "2026-10-20 09:00:00" }
  ]
}

响应字段

字段类型说明
userobject当前账号信息
statsobject统计数字
stats.app_countinteger我的应用数量
stats.authorization_countinteger授权记录总数
stats.active_countinteger当前有效的授权数
stats.revoked_countinteger已过期或已撤销的授权数
appsarray最近 5 个应用概要
announcementsarray系统公告(最多 5 条)
令牌失效时客户端应先调用 /api/mobile/refresh.php 续期,失败再引导用户重新登录。

错误响应

error_codeHTTP含义与处理建议
invalid_token401令牌不存在
token_expired401令牌已过期,请刷新或重新登录
token_revoked401令牌已被注销
account_disabled403账号已被停用

GETPOST /api/mobile/apps.php

#

列出、新建、修改、轮换密钥、作废密钥与删除自己的应用。列表只返回掩码后的 API KEY。

鉴权Bearer Token
完整地址https://auth.401522.xyz/api/mobile/apps.php

请求参数

名称类型属性说明
action
BODY
string可选操作类型:list / create / update / rotate_key / revoke_key / delete,GET 时默认为 list
id
BODY
integer可选应用 ID(除 list 外均需要)
name
BODY
string可选应用名称(create / update 必填)
client_type
BODY
string可选应用类型:web / spa / app
redirect_uris
BODY
string可选回调地址,多个用换行或逗号分隔
homepage_url
BODY
string可选主页地址
description
BODY
string可选应用描述
app_package
BODY
string可选Android 包名(client_type=app 时必填)
app_sha256
BODY
string可选证书 SHA-256 指纹,用于 App Links 校验
ttl_days
BODY
integer可选新密钥有效期(天),0 表示永久

请求示例

POST https://auth.401522.xyz/api/mobile/apps.php
Authorization: Bearer mat_9f3c7b41…
Content-Type: application/json

{
  "action": "create",
  "name": "我的移动应用",
  "client_type": "app",
  "redirect_uris": "fusionoauth://oauth/callback",
  "app_package": "com.example.myapp"
}

响应示例

{
  "api_version": "mobile",
  "app": {
    "id": 5,
    "client_id": "fusion_Ll64HxtbD6yk2w352v4sw",
    "name": "我的移动应用",
    "client_type": "app",
    "client_type_label": "移动应用",
    "redirect_uris": ["fusionoauth://oauth/callback"],
    "app_package": "com.example.myapp",
    "api_key_masked": "sk_42933…f06b",
    "has_api_key": true,
    "status": "pending",
    "status_label": "待审核",
    "created_at": "2026-11-01 09:30:00"
  },
  "client_secret": "…",
  "api_key": "sk_429338a3a…",
  "notice": "应用创建成功,等待管理员审核通过后方可调用 API。…"
}

响应字段

字段类型说明
appsarray(list 响应)应用列表
totalinteger(list 响应)应用总数
appobject(create / update / 密钥操作响应)应用信息
app.api_key_maskedstring掩码后的 API KEY,形如 sk_42933…f06b
app.has_api_keyboolean是否已设置 API KEY
app.status_labelstring状态中文名:正常 / 待审核 / 已禁用
client_secretstring(create 响应)明文 Client Secret,仅此一次返回
api_keystring(create / rotate_key 响应)明文 API KEY,仅此一次返回
noticestring操作结果提示
deletedboolean(delete 响应)是否删除成功
密钥仅显示一次:创建与轮换时返回的明文 api_key 不会再次出现在列表中。轮换后旧 KEY 立即失效,使用旧 KEY 的调用会返回 api_key_revoked。所有操作严格限定在当前账号名下,无法操作他人应用。

错误响应

error_codeHTTP含义与处理建议
missing_parameter400缺少 id 等必要参数
invalid_request400参数校验失败(如回调地址非法、移动应用未填包名)
app_not_found404应用不存在或不属于当前账号
invalid_token401令牌无效或已过期

GETPOST /api/mobile/authorizations.php

#

列出自己的授权记录,撤销单条授权或撤销某应用的全部授权。

鉴权Bearer Token
完整地址https://auth.401522.xyz/api/mobile/authorizations.php

请求参数

名称类型属性说明
action
BODY
string可选操作类型:list / revoke / revoke_client,GET 时默认为 list
id
BODY
integer可选授权记录 ID(revoke 时必填)
client_id
BODY
string可选应用 Client ID(revoke_client 时必填)
p
QUERY
integer可选页码,默认 1
per_page
QUERY
integer可选每页条数,默认 20,上限 50

请求示例

POST https://auth.401522.xyz/api/mobile/authorizations.php
Authorization: Bearer mat_9f3c7b41…
Content-Type: application/json

{
  "action": "revoke",
  "id": 128
}

响应示例

{
  "api_version": "mobile",
  "authorizations": [
    {
      "id": 128,
      "client_id": "fusion_Ll64HxtbD6yk2w352v4sw",
      "app_name": "我的移动应用",
      "scope": "openid profile email",
      "created_at": "2026-10-28 14:20:00",
      "expires_at": "2026-11-27 14:20:00",
      "revoked": false,
      "expired": false,
      "active": true
    }
  ],
  "total": 12,
  "active_count": 9,
  "page": 1,
  "per_page": 20,
  "total_pages": 1
}

响应字段

字段类型说明
authorizationsarray授权记录列表
totalinteger授权记录总数
active_countinteger当前有效的授权数
pageinteger当前页码
per_pageinteger每页条数
total_pagesinteger总页数
authorizations[].activeboolean是否有效(未撤销且未过期)
authorizations[].scopestring授权时同意的范围
countinteger(revoke_client 响应)本次撤销的条数
撤销单条授权会同时作废其对应的 refresh_token;revoke_client 会一并清理该应用的授权关系记录。

错误响应

error_codeHTTP含义与处理建议
missing_parameter400缺少 id 或 client_id
not_found404授权记录不存在或不属于当前账号
invalid_token401令牌无效或已过期

POST /api/mobile/logout.php

#

注销当前移动端令牌,使其立即失效。

鉴权Bearer Token
完整地址https://auth.401522.xyz/api/mobile/logout.php

请求示例

POST https://auth.401522.xyz/api/mobile/logout.php
Authorization: Bearer mat_9f3c7b41…

响应示例

{
  "api_version": "mobile",
  "revoked": true
}

响应字段

字段类型说明
revokedboolean是否已注销
注销后同一令牌再次访问任何接口都会返回 token_revoked。

错误响应

error_codeHTTP含义与处理建议
unsupported_method405请求方法不是 POST

V2 错误码

V2 错误响应采用双层错误码结构:error 保持 OAuth2 标准语义(你的既有分支逻辑无需修改),error_code 提供细粒度业务原因(用于精确定位问题)。

{
  "api_version": "v2",
  "request_id": "req_1a2b3c4d5e6f7a8b",
  "error": "invalid_client",
  "error_code": "client_banned",
  "error_title": "应用已被封禁",
  "error_description": "应用「我的应用」已被封禁,当前状态:已封禁。无法调用 API,如有疑问请联系平台管理员。",
  "http_status": 403,
  "timestamp": 1730000000,
  "error_uri": "https://auth.401522.xyz/docs.php#v2-errors"
}

应用状态相关

error_codeHTTP标准 error含义与处理建议
client_not_found 401 invalid_client client_id 不存在,应用可能已被删除。检查应用配置。
client_pending_review 403 invalid_client 应用尚未通过管理员审核,暂时无法调用 API。等待审核通过后重试。
client_banned 403 invalid_client 应用已被封禁(状态为 disabled / banned)。请联系平台管理员。
client_disabled 403 invalid_client 应用已被停用,请检查应用状态或联系管理员恢复。
client_secret_invalid 401 invalid_client client_secret 不正确,请检查应用配置。
unauthorized_client 403 unauthorized_client 该客户端无权执行此操作(如用 API KEY 访问不支持的端点)。

API KEY 相关

error_codeHTTP标准 error含义与处理建议
api_key_missing 401 invalid_client 缺少 api_key 参数,请在请求中携带应用级 API KEY。
api_key_invalid 401 invalid_client API KEY 不正确,请核对 client_id 与 api_key 是否匹配。
api_key_mismatch 401 invalid_client API KEY 与 client_id 不匹配,请确认二者属于同一应用。
api_key_expired 401 invalid_client API KEY 已过期(超出有效期),请在控制台或 /v2/keys.php 中重新生成。
api_key_revoked 401 invalid_client API KEY 已被轮换或手动作废,旧 KEY 不再生效。请使用新 KEY。

用户状态相关

error_codeHTTP标准 error含义与处理建议
user_banned 403 access_denied 用户账号已被封禁,无法完成授权或访问受保护资源。
user_not_approved 403 access_denied 用户账号尚未通过审核,暂时无法完成授权。
user_not_found 404 invalid_token 用户不存在或已注销。
user_not_logged_in 401 login_required 用户未登录(prompt=none 场景下静默授权失败)。

授权与凭证相关

error_codeHTTP标准 error含义与处理建议
invalid_request 400 invalid_request 缺少参数或参数不合法。
missing_parameter 400 invalid_request 缺少必要参数(如 code、client_id、refresh_token)。
unsupported_method 405 invalid_request 端点不支持当前请求方法,请使用文档标注的方法。
unsupported_grant_type 400 unsupported_grant_type 不支持的 grant_type。
redirect_uri_mismatch 400 invalid_request redirect_uri 与授权时不一致。
pkce_required 400 invalid_request 公共客户端(App / SPA)必须使用 PKCE。
pkce_failed 400 invalid_grant code_verifier 校验失败,检查生成与传输过程。
invalid_grant 400 invalid_grant 授权凭证无效(如授权码或刷新令牌与 client_id 不匹配)。
code_invalid 400 invalid_grant 授权码不存在,请检查是否复制完整。
code_expired 400 invalid_grant 授权码已过期(有效期 10 分钟),请重新发起授权。
code_used 400 invalid_grant 授权码已被使用,每个授权码只能兑换一次。
refresh_token_invalid 400 invalid_grant refresh_token 不存在。
refresh_token_expired 400 invalid_grant refresh_token 已过期,请重新授权。
refresh_token_used 400 invalid_grant refresh_token 已被使用(一次性凭据),请重新授权。
invalid_token 401 invalid_token 访问令牌不存在或格式错误。
token_expired 401 invalid_token 访问令牌已过期,请使用 refresh_token 刷新。
token_revoked 401 invalid_token 访问令牌已被撤销,请重新授权获取。
insufficient_scope 403 insufficient_scope 权限范围不足。
consent_required 401 consent_required 需要用户授权(prompt=none 但用户尚未授权该应用)。
access_denied 403 access_denied 用户拒绝了授权。

安卓唤起验证相关

error_codeHTTP标准 error含义与处理建议
ticket_invalid 400 invalid_request 验证票据不存在或已被消费。
ticket_expired 400 invalid_request 验证票据已过期(有效期 5 分钟),请重新申请。
ticket_consumed 400 invalid_request 验证票据已被使用,请重新申请。
assertion_invalid 400 invalid_request 身份断言签名不匹配、已过期或 audience 不符。

移动端登录相关

error_codeHTTP标准 error含义与处理建议
invalid_credentials 401 invalid-credentials 账号或密码错误(不区分具体原因,避免账号枚举)。
captcha_required 400 invalid-request 平台开启了人机验证,但请求未提交验证码。
captcha_invalid 400 invalid-request 验证码错误、已被使用,或令牌签名不合法。请重新获取验证码。
captcha_expired 400 invalid-request 验证码已过期(有效期 5 分钟),请刷新后重试。
account_disabled 403 access-denied 账号已被停用,请联系平台管理员。
refresh_token_invalid 400 invalid-grant 刷新令牌无效或已被注销,请重新登录。
refresh_token_expired 400 invalid-grant 刷新令牌已过期,请重新登录。
app_not_found 404 not-found 应用不存在或不属于当前账号。
not_found 404 not-found 资源不存在或不属于当前账号。

限流 / 服务

error_codeHTTP标准 error含义与处理建议
rate_limited 429 slow_down 请求过于频繁,请稍后重试(响应含 Retry-After 头)。
server_error 500 server_error 服务端异常,可稍后重试。
以下为 V1 接口,即将停用 V1 已进入维护冻结期:功能不再更新、不再新增错误语义,且不再获得安全修复。 请尽快迁移到 V2,迁移方式见上方「V1 → V2 迁移」章节。

V1 端点

以下路径在过渡期内继续可用,但已不建议新接入。

Authorization Endpoint https://auth.401522.xyz/authorize.php
Token Endpoint         https://auth.401522.xyz/token.php
UserInfo Endpoint      https://auth.401522.xyz/api/userinfo.php
User Endpoint          https://auth.401522.xyz/api/user.php
Refresh Endpoint       https://auth.401522.xyz/api/refresh.php
Revocation Endpoint    https://auth.401522.xyz/api/revoke.php
Introspection Endpoint https://auth.401522.xyz/api/introspect.php
Discovery              https://auth.401522.xyz/.well-known/openid-configuration

V1 的请求参数、调用方式与 V2 完全一致,示例:

POST https://auth.401522.xyz/token.php
grant_type=authorization_code
&code=RETURNED_CODE
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET

GET https://auth.401522.xyz/api/userinfo.php
Authorization: Bearer ACCESS_TOKEN

兼容别名:/v1/token.php、/v1/userinfo.php、/v1/refresh.php、/v1/revoke.php、/v1/introspect.php 均等价于对应的 V1 端点。

V1 错误码

V1 仅返回 error 与 error_description,无法区分「应用被封禁」与「应用未审核」等具体原因。这是迁移到 V2 的主要动因之一。

error含义
invalid_request缺少参数或参数不合法(如公共客户端未使用 PKCE)
invalid_clientclient_id / client_secret 错误或应用被禁用
invalid_grant授权码或 refresh_token 无效、过期、已使用,PKCE 校验失败
unauthorized_client应用状态异常
access_denied用户拒绝授权
login_requiredprompt=none 但用户未登录
consent_requiredprompt=none 但用户尚未授权该应用
server_error服务端异常,可稍后重试

安全建议

  • 移动端与 SPA 一律使用 PKCE,不要在客户端硬编码 client_secret。
  • 校验 state,防止 CSRF;校验 ID Token 的 iss、aud、exp。
  • 回调地址使用 HTTPS;App Links 优先于自定义 Scheme。
  • Access Token 只存于内存或加密存储,refresh_token 轮换后立即替换本地副本。
  • API KEY 定期轮换(如每 30 天),并为轮换操作准备灰度切换方案。
  • 网页唤起验证场景中,断言仅在服务端校验,切勿在前端直接信任。
  • 发现泄漏时,在控制台「我的授权」立即撤销对应授权。