Skip to content

fix(setup): 登录失效时自动扫码并修复空回调白名单 - #1223

Merged
deepcoldy merged 3 commits into
deepcoldy:masterfrom
linvon:fix/open-platform-login-expiry
Sep 6, 2026
Merged

fix(setup): 登录失效时自动扫码并修复空回调白名单#1223
deepcoldy merged 3 commits into
deepcoldy:masterfrom
linvon:fix/open-platform-login-expiry

Conversation

@linvon

@linvon linvon commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

改了什么

  • 识别开放平台 Web session 的半失效形态:首页仍有 CSRF,但具体 console 接口返回 HTTP 401、error.Code=4101code=99991641 + error.LogoutReason=40please log in again
  • redirect 修复命中上述强信号时返回 login_required,让 Dashboard 弹出现有扫码框;显式扫码入口强制换新登录态,不再复用被 console 拒绝的旧 Cookie。扫码成功后沿用现有逻辑自动重试修复。
  • 兼容新建应用的真实 safe_setting 响应:白名单为空时服务端会省略 redirectURL 键。只有当 allowRefreshToken / ipWhiteList / safeServerDomain 三个同级字段都符合真实响应形状时,才将其视为空数组。
  • Dashboard 入口文案从「修复配置」改为「修复开放平台回调」,明确这不是修改 Botmux 本地配置。

为什么

真实链路连续命中两个问题:

  1. 本地 Cookie 在 ask.feishu.cn 粗检下仍像是有效的,开放平台 /app 也能返回 CSRF;但读 safe_setting 时才返回 HTTP 400 + 99991641 / LogoutReason=40 / Code=4101。旧逻辑把它压成单 Bot 的普通 failed,Dashboard 无法进入扫码分支。
  2. 重新扫码后,新建应用的读接口返回 code=0,但因白名单为空而省略 redirectURL。旧解析器把这当成「返回体不可识别」,为避免盲写而零写入,随后用户 OAuth 仍然报 20029。

安全与影响面

  • 仍保持「读线上现值 → 合并 → 全量写回」,不删用户已有回调地址。不符合完整 safe_setting 形状的缺字段响应仍返回 null 并零写入。
  • 通用顶层 code=99991641 不单独触发扫码;用负向用例锁住,避免把普通 console 故障误判成登录过期。
  • 强制换新 Cookie 只发生在用户明确打开的 Dashboard 扫码入口,不改普通 setup 的缓存复用逻辑。
  • 影响仅限 Feishu 开放平台 redirect 修复与 Dashboard 登录 UI;Lark 租户、API-only Bot、各 CLI/后端、会话 turn 与最终回复链路不受影响。

UI 文字示意

修改前:修复配置
修改后:修复开放平台回调

实际验证

  • npx -y bun@1.4.0 run build 通过(使用仓库钉住的 Bun 1.4.0)。
  • vitest --project unitopen-platform-* / setup-open-platform-* / feishu-login-manager / dashboard-session-group-tag-repair 共 8 个文件,242 条用例全绿。
  • 真实 Dashboard 路径:命中 4101 后弹出新二维码,扫码后生成新 Web session。
  • 真实新建应用:修复结果为 fixed;随后独立回读白名单,期望的 loopback 与 Dashboard OAuth callback 两条地址均已在线,且授权实际使用的 redirect_uri 与白名单一致。
  • git merge-tree --write-tree origin/master HEAD 通过,无冲突。

@linvon
linvon requested a review from deepcoldy as a code owner September 3, 2026 06:35
@deepcoldy

Copy link
Copy Markdown
Owner

感谢这个修复 👍 两个坑(console 半失效导致弹不出扫码框、新建应用省略 redirectURL 键导致零写入)都定位得很准,尤其「登录态是整批共用的,不能降级成某个 app 的 failed」这个设计判断我认为是对的。

