template-monorepo/internal/model/auth/SDD.md

310 lines
9.9 KiB
Markdown
Raw Permalink 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.

# Auth Service
# Auth Service — SRS/SDD Document
| Version | Version Date | Editor | Memo |
|---------|--------------|--------|------|
| 1.0.0 | 2026/05/21 | Gateway Team | 初版Gateway Auth 模組 SDD |
---
## 1. Introduction
### 1.1 Purpose
Auth 模組為 TianTing Gateway 的**認證領域層**提供租戶範圍內的原子化認證原語邀請碼、註冊稽核、OAuth 暫存 Session、CloudEP JWT 簽發/刷新/登出。完整 HTTP 流程由 `internal/logic/auth/` 編排,並與 ZITADEL身份、Member會員、Notification通知協作。
### 1.2 Scope
**範圍內:**
- 租戶邀請碼Validate / Consume
- 註冊稽核 metadata條款版本、渠道、行銷 opt-in
- OAuth 社交註冊/登入暫存 SessionRedis
- CloudEP JWT access / refresh token 生命週期
- JWT 黑名單與 jti pair 管理
**範圍外(委派其他模組):**
- 使用者身份建立 → ZITADEL
- 會員 profile、OTP → Member 模組
- 郵件/簡訊 → Notification 模組
- RBAC 授權 → Permission 模組 + Casbin middleware
### 1.3 Definitions, Acronyms, and Abbreviation
| 縮寫 | 說明 |
|------|------|
| **JWT** | JSON Web TokenCloudEP 自簽 access / refresh token |
| **JTI** | JWT ID用於黑名單與 pair 映射 |
| **ROPG** | Resource Owner Password Grant密碼登入 |
| **OIDC** | OpenID Connect社交登入SSO |
| **OTP** | One-Time Password由 Member 模組管理 |
| **Tenant** | 租戶,多租戶隔離單位 |
| **UID** | 租戶內可讀會員識別碼(如 `ACME-10000003` |
### 1.4 Technologies to be used
| 項目 | 技術 |
|------|------|
| Application Language | Go 1.22+ |
| Framework | go-zero (`rest`, `logx`, `stores/redis`) |
| Cache / Session | Redis |
| Database | MongoDB |
| JWT | `github.com/golang-jwt/jwt/v4`HS256 |
| Identity Provider | ZITADEL`internal/library/zitadel` |
| API Codegen | goctl / `.api` 檔 |
### 1.5 Overview
Auth 模組採 Clean Architecture 分層:`domain/` 定義介面與實體,`repository/` 實作 Mongo / Redis 適配器,`usecase/` 提供原子 UseCase。HTTP handler 不直接存取 repository而是由 logic 層串接 ZITADEL + Member + Auth 原語。
主要流程:
1. **Email 註冊**Consume invite → ZITADEL 建 user → Member 建 unverified → 發 OTP → confirm 後 Activate + IssuePair
2. **密碼登入**ZITADEL ROPG → 查 Member → IssuePair
3. **社交註冊/登入**Redis Session 暫存 OAuth state → callback 換 token → Provision / Login
4. **Token 刷新/登出**Refresh 黑名單舊 pair 後重簽Logout 黑名單 access + refresh jti
---
## 2. System Overview
Auth 模組是 Gateway 認證子系統的核心,負責:
- 控制誰可以註冊(邀請碼)
- 記錄註冊合規稽核
- 管理短期 OAuth 流程狀態
- 簽發與驗證 CloudEP JWTmiddleware `AuthJWT`
對外透過 `/api/v1/auth/*` REST API 暴露JWT 驗證後將 `(tenant_id, uid)` 注入 request context供 Member / Permission 等下游使用。
---
## 3. System Architecture
### 3.1 System Architecture
```mermaid
flowchart TB
subgraph Client["Client / Frontend"]
Web[Web / Mobile App]
end
subgraph Gateway["Gateway"]
Handler["handler/auth"]
Logic["logic/auth<br/>(orchestration)"]
subgraph AuthModule["internal/model/auth"]
UC["usecase/"]
Repo["repository/"]
Domain["domain/"]
end
MW["middleware/AuthJWT"]
end
subgraph External["External Services"]
Zitadel[ZITADEL IdP]
Mongo[(MongoDB)]
Redis[(Redis)]
end
subgraph Sibling["Sibling Modules"]
Member[member]
Notif[notification]
end
Web --> Handler
Handler --> Logic
Logic --> UC
Logic --> Zitadel
Logic --> Member
Logic --> Notif
UC --> Repo
Repo --> Mongo
Repo --> Redis
MW --> UC
```
### 3.2 Decomposition Description
| 套件 | 職責 |
|------|------|
| `config/` | JWT TTL、Session TTL 設定 |
| `domain/entity/` | Mongo 文件模型InviteCode、RegistrationMetadata |
| `domain/enum/` | RegistrationChannelemail / google |
| `domain/repository/` | Port 介面 + Redis Session struct |
| `domain/usecase/` | UseCase 介面 + DTO |
| `domain/const.go` | BSON 欄位名、Redis key、邀請碼 hash helper |
| `domain/errors.go` | 領域 sentinel errors |
| `repository/` | Mongo + Redis 適配器、`EnsureMongoIndexes` |
| `usecase/` | 實作 + `NewModuleFromParam` factory |
| `usecase/module.go` | 組裝 Invite / RegistrationMeta / Session UseCase |
**ServiceContext 注入:**
| 欄位 | UseCase | 條件 |
|------|---------|------|
| `AuthInvite` | InviteUseCase | Mongo + Redis |
| `AuthRegistrationMeta` | RegistrationMetaUseCase | Mongo |
| `AuthRegistrationSession` | RegistrationSessionUseCase | Redis |
| `AuthLoginSession` | LoginSessionUseCase | Redis |
| `AuthToken` | TokenUseCase | JWT secret + Redis獨立於 Module |
### 3.3 Token
CloudEP JWT 採 HS256access / refresh 使用不同 secret。
**Claims 結構:**
| Claim | 說明 |
|-------|------|
| `tenant_id` | 租戶 ID |
| `uid` | 會員 UID |
| `typ` | `access``refresh` |
| `auth_gen` | 簽發世代(用於強制登出) |
| `jti` | Token 唯一 ID |
| `iat` / `exp` | 簽發/過期時間 |
**預設 TTL**
| Token | 預設 |
|-------|------|
| Access | 900 秒15 分鐘) |
| Refresh | 604800 秒7 天) |
| Registration Session | 600 秒10 分鐘) |
**Redis 映射:**
| Key | 用途 |
|-----|------|
| `auth:jwt:pair:{jti}` | access ↔ refresh jti 雙向映射 |
| `auth:jwt:bl:{jti}` | 已登出/已刷新的 jti 黑名單 |
**Refresh 流程:**
```mermaid
sequenceDiagram
participant C as Client
participant L as TokenRefreshLogic
participant T as TokenUseCase
participant R as Redis
C->>L: POST /auth/token/refresh {refresh_token}
L->>T: Refresh(refreshToken)
T->>T: Parse + verify typ=refresh
T->>R: Blacklist old refresh jti + paired access jti
T->>T: IssuePair(new access + refresh)
T->>R: SavePair(new jti mapping)
T-->>L: TokenPair
L-->>C: AuthTokenData
```
### 3.4 Invite Code
邀請碼以 SHA-256 hash 儲存,明文永不落庫。
| 操作 | 行為 |
|------|------|
| **Validate** | 依 `(tenant_id, code_hash)` 查詢,檢查過期與剩餘次數 |
| **Consume** | Redis SETNX lock30s→ 原子 `$inc used_count` |
**消費時機:**
- Email 註冊:在 `/register` 起始即 Consume
- 社交註冊Start 僅 ValidateCallback 才 Consume
### 3.5 OAuth Session
| Session 類型 | Redis Key | State 前綴 | 用途 |
|-------------|-----------|-----------|------|
| Registration | `auth:register:session:{id}` | `reg:` | 社交註冊暫存 invite / terms |
| Login | `auth:login:session:{id}` | `login:` | 社交登入暫存 tenant / redirect |
---
## 4. Data Design
### 4.1 Data Dictionary
#### invite_codesMongoDB
| Field | Type | Comment | Index |
|-------|------|---------|-------|
| _id | ObjectId | PK | PK |
| tenant_id | String | 租戶 ID | Unique(tenant_id, code_hash) |
| code_hash | String | SHA-256(normalized code) | Unique(tenant_id, code_hash) |
| max_uses | Int64 | 最大可用次數 | — |
| used_count | Int64 | 已使用次數 | — |
| expires_at | Int64 | 過期時間 ms0=永不過期) | — |
| new_users_only | Bool | 僅限新用戶(社交註冊) | — |
| create_at | Int64 | 建立時間 ms | — |
| update_at | Int64 | 更新時間 ms | — |
#### registration_metadataMongoDB
| Field | Type | Comment | Index |
|-------|------|---------|-------|
| _id | ObjectId | PK | PK |
| tenant_id | String | 租戶 ID | Unique(tenant_id, uid) |
| uid | String | 會員 UID | Unique(tenant_id, uid) |
| invite_code_id | String | 使用的邀請碼 ID | — |
| accept_terms_version | String | 接受的服務條款版本 | — |
| marketing_opt_in | Bool | 行銷 opt-in | — |
| registration_channel | String | email / google | — |
| client_ip | String | 註冊 IP | — |
| user_agent | String | User-Agent | — |
| occurred_at | Int64 | 事件時間 ms | — |
| create_at | Int64 | 建立時間 ms | — |
#### Redis Session / Token Keys
| Key Pattern | Type | TTL | Comment |
|-------------|------|-----|---------|
| auth:register:session:{id} | String(JSON) | 600s | 社交註冊 OAuth session |
| auth:login:session:{id} | String(JSON) | 600s | 社交登入 OAuth session |
| auth:invite:consume:{tenant}:{hash} | String | 30s | 邀請碼消費鎖 |
| auth:jwt:pair:{jti} | String | token TTL | access↔refresh 映射 |
| auth:jwt:bl:{jti} | String | 至自然過期 | JWT 黑名單 |
---
## 5. API Design
**Base Path** `/api/v1/auth`
### 5.1 Public Endpoints無 Bearer
| Method | Path | 說明 |
|--------|------|------|
| POST | `/register` | Email 註冊(回傳 challenge_id |
| POST | `/register/confirm` | OTP 確認 → 核發 JWT |
| POST | `/register/resend` | 重發註冊 OTP |
| POST | `/register/social/start` | 社交註冊 OAuth 起始 |
| GET | `/register/social/callback` | 社交註冊 OAuth callback |
| POST | `/login` | 密碼登入 |
| POST | `/login/social/start` | 社交登入 OAuth 起始 |
| GET | `/login/social/callback` | 社交登入 OAuth callback |
| POST | `/token/refresh` | 刷新 token pair |
| POST | `/token/exchange` | ZITADEL id_token → CloudEP JWT |
### 5.2 Protected Endpoints需 Bearer JWT
| Method | Path | 說明 |
|--------|------|------|
| POST | `/logout` | 登出(黑名單 jti |
完整請求/回應 schema 見 `generate/api/auth.api`;成功 envelope `code=102000`
---
## 6. Resource
| 資源 | 路徑 |
|------|------|
| API 定義 | `generate/api/auth.api` |
| Logic 編排 | `internal/logic/auth/` |
| JWT Middleware | `internal/middleware/authjwt_*.go` |
| 模組原始碼 | `internal/model/auth/` |
| 設定範例 | `etc/gateway.dev.example.yaml``Auth` / `JWT` 區塊 |
| 設計參考 | `docs/identity-member-design.md` |