认证中心 · 登录与应用授权 API
契约版本:1.2.2 · OpenAPI 3.1.1
覆盖 OAuth/OIDC 发现、授权、令牌、用户信息、撤销,以及软件授权激活、即时域名或设备绑定、查询和扣减。并非全部后台 API。servers 使用当前网站根路径,生产必须 HTTPS。OAuth 返回原始 JSON;/api/v1 使用 code/message/data 信封。所有示例都是虚构数据。
服务地址
/
认证方式
clientBasic
机密客户端 client_id / client_secret;也支持表单 client_secret_post
{
"type": "http",
"scheme": "basic",
"description": "机密客户端 client_id / client_secret;也支持表单 client_secret_post"
}
oauthAccess
Authorization: Bearer <access_token>;不可使用 id_token 或机器发布 token
{
"type": "oauth2",
"description": "Authorization: Bearer <access_token>;不可使用 id_token 或机器发布 token",
"flows": {
"authorizationCode": {
"authorizationUrl": "/oauth/authorize",
"tokenUrl": "/oauth/token",
"refreshUrl": "/oauth/token",
"scopes": {
"openid": "稳定用户标识与 ID Token",
"profile": "显示名称 name",
"email": "邮箱与验证标志",
"offline_access": "刷新令牌",
"license:read": "查询本人应用授权",
"license:consume": "扣减本人应用用量",
"license:activate": "兑换激活码并管理本人在当前应用的即时授权绑定"
}
}
}
}
applicationKey
创建应用时显示的 API Key;仅存服务端
{
"type": "apiKey",
"in": "header",
"name": "X-API-Key",
"description": "创建应用时显示的 API Key;仅存服务端"
}
GET /.well-known/openid-configuration
获取 OIDC 配置
issuer 与所有端点均使用部署的 APP_ORIGIN。客户端应优先使用发现文档。
操作 ID:discoverOIDC
认证:公开,无凭据
响应
HTTP 200
OIDC 配置
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| issuer | string | 是 | |
| authorization_endpoint | string | 是 | |
| token_endpoint | string | 是 | |
| userinfo_endpoint | string | 是 | |
| revocation_endpoint | string | 是 | |
| jwks_uri | string | 是 | |
| response_types_supported | array | 条件 / 否 | |
| grant_types_supported | array | 条件 / 否 | |
| subject_types_supported | array | 条件 / 否 | |
| id_token_signing_alg_values_supported | array | 条件 / 否 | |
| scopes_supported | array | 条件 / 否 | |
| token_endpoint_auth_methods_supported | array | 条件 / 否 | |
| code_challenge_methods_supported | array | 条件 / 否 | |
| claims_supported | array | 是 |
{
"$ref": "#/components/schemas/Discovery"
}
GET /.well-known/jwks.json
获取 ID Token 验签公钥
操作 ID:getJWKS
认证:公开,无凭据
响应
HTTP 200
RSA 公钥集,无私钥
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| keys | array | 是 |
{
"type": "object",
"required": [
"keys"
],
"properties": {
"keys": {
"type": "array",
"items": {
"$ref": "#/components/schemas/JWK"
}
}
}
}
GET /oauth/authorize
浏览器发起授权码登录
该端点先跳转本站授权页面,参数在后续授权请求中校验;最终回调包含 code/state/iss 或 error/state/iss。code 有效期 60 秒且只能使用一次。state 必须核对。默认要求所有客户端使用 PKCE S256;申请 openid 必须提供 nonce。兼容例外见登录指南。
操作 ID:authorize
认证:公开,无凭据
参数
| 名称 | 位置 | 必需 | 说明与约束 |
|---|---|---|---|
| response_type | query | 是 | {"type":"string","enum":["code"]} |
| client_id | query | 是 | 应用的公开 Client ID,不是应用 UUID {"type":"string"} |
| redirect_uri | query | 是 | 与登记值精确一致,含路径编码 {"type":"string","format":"uri"} |
| scope | query | 是 | 空格分隔,必须在应用允许的范围内 {"type":"string","example":"openid profile email"} |
| state | query | 是 | 每次授权生成不可预测的随机值 {"type":"string","minLength":16,"maxLength":1024} |
| nonce | query | 条件 / 否 | 请求 openid 时必需;核对 ID Token nonce。仅显式启用兼容的机密客户端可省略 {"type":"string","minLength":16,"maxLength":512} |
| code_challenge | query | 条件 / 否 | 默认必需:BASE64URL(SHA256(code_verifier)),无填充;仅显式启用传统 OIDC 兼容的机密客户端可省略 {"type":"string"} |
| code_challenge_method | query | 条件 / 否 | 提供 challenge 时必需 {"type":"string","enum":["S256"]} |
| prompt | query | 条件 / 否 | none 可能回调 login_required 或 consent_required;login 重新验证密码 {"type":"string","enum":["none","consent","login"]} |
响应
HTTP 302
跳转本站授权页
响应头:
{
"Location": {
"schema": {
"type": "string"
},
"description": "本站 /authorize 与原始查询参数"
}
}
POST /oauth/token
交换授权码或刷新令牌
机密客户端使用 HTTP Basic(用户名 client_id、密码 client_secret)或表单认证;公开客户端只传 client_id。表单认证对应下列空 security 选项,仍须服务端校验。不要发送 JSON。刷新会轮换令牌,旧刷新令牌重放会撤销整个令牌族。access_token 为不透明字符串,不能当 JWT 解码。
操作 ID:exchangeToken
认证:clientBasic 或 公开客户端 / 表单认证,见接口说明
请求体(必需)
application/x-www-form-urlencoded
{
"oneOf": [
{
"$ref": "#/components/schemas/CodeExchange"
},
{
"$ref": "#/components/schemas/RefreshExchange"
}
]
}
响应
HTTP 200
原始 JSON,无 data 包装
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| access_token | string | 是 | 不透明访问令牌;放入 Authorization: Bearer |
| token_type | string | 是 | |
| expires_in | integer | 是 | 秒 |
| scope | string | 是 | 实际授权范围,空格分隔 |
| refresh_token | string | 条件 / 否 | 仅 offline_access 返回;受登录会话有效期限制,轮换后原子替换旧值 |
| id_token | string | 条件 / 否 | 仅 openid 返回,RS256 JWT 字符串;声明结构见 IDTokenClaims |
{
"$ref": "#/components/schemas/TokenResponse"
}
示例:
{
"access_token": "example-access-token",
"token_type": "Bearer",
"expires_in": 900,
"scope": "openid profile email",
"id_token": "example.header.signature"
}
HTTP 400
invalid_grant(含过期、重放、PKCE/回调不符)、unsupported_grant_type 或其他授权校验失败
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| error | string | 是 | OAuth 错误码 |
{
"$ref": "#/components/schemas/OAuthError"
}
示例:
{
"error": "invalid_grant"
}
HTTP 401
invalid_client:客户端不存在、禁用或凭据错误
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| error | string | 是 | OAuth 错误码 |
{
"$ref": "#/components/schemas/OAuthError"
}
HTTP 429
按 IP 限流,稍后重试;平台错误结构,不含 data
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
示例:
{
"code": 42900,
"message": "操作过于频繁,请稍后再试"
}
HTTP 503
OAuth 处理器返回 error;Redis 限流中间件返回 code/message。两种结构都须处理
application/json
{
"oneOf": [
{
"$ref": "#/components/schemas/OAuthError"
},
{
"$ref": "#/components/schemas/PlatformError"
}
]
}
GET /oauth/userinfo
查询用户信息 · 字段映射
使用 OAuth access_token,必须含 openid;始终返回 application_creator 布尔值,表示当前用户是否为当前应用的创建人。profile 返回 name,email 返回 email/email_verified。所有字段位于根对象。当前不返回 picture、avatar、nickname、id、username、preferred_username、roles、phone_number。请验证响应 sub 与已经验签的 ID Token sub 一致。
操作 ID:getUserInfo
认证:oauthAccess(openid)
响应
HTTP 200
根据 token 实际 scope 返回用户声明;没有申请的字段会缺省
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| sub | string | 是 | 稳定的用户 UUID;用户唯一标识映射填 sub,JSONPath 填 $.sub。跨 issuer 使用 iss + sub 关联;scope: openid |
| application_creator | boolean | 是 | 当前登录用户是否为当前 OAuth 应用的创建人。由服务端按 access_token 绑定的 application_id 与不可由用户提交的 owner_id 比较;可作为该应用的初始管理员依据,不代表认证中心平台管理员或其他应用权限;scope: openid |
| name | string | 条件 / 否 | 平台昵称,可变且不保证唯一;映射填 name / $.name;scope: profile |
| string | 条件 / 否 | 邮箱;映射填 email / $.email,不用作稳定用户 ID;scope: email | |
| email_verified | boolean | 条件 / 否 | 真实布尔值,可为 false;不要将未验证邮箱视为已验证身份;scope: email |
{
"$ref": "#/components/schemas/UserInfo"
}
仅 openid
{
"sub": "00000000-0000-4000-8000-000000000001",
"application_creator": false
}
openid profile email
{
"sub": "00000000-0000-4000-8000-000000000001",
"name": "示例用户",
"email": "person@example.test",
"email_verified": false,
"application_creator": true
}
HTTP 401
invalid_token:访问令牌失效、被撤销、会话失效或账号/应用停用
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| error | string | 是 | OAuth 错误码 |
{
"$ref": "#/components/schemas/OAuthError"
}
示例:
{
"error": "invalid_token"
}
HTTP 403
insufficient_scope:缺少 openid
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| error | string | 是 | OAuth 错误码 |
{
"$ref": "#/components/schemas/OAuthError"
}
示例:
{
"error": "insufficient_scope"
}
POST /oauth/revoke
撤销访问/刷新令牌所属令牌族
与 token 端点使用相同客户端认证。未知或已撤销的 token 仍返回 200 空正文;不会退出认证中心全部浏览器会话。token_type_hint 当前不参与处理。
操作 ID:revokeToken
认证:clientBasic 或 公开客户端 / 表单认证,见接口说明
请求体(必需)
application/x-www-form-urlencoded
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| token | string | 是 | 待撤销的访问或刷新令牌 |
| client_id | string | 条件 / 否 | 未用 Basic 时必需 |
| client_secret | string | 条件 / 否 | 未用 Basic 的机密客户端必需 |
{
"type": "object",
"required": [
"token"
],
"properties": {
"token": {
"type": "string",
"description": "待撤销的访问或刷新令牌"
},
"client_id": {
"type": "string",
"description": "未用 Basic 时必需"
},
"client_secret": {
"type": "string",
"description": "未用 Basic 的机密客户端必需"
}
}
}
响应
HTTP 200
成功,空正文
HTTP 401
invalid_client
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| error | string | 是 | OAuth 错误码 |
{
"$ref": "#/components/schemas/OAuthError"
}
HTTP 429
按 IP 限流,稍后重试;平台错误结构,不含 data
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
示例:
{
"code": 42900,
"message": "操作过于频繁,请稍后再试"
}
HTTP 503
OAuth 处理器返回 error;Redis 限流中间件返回 code/message。两种结构都须处理
application/json
{
"oneOf": [
{
"$ref": "#/components/schemas/OAuthError"
},
{
"$ref": "#/components/schemas/PlatformError"
}
]
}
POST /api/v1/auth/check
查询应用授权是否可用
API Key 只用于服务端、限制所属应用且应用须允许 license:read;OAuth token 还限制本人授权。不需要浏览器 Cookie/CSRF。HTTP 200 不表示授权有效,必须判断 data.valid。
操作 ID:checkLicense
认证:applicationKey 或 oauthAccess(license:read)
请求体(必需)
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| authorization_id | string | 是 | 具体软件授权 ID,不是应用 ID 或 client_id |
| binding_value | string | 条件 / 否 | 域名/设备型授权须传已验证绑定;其他类型可省略 |
{
"$ref": "#/components/schemas/LicenseInput"
}
示例:
{
"authorization_id": "00000000-0000-4000-8000-000000000002",
"binding_value": "example.test"
}
响应
HTTP 200
授权结果;not_found 时只含 valid/reason
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | object | 是 | |
| message | string | 是 | |
| data | object | 是 |
{
"type": "object",
"required": [
"code",
"message",
"data"
],
"properties": {
"code": {
"const": 0
},
"message": {
"type": "string"
},
"data": {
"$ref": "#/components/schemas/LicenseCheck"
}
}
}
示例:
{
"code": 0,
"message": "success",
"data": {
"valid": false,
"reason": "not_found"
}
}
HTTP 400
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
HTTP 403
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
HTTP 429
按 IP 限流,稍后重试;平台错误结构,不含 data
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
示例:
{
"code": 42900,
"message": "操作过于频繁,请稍后再试"
}
HTTP 503
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
POST /api/v1/auth/consume
按幂等键扣减用量
应用须允许 license:consume;OAuth 同时限制用户。幂等范围为 authorization_id + idempotency_key,同键同数量重试返回当前 used,同键不同数量返回 409。仅支持 metered 授权。
操作 ID:consumeLicense
认证:applicationKey 或 oauthAccess(license:consume)
请求体(必需)
application/json
{
"allOf": [
{
"$ref": "#/components/schemas/LicenseInput"
},
{
"type": "object",
"required": [
"quantity",
"idempotency_key"
],
"properties": {
"quantity": {
"type": "integer",
"minimum": 1,
"maximum": 1000000000
},
"idempotency_key": {
"type": "string",
"minLength": 8,
"maxLength": 128
}
}
}
]
}
示例:
{
"authorization_id": "00000000-0000-4000-8000-000000000002",
"quantity": 1,
"idempotency_key": "example-order-001"
}
响应
HTTP 200
累计用量,不是剩余额度
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | object | 是 | |
| message | string | 是 | |
| data | object | 是 |
{
"type": "object",
"required": [
"code",
"message",
"data"
],
"properties": {
"code": {
"const": 0
},
"message": {
"type": "string"
},
"data": {
"type": "object",
"required": [
"used"
],
"properties": {
"used": {
"type": "integer",
"format": "int64"
}
}
}
}
}
示例:
{
"code": 0,
"message": "success",
"data": {
"used": 1
}
}
HTTP 400
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
HTTP 403
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
HTTP 404
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
HTTP 409
授权不可用、额度不足、非按量授权或同键不同数量
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
HTTP 429
按 IP 限流,稍后重试;平台错误结构,不含 data
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
示例:
{
"code": 42900,
"message": "操作过于频繁,请稍后再试"
}
HTTP 503
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
POST /api/v1/authorizations/activate
为当前 OAuth 用户兑换软件授权激活码
仅接受用户 OAuth Access Token,不接受应用 API Key。认证中心从令牌确定用户和应用,并拒绝不属于该应用的激活码。浏览器工作台也使用同一路径,但采用站内会话与 CSRF。
操作 ID:activateAuthorization
认证:oauthAccess(license:activate)
请求体(必需)
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | string | 是 | 软件授权激活码;与通用码券不同 |
{
"$ref": "#/components/schemas/ActivationRequest"
}
示例:
{
"code": "AC-example-code"
}
响应
HTTP 200
已创建并归属当前用户的授权
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | object | 是 | |
| message | string | 是 | |
| data | object | 是 |
{
"type": "object",
"required": [
"code",
"message",
"data"
],
"properties": {
"code": {
"const": 0
},
"message": {
"type": "string"
},
"data": {
"$ref": "#/components/schemas/ActivationResult"
}
}
}
示例:
{
"code": 0,
"message": "success",
"data": {
"authorization_id": "00000000-0000-4000-8000-000000000002",
"license_key": "00000000-0000-4000-8000-000000000002",
"application_id": "00000000-0000-4000-8000-000000000003",
"auth_type": "domain",
"binding_limit": 1,
"subdomain_limit": 5,
"quota": 0
}
}
HTTP 400
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
HTTP 401
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
HTTP 403
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
HTTP 404
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
HTTP 409
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
HTTP 503
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
POST /api/v1/authorizations/{id}/bindings
为当前用户的软件授权添加设备或域名绑定
令牌用户和令牌应用必须同时与目标授权匹配。设备、根域名以及根域名下明确配置的子域名在绑定成功后立即生效,不需要 DNS 验证。
操作 ID:addAuthorizationBinding
认证:oauthAccess(license:activate)
参数
| 名称 | 位置 | 必需 | 说明与约束 |
|---|---|---|---|
| id | path | 是 | activate 返回的 authorization_id {"type":"string","format":"uuid"} |
请求体(必需)
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| binding_type | string | 是 | |
| binding_value | string | 是 | 域名不含协议、端口或路径;设备值由应用生成并保持稳定 |
| parent_binding_id | string | 条件 / 否 | 添加子域名时填写所属根域名的绑定 ID |
{
"$ref": "#/components/schemas/BindingRequest"
}
示例:
{
"binding_type": "domain",
"binding_value": "example.test"
}
响应
HTTP 200
绑定已创建
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | object | 是 | |
| message | string | 是 | |
| data | object | 是 |
{
"type": "object",
"required": [
"code",
"message",
"data"
],
"properties": {
"code": {
"const": 0
},
"message": {
"type": "string"
},
"data": {
"$ref": "#/components/schemas/BindingResult"
}
}
}
HTTP 400
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
HTTP 401
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
HTTP 403
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
HTTP 404
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
HTTP 409
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
HTTP 503
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
POST /api/v1/authorizations/{id}/bindings/{binding}/verify
兼容旧客户端确认域名绑定
兼容旧客户端保留的入口。确认目标属于当前用户和当前应用后立即将旧绑定设为有效,不查询 DNS;新客户端无需调用。
操作 ID:confirmLegacyAuthorizationDomainBinding
认证:oauthAccess(license:activate)
参数
| 名称 | 位置 | 必需 | 说明与约束 |
|---|---|---|---|
| id | path | 是 | activate 返回的 authorization_id {"type":"string","format":"uuid"} |
| binding | path | 是 | 创建绑定返回的绑定 ID {"type":"string","format":"uuid"} |
响应
HTTP 200
旧域名绑定已确认生效
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | object | 是 | |
| message | string | 是 | |
| data | object | 是 |
{
"type": "object",
"required": [
"code",
"message",
"data"
],
"properties": {
"code": {
"const": 0
},
"message": {
"type": "string"
},
"data": {
"type": "object",
"required": [
"verified"
],
"properties": {
"verified": {
"const": true
}
}
}
}
}
HTTP 400
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
HTTP 401
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
HTTP 403
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
HTTP 404
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
HTTP 409
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
HTTP 503
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
DELETE /api/v1/authorizations/{id}/bindings/{binding}
解绑设备或域名
受应用解绑冷却时间限制;移除根域名会级联移除其子域名。
操作 ID:removeAuthorizationBinding
认证:oauthAccess(license:activate)
参数
| 名称 | 位置 | 必需 | 说明与约束 |
|---|---|---|---|
| id | path | 是 | activate 返回的 authorization_id {"type":"string","format":"uuid"} |
| binding | path | 是 | 创建绑定返回的绑定 ID {"type":"string","format":"uuid"} |
响应
HTTP 200
解绑成功
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | object | 是 | |
| message | string | 是 | |
| data | null | 是 |
{
"type": "object",
"required": [
"code",
"message",
"data"
],
"properties": {
"code": {
"const": 0
},
"message": {
"type": "string"
},
"data": {
"type": "null"
}
}
}
HTTP 400
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
HTTP 401
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
HTTP 403
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
HTTP 404
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
HTTP 409
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
HTTP 503
400 输入错误;403 凭据/范围不符;404 授权不存在;503 服务不可用。错误 code 为 HTTP 状态 × 100
application/json
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
{
"$ref": "#/components/schemas/PlatformError"
}
数据结构字典
上文的 $ref 指向以下命名结构。条件字段以说明中的 scope 和流程为准。
UserInfo
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| sub | string | 是 | 稳定的用户 UUID;用户唯一标识映射填 sub,JSONPath 填 $.sub。跨 issuer 使用 iss + sub 关联;scope: openid |
| application_creator | boolean | 是 | 当前登录用户是否为当前 OAuth 应用的创建人。由服务端按 access_token 绑定的 application_id 与不可由用户提交的 owner_id 比较;可作为该应用的初始管理员依据,不代表认证中心平台管理员或其他应用权限;scope: openid |
| name | string | 条件 / 否 | 平台昵称,可变且不保证唯一;映射填 name / $.name;scope: profile |
| string | 条件 / 否 | 邮箱;映射填 email / $.email,不用作稳定用户 ID;scope: email | |
| email_verified | boolean | 条件 / 否 | 真实布尔值,可为 false;不要将未验证邮箱视为已验证身份;scope: email |
完整结构与约束:
{
"type": "object",
"required": [
"sub",
"application_creator"
],
"additionalProperties": false,
"properties": {
"sub": {
"type": "string",
"format": "uuid",
"description": "稳定的用户 UUID;用户唯一标识映射填 sub,JSONPath 填 $.sub。跨 issuer 使用 iss + sub 关联",
"x-scope": "openid",
"x-mapping": "用户唯一标识"
},
"application_creator": {
"type": "boolean",
"description": "当前登录用户是否为当前 OAuth 应用的创建人。由服务端按 access_token 绑定的 application_id 与不可由用户提交的 owner_id 比较;可作为该应用的初始管理员依据,不代表认证中心平台管理员或其他应用权限",
"x-scope": "openid",
"x-mapping": "当前应用创建人"
},
"name": {
"type": "string",
"description": "平台昵称,可变且不保证唯一;映射填 name / $.name",
"x-scope": "profile",
"x-mapping": "显示名称 / 昵称"
},
"email": {
"type": "string",
"format": "email",
"description": "邮箱;映射填 email / $.email,不用作稳定用户 ID",
"x-scope": "email",
"x-mapping": "邮箱"
},
"email_verified": {
"type": "boolean",
"description": "真实布尔值,可为 false;不要将未验证邮箱视为已验证身份",
"x-scope": "email",
"x-mapping": "邮箱已验证"
}
}
}
IDTokenClaims
这是对解码后的声明结构的说明,不是 token 接口中的嵌套 JSON。必须通过 JWKS 验签,并验证 iss/aud/exp/nonce、UserInfo sub 一致性。刷新响应通常没有 nonce,不要将它作为新登录。
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| iss | string | 是 | APP_ORIGIN |
| sub | string | 是 | |
| aud | string | 是 | client_id |
| iat | integer | 是 | 签发时间,Unix 秒 |
| exp | integer | 是 | 过期时间,Unix 秒,签发后 900 秒 |
| nonce | string | 条件 / 否 | 授权码请求中提供时返回;刷新时省略 |
| at_hash | string | 是 | access_token SHA256 左半段的 Base64URL |
| application_creator | boolean | 是 | 当前登录用户是否为 aud 所指应用的创建人;仅在验签并校验 iss、aud、exp、nonce 后用于该应用内的管理员判定,不代表平台管理员权限 |
| name | string | 条件 / 否 | profile scope |
| string | 条件 / 否 | email scope | |
| email_verified | boolean | 条件 / 否 | email scope |
完整结构与约束:
{
"type": "object",
"description": "这是对解码后的声明结构的说明,不是 token 接口中的嵌套 JSON。必须通过 JWKS 验签,并验证 iss/aud/exp/nonce、UserInfo sub 一致性。刷新响应通常没有 nonce,不要将它作为新登录。",
"required": [
"iss",
"sub",
"aud",
"iat",
"exp",
"at_hash",
"application_creator"
],
"properties": {
"iss": {
"type": "string",
"format": "uri",
"description": "APP_ORIGIN"
},
"sub": {
"type": "string",
"format": "uuid"
},
"aud": {
"type": "string",
"description": "client_id"
},
"iat": {
"type": "integer",
"description": "签发时间,Unix 秒"
},
"exp": {
"type": "integer",
"description": "过期时间,Unix 秒,签发后 900 秒"
},
"nonce": {
"type": "string",
"description": "授权码请求中提供时返回;刷新时省略"
},
"at_hash": {
"type": "string",
"description": "access_token SHA256 左半段的 Base64URL"
},
"application_creator": {
"type": "boolean",
"description": "当前登录用户是否为 aud 所指应用的创建人;仅在验签并校验 iss、aud、exp、nonce 后用于该应用内的管理员判定,不代表平台管理员权限"
},
"name": {
"type": "string",
"description": "profile scope"
},
"email": {
"type": "string",
"format": "email",
"description": "email scope"
},
"email_verified": {
"type": "boolean",
"description": "email scope"
}
}
}
TokenResponse
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| access_token | string | 是 | 不透明访问令牌;放入 Authorization: Bearer |
| token_type | string | 是 | |
| expires_in | integer | 是 | 秒 |
| scope | string | 是 | 实际授权范围,空格分隔 |
| refresh_token | string | 条件 / 否 | 仅 offline_access 返回;受登录会话有效期限制,轮换后原子替换旧值 |
| id_token | string | 条件 / 否 | 仅 openid 返回,RS256 JWT 字符串;声明结构见 IDTokenClaims |
完整结构与约束:
{
"type": "object",
"required": [
"access_token",
"token_type",
"expires_in",
"scope"
],
"properties": {
"access_token": {
"type": "string",
"description": "不透明访问令牌;放入 Authorization: Bearer"
},
"token_type": {
"type": "string",
"enum": [
"Bearer"
]
},
"expires_in": {
"type": "integer",
"const": 900,
"description": "秒"
},
"scope": {
"type": "string",
"description": "实际授权范围,空格分隔"
},
"refresh_token": {
"type": "string",
"description": "仅 offline_access 返回;受登录会话有效期限制,轮换后原子替换旧值"
},
"id_token": {
"type": "string",
"description": "仅 openid 返回,RS256 JWT 字符串;声明结构见 IDTokenClaims"
}
}
}
CodeExchange
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| grant_type | string | 是 | |
| code | string | 是 | 回调中的一次性授权码 |
| redirect_uri | string | 是 | 与发起授权的值完全一致 |
| code_verifier | string | 条件 / 否 | 默认必需,原始 PKCE verifier;仅未提交 challenge 且显式启用传统 OIDC 兼容的机密客户端可省略 |
| client_id | string | 条件 / 否 | 未用 Basic 时必需 |
| client_secret | string | 条件 / 否 | 未用 Basic 的机密客户端必需;公开客户端不携带 |
完整结构与约束:
{
"type": "object",
"required": [
"grant_type",
"code",
"redirect_uri"
],
"properties": {
"grant_type": {
"const": "authorization_code",
"type": "string"
},
"code": {
"type": "string",
"description": "回调中的一次性授权码"
},
"redirect_uri": {
"type": "string",
"format": "uri",
"description": "与发起授权的值完全一致"
},
"code_verifier": {
"type": "string",
"minLength": 43,
"maxLength": 128,
"description": "默认必需,原始 PKCE verifier;仅未提交 challenge 且显式启用传统 OIDC 兼容的机密客户端可省略"
},
"client_id": {
"type": "string",
"description": "未用 Basic 时必需"
},
"client_secret": {
"type": "string",
"description": "未用 Basic 的机密客户端必需;公开客户端不携带"
}
}
}
RefreshExchange
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| grant_type | string | 是 | |
| refresh_token | string | 是 | 上次返回的最新刷新令牌,不可并发复用 |
| client_id | string | 条件 / 否 | 未用 Basic 时必需 |
| client_secret | string | 条件 / 否 | 未用 Basic 的机密客户端必需 |
完整结构与约束:
{
"type": "object",
"required": [
"grant_type",
"refresh_token"
],
"properties": {
"grant_type": {
"type": "string",
"const": "refresh_token"
},
"refresh_token": {
"type": "string",
"description": "上次返回的最新刷新令牌,不可并发复用"
},
"client_id": {
"type": "string",
"description": "未用 Basic 时必需"
},
"client_secret": {
"type": "string",
"description": "未用 Basic 的机密客户端必需"
}
}
}
OAuthError
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| error | string | 是 | OAuth 错误码 |
完整结构与约束:
{
"type": "object",
"required": [
"error"
],
"properties": {
"error": {
"type": "string",
"description": "OAuth 错误码"
}
}
}
PlatformError
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | integer | 是 | |
| message | string | 是 |
完整结构与约束:
{
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer"
},
"message": {
"type": "string"
}
}
}
LicenseInput
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| authorization_id | string | 是 | 具体软件授权 ID,不是应用 ID 或 client_id |
| binding_value | string | 条件 / 否 | 域名/设备型授权须传已验证绑定;其他类型可省略 |
完整结构与约束:
{
"type": "object",
"required": [
"authorization_id"
],
"properties": {
"authorization_id": {
"type": "string",
"format": "uuid",
"description": "具体软件授权 ID,不是应用 ID 或 client_id"
},
"binding_value": {
"type": "string",
"description": "域名/设备型授权须传已验证绑定;其他类型可省略"
}
}
}
LicenseCheck
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| valid | boolean | 是 | |
| reason | string | 是 | 空字符串表示有效;not_found 也可能表示当前凭据不可见该授权 |
| expires_at | string,null | 条件 / 否 | null 表示没有到期时间;not_found 时省略 |
| quota | integer | 条件 / 否 | 总额度;not_found 时省略 |
| used | integer | 条件 / 否 | 已用额度;not_found 时省略 |
| auth_type | string | 条件 / 否 | 授权类型;not_found 时省略 |
完整结构与约束:
{
"type": "object",
"required": [
"valid",
"reason"
],
"properties": {
"valid": {
"type": "boolean"
},
"reason": {
"type": "string",
"enum": [
"",
"not_found",
"expired_or_cancelled",
"binding_not_verified",
"quota_exhausted"
],
"description": "空字符串表示有效;not_found 也可能表示当前凭据不可见该授权"
},
"expires_at": {
"type": [
"string",
"null"
],
"format": "date-time",
"description": "null 表示没有到期时间;not_found 时省略"
},
"quota": {
"type": "integer",
"format": "int64",
"description": "总额度;not_found 时省略"
},
"used": {
"type": "integer",
"format": "int64",
"description": "已用额度;not_found 时省略"
},
"auth_type": {
"type": "string",
"description": "授权类型;not_found 时省略"
}
}
}
JWK
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| kty | string | 是 | |
| use | string | 是 | |
| alg | string | 是 | |
| kid | string | 是 | 当前 primary;按 token kid 选公钥 |
| n | string | 是 | RSA modulus,Base64URL |
| e | string | 是 | RSA exponent,Base64URL |
完整结构与约束:
{
"type": "object",
"required": [
"kty",
"use",
"alg",
"kid",
"n",
"e"
],
"properties": {
"kty": {
"type": "string",
"enum": [
"RSA"
]
},
"use": {
"type": "string",
"enum": [
"sig"
]
},
"alg": {
"type": "string",
"enum": [
"RS256"
]
},
"kid": {
"type": "string",
"description": "当前 primary;按 token kid 选公钥"
},
"n": {
"type": "string",
"description": "RSA modulus,Base64URL"
},
"e": {
"type": "string",
"description": "RSA exponent,Base64URL"
}
}
}
Discovery
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| issuer | string | 是 | |
| authorization_endpoint | string | 是 | |
| token_endpoint | string | 是 | |
| userinfo_endpoint | string | 是 | |
| revocation_endpoint | string | 是 | |
| jwks_uri | string | 是 | |
| response_types_supported | array | 条件 / 否 | |
| grant_types_supported | array | 条件 / 否 | |
| subject_types_supported | array | 条件 / 否 | |
| id_token_signing_alg_values_supported | array | 条件 / 否 | |
| scopes_supported | array | 条件 / 否 | |
| token_endpoint_auth_methods_supported | array | 条件 / 否 | |
| code_challenge_methods_supported | array | 条件 / 否 | |
| claims_supported | array | 是 |
完整结构与约束:
{
"type": "object",
"required": [
"issuer",
"authorization_endpoint",
"token_endpoint",
"userinfo_endpoint",
"revocation_endpoint",
"jwks_uri",
"claims_supported"
],
"properties": {
"issuer": {
"type": "string",
"format": "uri"
},
"authorization_endpoint": {
"type": "string",
"format": "uri"
},
"token_endpoint": {
"type": "string",
"format": "uri"
},
"userinfo_endpoint": {
"type": "string",
"format": "uri"
},
"revocation_endpoint": {
"type": "string",
"format": "uri"
},
"jwks_uri": {
"type": "string",
"format": "uri"
},
"response_types_supported": {
"type": "array",
"items": {
"type": "string"
}
},
"grant_types_supported": {
"type": "array",
"items": {
"type": "string"
}
},
"subject_types_supported": {
"type": "array",
"items": {
"type": "string"
}
},
"id_token_signing_alg_values_supported": {
"type": "array",
"items": {
"type": "string"
}
},
"scopes_supported": {
"type": "array",
"items": {
"type": "string"
}
},
"token_endpoint_auth_methods_supported": {
"type": "array",
"items": {
"type": "string"
}
},
"code_challenge_methods_supported": {
"type": "array",
"items": {
"type": "string"
}
},
"claims_supported": {
"type": "array",
"items": {
"type": "string",
"enum": [
"sub",
"name",
"email",
"email_verified",
"application_creator"
]
}
}
}
}
ActivationRequest
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | string | 是 | 软件授权激活码;与通用码券不同 |
完整结构与约束:
{
"type": "object",
"additionalProperties": false,
"required": [
"code"
],
"properties": {
"code": {
"type": "string",
"minLength": 1,
"maxLength": 100,
"description": "软件授权激活码;与通用码券不同"
}
}
}
ActivationResult
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| authorization_id | string | 是 | 兼容字段,与 license_key 相同 |
| license_key | string | 是 | 接入应用保存并用于后续授权校验的许可证密钥 |
| application_id | string | 是 | |
| auth_type | string | 是 | |
| binding_limit | integer | 是 | |
| subdomain_limit | integer | 是 | |
| quota | integer | 是 |
完整结构与约束:
{
"type": "object",
"additionalProperties": false,
"required": [
"authorization_id",
"license_key",
"application_id",
"auth_type",
"binding_limit",
"subdomain_limit",
"quota"
],
"properties": {
"authorization_id": {
"type": "string",
"format": "uuid",
"description": "兼容字段,与 license_key 相同"
},
"license_key": {
"type": "string",
"format": "uuid",
"description": "接入应用保存并用于后续授权校验的许可证密钥"
},
"application_id": {
"type": "string",
"format": "uuid"
},
"auth_type": {
"type": "string",
"enum": [
"membership",
"subscription",
"domain",
"device",
"metered"
]
},
"binding_limit": {
"type": "integer",
"minimum": 0
},
"subdomain_limit": {
"type": "integer",
"minimum": 0
},
"quota": {
"type": "integer",
"format": "int64",
"minimum": 0
}
}
}
BindingRequest
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| binding_type | string | 是 | |
| binding_value | string | 是 | 域名不含协议、端口或路径;设备值由应用生成并保持稳定 |
| parent_binding_id | string | 条件 / 否 | 添加子域名时填写所属根域名的绑定 ID |
完整结构与约束:
{
"type": "object",
"additionalProperties": false,
"required": [
"binding_type",
"binding_value"
],
"properties": {
"binding_type": {
"type": "string",
"enum": [
"domain",
"device"
]
},
"binding_value": {
"type": "string",
"maxLength": 255,
"description": "域名不含协议、端口或路径;设备值由应用生成并保持稳定"
},
"parent_binding_id": {
"type": "string",
"format": "uuid",
"description": "添加子域名时填写所属根域名的绑定 ID"
}
}
}
BindingResult
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| id | string | 是 | |
| verified | boolean | 是 |
完整结构与约束:
{
"type": "object",
"additionalProperties": false,
"required": [
"id",
"verified"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"verified": {
"type": "boolean"
}
}
}