自动评审这边跑下来没有发现阻断性问题,验证情况:

  • 基于最新 origin/master81433a720)本地 rebase,0 冲突;git merge-tree --write-tree 对当前 PR head 复验同样 0 冲突。
  • bun run build 绿、tsc --noEmit 干净;4 个改动测试文件 194/194 全绿(0 skip,it() 声明数与实跑数对得上);同族 open-platform / onboarding 6 个文件 110/110 绿。
  • 对新增的守卫做了变异测试,两条最关键的都被现有用例钉住了:把三字段形状校验削成裸 raw === undefined → 「读不到白名单时零写入,绝不盲写覆盖用户条目」等 3 条转红;把 99991641 && LogoutReason === 40 削成只看 99991641 → 「通用 console 故障不误弹扫码」转红。负向用例写得很到位。
  • 另外确认了一件事,供后续参考:即使构造「错误信封里回显了 data 三字段」这种形态,也走不到新分支——postJsoncode !== 0 检查会先抛 OpenPlatformApiError,所以 extractOpenPlatformRedirectUrls 只会面对服务端明确成功的响应。数据安全方向是稳的。

有两条非阻断的小建议,供你参考:

  1. 文案联动(建议改):按钮文案从「修复配置」改成「修复开放平台回调」之后,settings.oauthRedirectBaseHelp 里仍在指引用户去点「修复配置」/「Fix callback config」(src/dashboard/web/i18n.ts 第 1339 行中文、4018 行英文,这段 help 实际渲染在 settings-page.tsx:1613)。用户按提示在界面上会找不到这个名字,顺手改一行就能对齐。

  2. 加一行日志(可选):新的「redirectURL 键省略 ⟹ 视为空集 ⟹ 真的发出写请求」这条分支目前没有任何日志。它依赖的是飞书服务端「空列表就省略该键」的约定,而这条推断没有回读校验兜底——万一将来服务端改了约定,线上会静默走错分支且不好回溯。加一句 logger 是比较便宜的保险。

以上是自动评审的初步意见,最终以维护者审阅为准

评审跟进两处小改:

- `settings.oauthRedirectBaseHelp` 的中英文案仍指引用户去点「修复配置」/
  "Fix callback config",而该按钮已改名为「修复开放平台回调」。用户按提示在
  界面上找不到这个名字,改为与按钮当前标签逐字一致。
- `extractOpenPlatformRedirectUrls` 里「redirectURL 键缺失 ⟹ 视为空白名单」
  这条分支是从服务端「空列表就省略该键」的约定**推断**出来的,而不是读到了
  `[]`,且没有回读校验兜底。补一条 info 日志,让约定变更导致的白名单异常
  事后能追回到这次推断。

验证:`bun run build` 通过、`tsc --noEmit` 无错;`open-platform-*` /
`setup-open-platform-*` / `feishu-login-manager` /
`dashboard-session-group-tag-repair` / `settings-oauth-redirect-base-ui`
共 5 个文件 204 条用例全绿。探针确认日志只在「键缺失」这一条分支打印,
显式 `[]`、非空列表、以及 `{code:0}` 不可识别三种输入均不打印。

Co-Authored-By: Claude Code <noreply@anthropic.com>

@deepcoldy deepcoldy left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

首审 + 复审均无阻断项,评审提出的两条非阻断建议(回调文案死指引、省略键推断补日志)已直接补在 68e512027

验证:bun run build / tsc --noEmit 通过;open-platform-* / setup-open-platform-* / feishu-login-manager / dashboard-session-group-tag-repair / settings-oauth-redirect-base-ui 共 5 个文件 204 条用例全绿;对新增守卫做了变异测试,三字段形状校验与 LogoutReason 组合判定均被现有用例钉住。已基于最新 master rebase 复验无冲突,并核对合并树同时保留了双方改动。

CI 必需检查 build 绿;bun-test 腿的单点红为既有问题(plugin-card-action-gateway 在无任何 PR 的 master 提交上以逐字相同的断言失败),该腿 continue-on-error: true 且不在必需状态检查内,与本 PR 无关。

@deepcoldy
deepcoldy merged commit 80474f4 into deepcoldy:master Sep 6, 2026
3 of 4 checks passed
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown

🚀 Released in v3.19.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants