RankHub

权限范围与可用 API

17 个 scope 与它们解锁的接口族、第三方与第一方的能力边界、令牌能在哪些域名上调用,以及 scope 不够时会看到什么。

Scope 目录

授权页上给用户看的中文文案由 scope 决定 —— 申请得越多,用户越可能点「拒绝」。

scope授权页文案能拿到什么
openid身份标识sub 与 id_token
profile基本资料显示名等公开资料
email邮箱用户邮箱与验证状态(绑定了才有)
phone手机号用户手机号与验证状态(绑定了才有)
offline_access离线访问语义上的长期续期(实际授权码总会发 refresh token)
profile:read / profile:write个人资料 · 读取 / 管理/v0/auth/me、收藏、动态、头像横幅上传
account_security:read / :write账号安全 · 读取 / 管理会话列表、MFA、Passkey、邮箱/手机换绑
game:read / game:write游戏资料 · 读取 / 管理/v1/games/**(档案、成绩、最佳成绩、推数据、删除申请)
social:read / social:write社区与社交 · 读取 / 管理谱面评论(过渡期还在 /v0/social/**);社交面本身只服务第一方
event:read / event:write赛事 · 读取 / 管理当前无可用接口(赛事模块未启用)
development:read / development:write开发者应用 · 读取 / 管理/v1/developer/**(你自己的 API Key / OAuth 应用 / 统计)

Scope 与接口族的对应

scope 域接口族例子
profile/v0/auth/me、/v0/collections/me/**、/v0/activities/**、/v0/assets/uploads/**GET /v0/auth/me
account_security/v0/auth/me/sessions**、/v0/auth/me/email、/v0/auth/me/phone、/v0/mfa/**、/v0/passkeys**GET /v0/auth/me/sessions
game/v1/games/**GET /v1/games/maimai/profiles
social/v0/social/**(谱面评论过渡例外)给谱面写评论
development/v1/developer/**GET /v1/developer/oauth-apps

写操作需要对应的 :write;有 :write 就隐含 :read(只判 read 的接口也放行)。

每个接口的具体读写语义、请求体与响应示例见业务 API 总览。

account_security 的写操作要求浏览器会话

撤销会话、改密码、换绑邮箱/手机号这类操作不接受第三方令牌,即使你有 account_security:write:服务端会回 403 This endpoint requires a browser session。 这类操作只能由用户在 RankHub 自己的页面/App 上完成。

event:* 目前拿不到东西

赛事模块还没启用,event:read / event:write 现在申请了也没有接口可调。别申请。

game:read / game:write 的边界

这两个 scope 是游戏数据的全部权限,但它们只在 /v1/games/** 上生效, 而且不越过"仅第一方"的线:

你想要的第三方应用怎么做
读授权用户的档案 / 成绩 / 最佳成绩GET /v1/games/**,需要 game:read
建档案、推成绩POST /v1/games/{game}/profiles、POST .../{profileId}/scores,需要 game:write
删档案不能删,只能 POST .../deletion-requests 由用户确认
从游戏平台导入 / 同步做不到 —— 需要用户凭据,只能由用户在 RankHub 内完成
读别人的公开档案做不到 —— 社交面本期只服务第一方

game:write 覆盖 game:read,但不会把上面两个"做不到"变成能做到:

仅第一方的形状第三方调用的结果
POST /v1/games/{game}/profiles/create(票据建档)403 game.firstPartyOnly
POST /v1/games/{game}/profiles/import403 game.firstPartyOnly
POST /v1/games/{game}/profiles/{profileId}/sync403 game.firstPartyOnly
/v1/tasks/**403 game.firstPartyOnly
/v1/games/maimai/relay/**(机台中转)403 game.firstPartyOnly
POST .../deletion-requests/{requestId}/decision(用户表态)403 game.firstPartyOnly
/v0/games/**、/v0/social/**403 game.firstPartyOnly(别名 / 评论为过渡例外)
直接 DELETE 档案403 game.deletionConsentRequired

第一方(RankHub App 与浏览器会话)不受这张表的限制 —— 它本来就是"用户本人"在用。

补 scope 解决不了 403 game.firstPartyOnly

403 game.firstPartyOnly 是形状层面的拒绝,不是 scope 不足。 重新授权、加 game:write 都不会让它通过;请改用 /v1/games/** 上对第三方开放的形状。

过渡例外:别名与谱面评论

曲目别名与谱面评论的 v1 形状还没设计,所以这两族在过渡期继续留在 /v0, 第三方仍可调用(scope 仍是 game:read|write / social:read|write):

  • GET|POST /v0/games/{game}/song-aliases/**、.../proposals/**;
  • /v0/social/chart-reviews/**、/v0/social/posts/**/comments。

