手冊首頁 / 認證(登入前) / 認證功能群總覽

認證功能群總覽(Auth Overview)

本檔放「本功能群多個頁面共用的知識」:頁面地圖、認證資料模型、登入 → MFA → JWT 流程、密碼變更生命週期、匿名態特性

各頁面 spec 引用本檔,只寫自己頁面的差異——改共用邏輯時改這裡一份

事實基準:2026-07-05 從 FE(views/auth/config/router/index.js)/ BE(api/auth)code 與 db_schema.jsonpublic schema)掃出。

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. 認證資料模型

au_auth_data_model 認證資料模型(public schema) users public.users password(加密)·status login_failed_count·last_login_* topt_secret·mfa_type tokens public.login_tokens JWT 註冊表 jti·token_type·is_revoked·expires users->tokens user_identity totp public.totp_secrets MFA TOTP secret·uri(QR) users->totp user_id llog public.login_logs 登入稽核 token·user_uid·last_login users->llog 登入時寫 cpr public.user_change_password_request 密碼變更請求(token) uid·type(0/1/2/3/9)·status(0/1)·expired users->cpr user_id cplog public.user_change_pwd_logs 密碼變更歷史 type·password users->cplog user_id·變更時寫
認證資料模型:users 核心 + JWT token 註冊 + TOTP + 密碼變更請求 / 稽核

全部在 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 流程

au_login_flow 登入 → MFA → JWT 發放(匿名態起點) start 登入頁(匿名) login POST /login 帳號 + 密碼 (+ captcha) start->login cred 密碼正確 & 帳號啟用? login->cred fail 登入失敗 login_failed_count++ / 鎖定 / 停用擋下 cred->fail mfa 需要 MFA?(mfa_type) cred->mfa otp 轉 otp-verify POST /otp-verify(+ /otp-resend) 首次啟用 TOTP:/otp-qrcode + /totp-secret mfa->otp issue 發 JWT(access + refresh) 寫 login_tokens(jti) + login_logs RLS session 變數注入 mfa->issue 否(免 MFA) otpok OTP 正確? otp->otpok otpok->otp 否(可重送) otpok->issue home 進入系統 issue->home
登入 → 憑證檢查 → MFA 分流 → OTP → 發 JWT
  • POST /login(帳密 + captcha)→ 憑證與帳號狀態檢查(失敗 login_failed_count++、停用擋下)。
  • mfa_type 分流:需 MFA → 轉 /otp-verifyPOST /otp-verify;首次啟用 TOTP 走 /otp-qrcode + /totp-secret;可 /otp-resend);免 MFA → 直接發 JWT。
  • 發 JWT(access + refresh)→ 寫 login_tokens(jti)+ login_logssession_scope 注入 RLS session 變數。POST /refresh 換新 access token、POST /logout 撤銷(is_revoked=1)。

(各 endpoint 完整規格見 login.md §6。)

4. 密碼變更生命週期(ChangePasswordTypeCode)

user_change_password_requesttype 統一多種密碼變更情境:

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. 本群共用的已知坑

  1. 欄名拼寫 topt_secretusers.topt_secret(非 totp_secret)——查詢 / 對照時注意。
  2. 帳號狀態多值users.status 0/1/-1/-2 四態;登入須檢查 status=1(啟用)。
  3. JWT 撤銷靠 login_tokens:logout / refresh 以 jti + is_revoked 管理;純無狀態 JWT 無法撤銷,此表補上黑名單能力。
  4. 重設 token single-use + 過期user_change_password_request.status 0→1 且 expired——已用 / 過期 token 不可再用。
  5. 匿名態頁不套 RLS:登入前 session 無 tenant 變數;登入成功才注入 RLS 變數。