member_center/docs/SCOPES.md
2026-07-07 13:51:30 +09:00

114 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# OAuth Scope 現況
本文只記錄目前程式已註冊與 seed 的 scope。Client Credentials 與 Authorization Code 實際核發的 scope 由 OAuth application `usage` 對應的 DB mapping 決定,不接受呼叫端自行擴權。修改預設 mapping 後,既有環境需執行 `sync-oauth-clients`
## 授權邊界
- `profile:*` 是 current-user scope資料主體固定為 access token 的 `sub`,不能查詢其他會員。
- Email 不是跨會員 lookup key目前沒有 by-email service API。
- Tenant scope 必須帶有效 `tenant_id`,且與 request/list tenant 相符;缺少或不符時 fail-closed。
- `.global` scope 不依賴 tenant claim只應授予平台級 confidential client。
- Superuser/Admin 後台權限不使用 OAuth scopes而使用 Web role + Admin Permission。
## Resource / Audience
| Resource | 預設 audience | Tenant | Scopes |
|---|---|---|---|
| `member_center_api` | `member_center_api` | scope 個別判定 | OIDC、`profile:*``newsletter:list.*``newsletter:subscriptions.*``newsletter:events.*` |
| `send_engine_api` | `send_engine_api` | 必須 | `newsletter:send.read``newsletter:send.write` |
| `file_access_api` | `file_access_api` | 必須 | `files:*` |
Token audience 由 scope → resource registry 計算。
## Scope Catalog
### OIDC
| Scope | 能力 |
|---|---|
| `openid` | OpenID Connect subject / ID token。 |
| `email` | Email claim。 |
| `profile` | 標準 OIDC profile scope實際會員 API 仍需細分的 `profile:*`。 |
### Current-user Profile
| Scope | 能力 |
|---|---|
| `profile:basic.read` | 讀取目前登入會員基本資料。 |
| `profile:basic.write` | 修改目前登入會員基本資料。 |
| `profile:addresses.read` | 讀取目前會員地址簿。 |
| `profile:addresses.write` | 新增、修改、刪除目前會員地址。 |
| `profile:subscriptions.read` | 讀取目前會員的電子報訂閱。 |
| `profile:subscriptions.write` | 取消目前會員自己的訂閱。 |
### Newsletter / Member Center
| Scope | Tenant 規則 | 能力 |
|---|---|---|
| `newsletter:list.read` | token tenant 必須擁有 list | 依 list 讀取訂閱名單。 |
| `newsletter:list.read.global` | 平台級 | 跨 tenant 讀取訂閱名單。 |
| `newsletter:subscriptions.read` | token tenant 必須擁有 list | 依 list + email 讀取訂閱偏好。 |
| `newsletter:subscriptions.write` | token tenant 必須擁有 list | 建立訂閱、簽發一般退訂 token、更新偏好。 |
| `newsletter:events.read` | 依 resource service 規則 | 讀取電子報事件;目前 Member Center 無直接 endpoint。 |
| `newsletter:events.write` | `tenant_id` 必須匹配 | Tenant 事件回寫、one-click token、disable subscription。 |
| `newsletter:events.write.global` | 平台級 | 跨 tenant 事件回寫、one-click token、disable subscription、webhook client mapping。 |
### Send Engine
| Scope | 能力 |
|---|---|
| `newsletter:send.write` | 在 Send Engine 建立/執行發送工作。 |
| `newsletter:send.read` | 在 Send Engine 讀取發送狀態。 |
上述 scope 的資源是 Send Engine不是 Member Center controller。
### File Access
| Scope | 能力 |
|---|---|
| `files:upload.write` | File Access service 上傳檔案。 |
| `files:download.read` | Access agent 呼叫 Member Center 驗證 delegated download token。 |
| `files:download.delegate` | 業務服務向 Member Center 簽發短效 download token。 |
| `files:metadata.read` | File Access service 讀取檔案 metadata。 |
| `files:delete` | File Access service 刪除檔案。 |
`files:upload.write``files:metadata.read``files:delete` 由 File Access service 驗證Member Center 目前只提供 delegated token issuing / validation。
## Client Usage 預設 Mapping
| Usage | Client 型態 / Tenant | 預設 scopes |
|---|---|---|
| `web_login` | public 或 confidential互動式登入 | `openid``email``profile`、全部 current-user `profile:*` |
| `tenant_api` | confidential必須綁 tenant | `newsletter:events.write``newsletter:list.read``newsletter:subscriptions.read/write`、全部 `profile:*` |
| `platform_service` | confidential可不綁 tenant | `newsletter:events.write.global``newsletter:list.read.global`、全部 `profile:*` |
| `send_api` | confidential必須綁 tenant | `newsletter:send.read/write` |
| `file_api` | confidential必須綁 tenant | 全部 `files:*` |
| `webhook_outbound` | 現有 webhook credential usage | `openid``email``profile``newsletter:events.write` |
Mapping seed 採完整集合同步:從預設 mapping 移除的 scope 會在 DB mapping 停用。個別 OAuth application permissions 由 Installer `sync-oauth-clients` 更新。
現有 `tenant_api` / `platform_service` mapping 雖包含 `profile:*`,但 current-user endpoint 仍要求 `sub` 對應實際會員Client Credentials principal 不能用這些 endpoint 查詢其他會員。目前沒有 S2S 會員資料 endpoint。
## Member Center Endpoint 對照
| Endpoint | Scope |
|---|---|
| `GET /user/profile` | `profile:basic.read` |
| `POST /user/profile` | `profile:basic.write` |
| `GET /user/addresses` | `profile:addresses.read` |
| `POST /user/addresses``DELETE /user/addresses/{id}` | `profile:addresses.write` |
| `GET /user/subscriptions` | `profile:subscriptions.read` |
| `POST /user/subscriptions/{id}/unsubscribe` | `profile:subscriptions.write` |
| `POST /newsletter/subscribe` | `newsletter:subscriptions.write` |
| `POST /newsletter/unsubscribe-token` | `newsletter:subscriptions.write` |
| `GET /newsletter/preferences` | `newsletter:subscriptions.read` |
| `POST /newsletter/preferences` | `newsletter:subscriptions.write` |
| `GET /newsletter/subscriptions` | `newsletter:list.read``.global` |
| `POST /newsletter/one-click-unsubscribe-token(s)` | `newsletter:events.write``.global` |
| `POST /subscriptions/disable` | `newsletter:events.write``.global` |
| `POST /integrations/send-engine/webhook-clients/upsert` | `newsletter:events.write.global` |
| `POST /file-access/download-tokens` | `files:download.delegate` |
| `POST /file-access/download-tokens/validate` | `files:download.read` |
以下端點依一次性 token 操作,不要求 OAuth scope`GET /newsletter/confirm``POST /newsletter/unsubscribe`。公開 auth endpointregister、forgot/reset、email verify亦不屬於 scope 授權模型。