DivingFish:OAuth/Bearer 认证体系 #2

Open
opened 2026-08-20 09:31:57 +00:00 by KumaAgent · 0 comments
Member

背景

来自 DivingFish 实现 vs 文档偏移审查,这是当中信息量最大、也最需要谨慎评估的一块:oauth-api-document.md 描述的完整 OAuth/OIDC 授权服务器,实际上不在 df-backend(www.diving-fish.com 主站后端)这个仓库里——df-backend 自己只是这个外部 IdP 的一个客户端(网站 Cookie 登录用)+ 一个资源服务器(校验它签发的 Bearer token)。授权服务器本体运行在独立域名 auth.diving-fish.com,本次审查没有拿到它的源码,所以下面涉及"外部 IdP 到底长什么样"的部分只能按文档描述,可信度低于 df-backend 部分。

参考文档:

df-backend 源码(database/ 子目录):https://github.com/Diving-Fish/maimaidx-prober/tree/main/database

已确认存在、值得优先实现的部分(df-backend 源码复核过)

src/DivingFish 客户端库目前完全没有 Bearer/OAuth 支持,但下面这些资源服务器路由是真实在跑的,用 Authorization: Bearer <token>,与 Cookie、Import-Token 三选一等效:

  • GET /player/recordsGET /player/record(新版单曲查询,用 token 里的 sub 决定查谁,明确不接受 qq/username 参数)
  • GET /player/plate(已被 /player/recordsplate/version 过滤取代,路由自身注释标注仅为兼容保留)
  • POST /player/update_records_html@oauth_or_login_required("prober.records.write"):Cookie/Import-Token/Bearer 三选一,请求体是原始 HTML 文本)

来源:https://github.com/Diving-Fish/maimaidx-prober/blob/main/database/app.pyoauth_or_login_required 装饰器 + https://github.com/Diving-Fish/maimaidx-prober/blob/main/database/tools/oauth_rs.py(本地验签外部 IdP 签发的 RS256 JWT,检查 iss/aud/exp/scope,按配额限流)+ https://github.com/Diving-Fish/maimaidx-prober/blob/main/database/routes/maimai.py

需要外部 IdP 配合才能确认细节的部分(仅按文档,未验证)

  • OIDC 服务发现(.well-known/openid-configuration)——df-backend 作为客户端确实在消费它(discovery(),10 分钟缓存,校验 issuer),但角色是"用"不是"提供"
  • /oauth/authorize 授权码 + PKCE(S256)——df-backend 内部用同样的 PKCE 机制发起外部授权码请求,但这个端点本身应该在 auth.diving-fish.com
  • /oauth/token:df-backend 只用过 authorization_code 一种 grant_type 换 token;refresh_token/on-behalf-of/device_code 三种在 df-backend 仓库里找不到任何痕迹,是否存在于外部 IdP 未知
  • /oauth/device_authorization/oauth/revoke:完全没有线索,未知是否存在
  • /oauth/userinfo:df-backend 作为客户端确认调用过(用 Bearer 换 sub/preferred_username),证明外部确实存在这个端点且响应形状与文档一致
  • /oauth/logout:df-backend 本地有一个同名路由,但语义是"网站发起登出"(清本地 Cookie 后跳转外部 IdP 登出端点,且未传 id_token_hint/state),跟文档描述的"由授权服务器本身实现登出"不是一回事

来源:https://github.com/Diving-Fish/maimaidx-prober/blob/main/database/routes/oauth_login.py

已停止签发的旧凭证

Developer-Token 的申请/改级别接口(POST/PUT /developer_token)已被 df-backend 硬编码为恒定 410 Gone,提示改用 auth.diving-fish.com 的"应用"体系申请。src/DivingFish/DfDeveloperClient 完全建立在这条已关闭申请入口的旧凭证类型上——只有历史渠道拿到的旧 token 还能用。实现 Bearer 支持的同时,需要考虑 Developer-Token 路径的长期定位(是否保留、是否加废弃标注)。

来源:https://github.com/Diving-Fish/maimaidx-prober/blob/main/database/routes/public.py

建议的落地顺序

  1. 先实现资源服务器一侧(Bearer token 的携带 + 三选一鉴权,已被 df-backend 源码坐实的三个端点/四个路由)——收益明确,不依赖外部 IdP 的进一步信息。
  2. OIDC 客户端流程(发现文档、PKCE 授权码、token 换取、userinfo)需要先拿到或实测 auth.diving-fish.com 的行为,建议先起草一个针对 auth.diving-fish.com 的最小连通性验证,而不是直接按文档实现。

这个 issue 信息量大、且部分依赖外部未知项,标 状态:待拆片,建议由维护者视情况拆成"资源服务器 Bearer 支持"和"OIDC 客户端授权流程"两张子票。