除此之外的 /v0/games/**、/v0/social/** 对第三方关闭。过渡期结束后这两族会迁到 v1, 届时会另行公告 —— 新代码不要围绕 /v0 的形状做长期设计。

调用方式

业务接口只有一个入口:https://api.rankhub.cc。

# 游戏档案(需要 game:read)
curl -s https://api.rankhub.cc/v1/games/maimai/profiles \
  -H "Authorization: Bearer $ACCESS_TOKEN"

# 开发者面(需要 development:read,返回 v1 信封)
curl -s https://api.rankhub.cc/v1/developer/oauth-apps \
  -H "Authorization: Bearer $ACCESS_TOKEN"

/v1/** 的响应带统一信封:

{
  "code": "common.ok",
  "message": "OK",
  "data": [],
  "requestId": "req_…"
}

/v0/** 的响应是直接的对象/数组(没有信封)。

只使用 api.rankhub.cc

业务接口只认 https://api.rankhub.cc。换成其他地址/端口会得到 401 —— 那不是 "令牌没生效",而是这个入口不参与令牌鉴权。不要把这些地址写进配置。

401 / 403 / 428 / 429 怎么区分

你会看到含义处理
401(无 body 细节)没带令牌 / 令牌无效 / 过期 / 已被撤销先刷新;刷新失败重新授权
403 + OIDC access token requires <scope>令牌有效,但缺这个 scope去开发者平台补 scope,用户需要重新授权(scope 变了旧令牌不会自动升级)
403 + game.firstPartyOnly这个形状只给第一方换用 /v1/games/** 上对第三方开放的形状,不要重试
403 + game.writeSuspended该应用的写权限被暂停(只拦写,读与登录不受影响)停下排查数据来源,联系平台恢复;换令牌也没用
403 + game.deletionConsentRequired想直接删档案改用 POST .../deletion-requests,由用户确认
403 + This endpoint requires a browser session该操作只允许浏览器会话换成让用户自己在 RankHub 里操作
428 + game.writeConfirmationRequired这次写入要用户先确认把 data.confirmation.approveUrl 给用户,确认后用 confirmationToken 重放同一份 payload
429 + common.rateLimited限流按 Retry-After 退避
503判定服务暂时不可用可重试,不要清用户会话

刷新后 scope 会变吗

不会自动变。刷新返回的 scope 是当初授权时授予的那一组。要新增 scope,必须让用户重新走一次授权 (新请求里带上新的 scope 列表),旧的 refresh token 不会因此升级权限。

CORS

  • 协议端点(auth.rankhub.cc 的 /v1/oauth/**、/v1/oidc/**):会反射请求的 Origin 并带 Access-Control-Allow-Credentials: true,所以浏览器可以直接调(换令牌、userinfo、撤销)。
  • 开发者 API(api.rankhub.cc/v1/developer/**):只允许白名单来源 (OPEN_ALLOWED_ORIGINS,生产含 https://open.rankhub.cc)。第三方网页不要指望直连它 —— 那是给开发者平台自己用的。
  • 业务接口(/v0/**、/v1/games/**)不保证对任意来源开放;需要浏览器直连的场景请先联系我们。

本页内容