feat(oauth): 账号名改从 zone.account 取,去掉 account-settings.read 依赖

实测确认 GET /zones 每个 zone 自带 account {id,name},该接口只需 zone.read,
因此账号 id 与账号名都不必再调 GET /accounts(account-settings.read)。
顺带修掉 account_id 旧字段在当前响应里已为 null 导致的降级路径取不到账号 id。

- RealCFApi.discover 只列 /zones,移除 listAccounts 与 accountSource
- scope 候选集去掉 account-settings.read;设置页移除「含账号名权限」按钮
- 设置页 Scope 说明与 docs/02、README 同步(补 User Details Read 的区别说明)
- 85/85 测试通过(新增 zone 带 account / 不带 account 两种断言)
This commit is contained in:
bigcode
2026-09-30 17:03:59 +08:00
parent 7a1625d575
commit 5b887908e2
8 changed files with 82 additions and 88 deletions
+20 -9
View File
@@ -67,12 +67,11 @@ Cloudflare 第三方 OAuth 客户端的 scope 是 **点号分隔** 的 `<group>.
是 **wrangler 的第一方简写**,第三方客户端请求会被一律拒绝(它只对第一方 client 生效)。权威列表是
`GET /client/v4/oauth/scopes`,选择器里是它的可勾选项。
本应用默认请求这四个(已在 Cloudflare 侧逐个验证可被接受):
本应用默认只请求这三个(已在 Cloudflare 侧逐个验证可被接受):
| scope id | 选择器里的名称 | 用途 |
| --- | --- | --- |
| `account-settings.read` | Account Settings Read | 列出账号(拿账号名) |
| `zone.read` | Zone Read | 发现该账号下的域名 |
| `zone.read` | Zone Read | 发现该账号下的域名,并顺带拿到账号 id 与账号名 |
| `workers-scripts.write` | Workers Scripts Edit | 上传账号级 Email Worker 脚本 |
| `email-routing-rule.write` | Email Routing Rules Edit | 开启 Email Routing + 配置 catch-all 规则 |
@@ -84,11 +83,23 @@ Cloudflare 第三方 OAuth 客户端的 scope 是 **点号分隔** 的 `<group>.
- **客户端注册的 scope 是上限,不是默认值**。App 里没勾的权限,即使账号本身有,授权时也不会生效;
反过来请求里不写某个 scope,即使 App 勾了也不会被授予。
### 缺少账号级读权限时的降级(2026-09-30 实测后加入)
### 账号级读权限:不需要(2026-09-30 实测)
若 App 没有勾 `account-settings.read`,`GET /accounts` 会 403。Console 会自动降级:直接列 token 可见的
`/zones`,用 zone 自带的 `account_id` 反推目标账户,账号展示名用第一个域名代替(如 `example.com 等 3 个域名`)。
因此**只勾 `zone.read` + `workers-scripts.write` + `email-routing-rule.write` 也能完成接入**,只是账号名显示为域名。
`GET /zones` 的每个 zone 自带 `account: {id, name}`,而该接口的 Accepted Permission 只有 Zone Read。
所以账号 id 和账号名都能从 zone 上直接读到:
- **不需要 `account-settings.read`** —— 它只覆盖 `GET /accounts`(列账号),本应用不再调这个接口;
- **不需要 `user-details.read`** —— 那是读「授权的那个人」(`/user`),跟 Cloudflare 账号无关。
实测该账号的 `GET /zones` 响应:
```json
{ "id": "...", "name": "adx9.com",
"account": { "id": "bf8cd983e6dfd171c1881b00b512ed5a", "name": "Phptits@msn.com's Account" } }
```
注意 `account_id` 这个旧字段在当前响应里已经是 `null`,读账号必须走 `account.id`。zone 上没有 `account`
时(非标响应)才回退:用 `account_id` + 第一个域名展示(如 `example.com 等 3 个域名`)。
## 授权配置自检(不用开浏览器)
@@ -109,8 +120,8 @@ Cloudflare 第三方 OAuth 客户端的 scope 是 **点号分隔** 的 `<group>.
`preflight` 在收到 `invalid_scope` 时会自动跑完这个探测,并在结果里返回:
```json
"scopes": { "allowed": ["zone.read", "workers-scripts.write"],
"denied": ["account-settings.read"], "probed": true, "note": null }
"scopes": { "allowed": ["zone.read", "workers-scripts.write", "email-routing-rule.write"],
"denied": ["zone-settings.read"], "probed": true, "note": null }
```
设置页把两列分别渲染成绿色/橙色标签,「待勾选」列就是需要在 OAuth App 选择器里补上的权限。