## 背景 来自 DivingFish 实现 vs 文档偏移审查,这是当中信息量最大、也最需要谨慎评估的一块:`oauth-api-document.md` 描述的完整 OAuth/OIDC 授权服务器,实际上**不在 df-backend(www.diving-fish.com 主站后端)这个仓库里**——df-backend 自己只是这个外部 IdP 的一个客户端(网站 Cookie 登录用)+ 一个资源服务器(校验它签发的 Bearer token)。授权服务器本体运行在独立域名 `auth.diving-fish.com`,本次审查没有拿到它的源码,所以下面涉及"外部 IdP 到底长什么样"的部分只能按文档描述,可信度低于 df-backend 部分。 参考文档: - OAuth 接口文档:https://maimai.diving-fish.com/manual/docs/developer/oauth-api-document - OAuth 快速开始:https://maimai.diving-fish.com/manual/docs/developer/oauth-quickstart - 从 Developer-Token 迁移到 OAuth:https://maimai.diving-fish.com/manual/docs/developer/oauth-migration df-backend 源码(`database/` 子目录):https://github.com/Diving-Fish/maimaidx-prober/tree/main/database ## 已确认存在、值得优先实现的部分(df-backend 源码复核过) `src/DivingFish` 客户端库目前完全没有 Bearer/OAuth 支持,但下面这些资源服务器路由是真实在跑的,用 `Authorization: Bearer <token>`,与 Cookie、Import-Token 三选一等效: - `GET /player/records`、`GET /player/record`(新版单曲查询,用 token 里的 `sub` 决定查谁,明确不接受 `qq`/`username` 参数) - `GET /player/plate`(已被 `/player/records` 的 `plate`/`version` 过滤取代,路由自身注释标注仅为兼容保留) - `POST /player/update_records_html`(`@oauth_or_login_required("prober.records.write")`:Cookie/Import-Token/Bearer 三选一,请求体是原始 HTML 文本) 来源:https://github.com/Diving-Fish/maimaidx-prober/blob/main/database/app.py 的 `oauth_or_login_required` 装饰器 + https://github.com/Diving-Fish/maimaidx-prober/blob/main/database/tools/oauth_rs.py(本地验签外部 IdP 签发的 RS256 JWT,检查 `iss`/`aud`/`exp`/`scope`,按配额限流)+ https://github.com/Diving-Fish/maimaidx-prober/blob/main/database/routes/maimai.py ## 需要外部 IdP 配合才能确认细节的部分(仅按文档,未验证) - OIDC 服务发现(`.well-known/openid-configuration`)——df-backend 作为客户端确实在消费它(`discovery()`,10 分钟缓存,校验 issuer),但角色是"用"不是"提供" - `/oauth/authorize` 授权码 + PKCE(S256)——df-backend 内部用同样的 PKCE 机制发起外部授权码请求,但这个端点本身应该在 `auth.diving-fish.com` 上 - `/oauth/token`:df-backend 只用过 `authorization_code` 一种 grant_type 换 token;`refresh_token`/on-behalf-of/`device_code` 三种在 df-backend 仓库里找不到任何痕迹,是否存在于外部 IdP 未知 - `/oauth/device_authorization`、`/oauth/revoke`:完全没有线索,未知是否存在 - `/oauth/userinfo`:df-backend 作为客户端确认调用过(用 Bearer 换 `sub`/`preferred_username`),证明外部确实存在这个端点且响应形状与文档一致 - `/oauth/logout`:df-backend 本地有一个同名路由,但语义是"网站发起登出"(清本地 Cookie 后跳转外部 IdP 登出端点,且未传 `id_token_hint`/`state`),跟文档描述的"由授权服务器本身实现登出"不是一回事 来源:https://github.com/Diving-Fish/maimaidx-prober/blob/main/database/routes/oauth_login.py ## 已停止签发的旧凭证 `Developer-Token` 的申请/改级别接口(`POST`/`PUT /developer_token`)已被 df-backend 硬编码为恒定 `410 Gone`,提示改用 `auth.diving-fish.com` 的"应用"体系申请。`src/DivingFish/DfDeveloperClient` 完全建立在这条已关闭申请入口的旧凭证类型上——只有历史渠道拿到的旧 token 还能用。实现 Bearer 支持的同时,需要考虑 Developer-Token 路径的长期定位(是否保留、是否加废弃标注)。 来源:https://github.com/Diving-Fish/maimaidx-prober/blob/main/database/routes/public.py ## 建议的落地顺序 1. 先实现资源服务器一侧(Bearer token 的携带 + 三选一鉴权,已被 df-backend 源码坐实的三个端点/四个路由)——收益明确,不依赖外部 IdP 的进一步信息。 2. OIDC 客户端流程(发现文档、PKCE 授权码、token 换取、userinfo)需要先拿到或实测 `auth.diving-fish.com` 的行为,建议先起草一个针对 `auth.diving-fish.com` 的最小连通性验证,而不是直接按文档实现。 这个 issue 信息量大、且部分依赖外部未知项,标 `状态:待拆片`,建议由维护者视情况拆成"资源服务器 Bearer 支持"和"OIDC 客户端授权流程"两张子票。
Sign in to join this conversation.
No description provided.