依 autoflow-agent workspace v2 設計把 PRD / 設計 / 架構 / 交付類 共享文件從個人層 .autoflow/(ignored)搬到 docs/autoflow/(進 git), 讓團隊可共享產品與架構文件,個人層只留 progress / review / testing 等 per-branch 筆記。 - 02-prd/ 21 個檔(PRD、features、market-analysis 等) - 03-design/ 18 個檔(design-spec、wireframes、flows 等) - 04-architecture/ 31 個檔(TDD、design-doc、ADR×14、API 規格等) - 07-delivery/ 3 個檔(project-summary、phase-0.6-handover、stage-deployment-setup) 合計 73 檔。原檔已從 .autoflow/ 移除(migration 工具執行 git mv, 但因 .autoflow/ 在 .gitignore 中、git 將此操作視為新增、無 rename history)。
7.9 KiB
7.9 KiB
Phase 0.6 OIDC 接入 — 交接摘要
日期:2026-04-26
範圍:visionA-backend StaticAuthProvider → Innovedus Member Center OIDC(BFF Pattern + Authorization Code + PKCE)
上位文件:
.autoflow/04-architecture/oidc-tdd.md、.autoflow/04-architecture/adr/adr-010-oidc-bff.md、.autoflow/04-architecture/adr/adr-011-supersede-static-auth.md整體交付:見
.autoflow/07-delivery/project-summary.md
1. Phase 0.6 完成項目
Backend(OB1-OB6)✅
- OB1
internal/oidc/:coreos/go-oidc 包裝,discovery + JWKS + token exchange + id_token 驗簽(24 tests / 93.4% 覆蓋) - OB2
internal/usersession/:in-memory session store + cookie HMAC 簽章(24 tests) - OB3+OB4
internal/api/middleware/auth.go+ 4 個 OIDC handler(/api/auth/login//callback//logout//me)(14 tests) - OB5 完全移除
StaticAuthProvider、AuthenticatedClient fixture 統一(17 packages 全綠 / oidc_e2e build tag 移除) - OB6 ADR-011 推翻 ADR-005 Auth 部分(DB 部分仍有效)
Frontend(OF1-OF2)✅
- OF1 login 頁改 OIDC redirect 按鈕(11 tests + i18n)
- OF2 API client
credentials: 'include'、auth-store 拔 localStorage、改 cookie session(107 tests 綠)
Frontend(OF3-OF4)⏳
- OF3 register 頁移除、account 接
/api/auth/me(待補) - OF4 i18n 補齊(待補)
DevOps(OD1)✅
- 5 service docker-compose(postgres / member-center / member-center-web / member-center-init / visiona-api / visiona-proxy)全 healthy
docs/DEV-SETUP.md完整 setup + 故障排除(含 §7.6 OIDC flow 階段問題)
DevOps(OD2)⏳
make dev-with-mcMakefile target +.env.example整理(待補;MC bug 修復後加 seed script)
Testing(OT1)✅
internal/oidc/oidctest/:fake OIDC server(自簽 JWKS / 模擬 authorize / token endpoints)internal/api/handlers/oidc_e2e_test.go:6 個 e2e cases(含PairingTokenBindsToOIDCUser,驗 OIDC sub 真的有貫通到 PairingStore)- 17 packages 全綠 / build tag 已拿掉(合進主測試)
Testing(OT2)✅(範圍調整)
- 因 MC 兩個 bug 阻擋自動 e2e(password grant 缺 sub claim、admin API 不接受 client_secret),原訂「真 MC e2e」改為:
docs/SMOKE-TEST.md:完整 7 階段手動煙測 checklistdocs/DEV-SETUP.md§7.6 補 OIDC flow 故障排除對照表- 真 MC 自動 e2e 列入 Phase 1 TODO(待 MC 修 bug)
2. 跑通的 Demo
Demo A:OIDC Flow(手動,需先依 docs/DEV-SETUP.md §5 註冊 OAuth client)
端到端使用者旅程(對應 docs/SMOKE-TEST.md 階段 3-7):
[browser] http://localhost:3000/login
↓ 點「使用您的 Innovedus 帳號登入」
[backend] GET /api/auth/login
↓ 產 PKCE + state + nonce,存 pending session(10 分鐘 TTL)
↓ Set-Cookie: visiona_pending_sid
↓ 302 to MC /oauth/authorize?response_type=code&...&code_challenge=...
[MC] http://localhost:5050/oauth/authorize
↓ 顯示登入頁 → demo@visiona.local / Demo12345!
↓ 同意授權
↓ 302 back to http://localhost:3721/api/auth/callback?code=...&state=...
[backend] GET /api/auth/callback
↓ 驗 state(CSRF)
↓ POST MC /oauth/token (code + verifier + client_secret)
↓ 驗 id_token(iss / aud / exp / nonce / JWKS 簽章)
↓ 建 visionA session(user_id = OIDC sub, 7d / 24h idle)
↓ Set-Cookie: visiona_session
↓ 302 to http://localhost:3000{return_to}
[browser] dashboard 顯示已登入 demo user
↓ 後續 API request 自動帶 visiona_session cookie
[backend] /api/devices /api/models /api/auth/me 全帶 cookie 認證
Demo B:Pairing Token 綁 OIDC user(關鍵承諾驗證)
目的:驗證取代 StaticAuth 後,pairing token 不再綁 demo-user 而是真實 OIDC sub。
[browser] /devices/pair → 點「產生 Pairing Token」
[backend] POST /api/pairing/token (cookie: visiona_session)
↓ middleware 解 cookie → UserContext{UserID: <OIDC sub>}
↓ PairingStore.Create(userID=<OIDC sub>, token=vAc_xxx)
↓ log: "PairingStore Create userID=<UUID>"
[browser] 拿到 token vAc_xxx
↓ 餵給 local-tool agent
[agent] 連 visiona-proxy → 帶 pairing token → 換 session token
[backend] agent 連入 → 後端 binding user_id 是 OIDC sub(與 step 2 一致)
Demo C:fake OIDC e2e(自動化)
go test ./internal/api/handlers/... -run TestOIDCE2E
跑完含 6 個 case:
- LoginRedirectsToProvider
- CallbackCreatesSession
- StateMismatchRejected
- NonceMismatchRejected
- ExpiredTokenRejected
- PairingTokenBindsToOIDCUser(最關鍵)
17 packages 全綠 / build tag 已合進主測試。
3. 手動 Demo Flow
完整步驟見 docs/SMOKE-TEST.md,7 階段 / 預估 30 分鐘:
| 階段 | 內容 | 時間 |
|---|---|---|
| 1 | 基礎服務驗證(5 service + frontend healthy) | 5 min |
| 2 | MC 設定(建 tenant + OAuth client + demo user) | 10 min |
| 3 | 完整 Login Flow(redirect chain 走完) | 5 min |
| 4 | API 帶 Cookie 驗證(/me + /devices + /models) | 3 min |
| 5 | Pairing Token 綁 OIDC user(關鍵承諾) | 5 min |
| 6 | 登出 + 重登 | 3 min |
| 7 | 跨頁 Refresh / 持久化 | 2 min |
每個階段都有對應的「故障排除 #N」可查;卡住先看 docs/SMOKE-TEST.md §故障排除 + docs/DEV-SETUP.md §7。
4. 已知 Limitation
| # | Limitation | 影響範圍 |
|---|---|---|
| 1 | MC admin API 不能 seed OAuth client(password grant + client_secret 兩個 bug) | §2 OAuth client 註冊必須手動走 Web UI;自動 e2e blocked |
| 2 | MC 只支援 usage=webhook_outbound 帶 redirect_uris |
雛形借用,命名語意不對 |
| 3 | visionA-backend in-memory session store 重啟即消失 | 所有 user 重登 |
| 4 | 沒有 RP-initiated logout | 登出 visionA 不會把 MC session 也登出 |
| 5 | 沒有 refresh token rotation | 24h idle / 7d absolute 後必須重登 |
| 6 | host visiona-local(local-tool)佔 3721 與 docker compose 衝突 | 兩個只能擇一跑 |
5. Phase 1 TODO
MC team(unblock visionA 自動化)
- MC-1 修 password grant Identity user 缺 sub claim → 500 bug
- MC-2 admin API 接受 + 回傳 client_secret
- MC-3 新增
usage=web_appOAuth client 類型
visionA Phase 1
- OD2
make dev-with-mc+make dev-seedscript(依賴 MC-1 + MC-2) - OT2 補完 真 MC 自動 e2e(用 testcontainers 起真 MC,把 SMOKE-TEST §3-§7 全自動)
- OF3 OF4 register 頁移除 + account 改造 + i18n 補齊
- OB-Phase1-1 in-memory session store → Redis
- OB-Phase1-2 RP-initiated logout(OIDC end_session_endpoint)
- OB-Phase1-3 Refresh token rotation(依賴 MC 上 refresh token 支援)
- OB-Phase1-4 Member Center webhook(user 刪除 / 停用通知)
6. 相關文件索引
| 主題 | 文件 |
|---|---|
| 架構決策 | .autoflow/04-architecture/adr/adr-010-oidc-bff.md、adr/adr-011-supersede-static-auth.md |
| TDD(含時序圖、模組設計、env、安全考量) | .autoflow/04-architecture/oidc-tdd.md |
| Dev 環境 setup | docs/DEV-SETUP.md |
| 手動煙測 | docs/SMOKE-TEST.md |
| 整體 visionA 交付 | .autoflow/07-delivery/project-summary.md |
7. 驗收狀態
- 端到端 redirect chain 通(fake OIDC e2e 自動驗)
- Pairing token 綁 OIDC sub(OT1 PairingTokenBindsToOIDCUser ✅)
- StaticAuthProvider 完全移除(OB5 ✅)
- Frontend 完全不接觸 token(OF1 + OF2 ✅)
- docker-compose 一鍵起 5 service(OD1 ✅)
- 手動煙測 checklist 完整(OT2 ✅,本文件對應)
- OF3 + OF4 完成(待補;不阻擋 Phase 0.6 驗收,列入 Phase 1)
- OD2 Makefile + seed script(依賴 MC bug 修復;列入 Phase 1)
- 真 MC 自動 e2e(依賴 MC bug 修復;列入 Phase 1)