手冊首頁 / 認證(登入前) / 認證功能群總覽
認證功能群總覽(Auth Overview)
本檔放「本功能群多個頁面共用的知識」:頁面地圖、認證資料模型、登入 → MFA → JWT 流程、密碼變更生命週期、匿名態特性。
各頁面 spec 引用本檔,只寫自己頁面的差異——改共用邏輯時改這裡一份。
事實基準:2026-07-05 從 FE(
views/auth/、config/router/index.js)/ BE(api/auth)code 與db_schema.json(publicschema)掃出。
1. 頁面地圖
本群是系統的未登入入口:所有頁面在 JWT 建立之前運作(匿名可達)。
| 頁面 | FE route | 用途一句話 | spec |
|---|---|---|---|
| 登入(含 MFA OTP) | /・/login |
帳密登入、captcha、MFA OTP 分流 | ⬜ 登入 |
| OTP 驗證 | /・/otp-verify |
輸入 TOTP、首次啟用 QR、重送 | 併入 login.md |
| 忘記密碼 | /forget-password |
送出密碼重設請求 | ⬜ 忘記密碼 |
| 重設密碼 | /reset-password |
憑 token 設新密碼(含首次登入 / 過期強制) | 併入 forget-password.md |
2. 認證資料模型
全部在 public schema:
| 表 | 角色 |
|---|---|
public.users |
帳號核心:password(加密)/ status(0
未啟用 / 1 啟用 / -1 停用 / -2 刪除)/ login_failed_count /
last_login_success_time /
last_login_failed_time /
topt_secret(TOTP,注意欄名拼寫)/
mfa_type(MFA 類型) |
public.login_tokens |
JWT 註冊表:jti / token_type /
user_identity / is_revoked /
expires——refresh / logout 撤銷靠此 |
public.totp_secrets |
MFA TOTP:secret + uri(生成 QR 碼) |
public.login_logs |
登入稽核:token / user_uid /
username / last_login |
public.user_change_password_request |
密碼變更請求(token = uid):type(0
首次註冊 / 1 密碼重設 / 2 忘記密碼 / 3 密碼過期 / 9 自行變更)/
status(0 未使用 / 1 已使用)/ expired |
public.user_change_pwd_logs |
密碼變更歷史:type / password(防重用 /
稽核) |
3. 登入 → MFA → JWT 流程
POST /login(帳密 + captcha)→ 憑證與帳號狀態檢查(失敗login_failed_count++、停用擋下)。- 依
mfa_type分流:需 MFA → 轉/otp-verify(POST /otp-verify;首次啟用 TOTP 走/otp-qrcode+/totp-secret;可/otp-resend);免 MFA → 直接發 JWT。 - 發 JWT(access + refresh)→ 寫
login_tokens(jti)+login_logs;session_scope注入 RLS session 變數。POST /refresh換新 access token、POST /logout撤銷(is_revoked=1)。
(各 endpoint 完整規格見 login.md §6。)
4. 密碼變更生命週期(ChangePasswordTypeCode)
user_change_password_request 以 type
統一多種密碼變更情境:
| type | 情境 | 觸發 |
|---|---|---|
| 0 | 首次註冊 | 新帳號首次登入強制設密碼 |
| 1 | 密碼重設 | 管理員 / 系統重設 |
| 2 | 忘記密碼 | 使用者從忘記密碼頁請求 |
| 3 | 密碼過期 | 密碼到期強制變更 |
| 9 | 自行變更 | 使用者主動改密碼 |
請求 status
0 未使用 → 1 已使用(single-use)+ expired
過期時間;重設密碼頁憑
token(uid)驗證後設新密碼、寫
user_change_pwd_logs。
5. 匿名態特性(本群與其他頁的關鍵差異)
- 本群沒有「角色」,只有「造訪者」:任何還沒登入的人(新使用者 / 忘記密碼的人 / token 過期被踢出的人)都可能落在這幾頁;沒有 manager/auditor/viewer 之分。「身為造訪者,我要輸入帳密(必要時完成 MFA)換到一組 JWT,才能進入下面各功能群。」登入成功後才進入其他群的角色體系。
- §3
權限矩陣與其他頁不同:本群頁面在未登入態運作,無
JWT、無專案 / 選單能力可判;「權限」=
端點是否需認證(
/login、/forget-password、/otp-verify皆匿名可達;/logout、/refresh需既有 token)。 - §5 UI 截圖為登出態:截圖需在登出狀態擷取(非側邊選單內頁)。
- token 持久化模式:FE 有
cm_persist_mode(session vs local)——曾發生cm_persist_mode=session心跳過期清 token 誤判為登入壞(見各頁 §12 / pilot 截圖 session 教訓)。
6. 本群共用的已知坑
- 欄名拼寫
topt_secret:users.topt_secret(非totp_secret)——查詢 / 對照時注意。 - 帳號狀態多值:
users.status0/1/-1/-2 四態;登入須檢查status=1(啟用)。 - JWT 撤銷靠
login_tokens:logout / refresh 以jti+is_revoked管理;純無狀態 JWT 無法撤銷,此表補上黑名單能力。 - 重設 token single-use +
過期:
user_change_password_request.status0→1 且expired——已用 / 過期 token 不可再用。 - 匿名態頁不套 RLS:登入前 session 無 tenant 變數;登入成功才注入 RLS 變數。