How should I implement authentication for a SaaS?
It depends on who your users are. Most SaaS products should let one identity system own sign-in, sessions, and account recovery, then connect that session to workspace membership on the server. Choose methods deliberately: email OTP and passkeys reduce friction, OAuth helps consumer sign-ups, and 2FA belongs where buyers require it. Never trust a client-supplied workspace ID; derive access from membership. Test invitation, removal, session revocation, and account deletion, not just login. A tested kit such as supastack can supply the baseline, but your product still owns its authorization rules.
讓一個系統掌管身份
登入表單收集的是一次請求。認證系統決定該請求是否確立身份,並簽發應用其餘部分信任的會話。把這份職責放在一個地方,可以避免每條路由各自發明對“已登入使用者”的解釋。
supastack 組合 Better Auth 處理身份與會話。應用程式碼在受保護邊界解析會話,並將其關聯到工作區。介面可以展示有用的訪問狀態,但客戶端狀態絕不能成為操作已獲授權的證據。
這條規則必須在產品釋出的每個端面上成立。Web、移動端與桌面端應該消費同一個身份判定,而不是各實現一遍——三種“已登入”的解釋正是賬戶 bug 的來源。
審慎地選擇登入方式
每種方式都在用摩擦換取攻擊面與外部依賴。密碼需要重置流程和速率限制。魔法連結和一次性碼依賴郵件的送達能力。OAuth 把身份委託給 Google、GitHub 或 Apple 這類供應商——也繼承了它們的宕機、授權頁和回撥規則。
supastack 通過 Better Auth 把這些方式組合在一個統一的身份判定之後——郵箱 OTP、密碼、魔法連結、OAuth,外加可選的雙因素與通行金鑰。只發布你的使用者真正需要的最小集合;每多一種方式,就多一條回撥路徑、多一種失敗模式、多一條釋出前要驗證的流程。認證指南講了接線方式。
當一個人可以用多種方式登入時,要決定這些方式如何匯合。解析到同一郵箱地址的 Google 賬戶和魔法連結應該落在同一個身份上,而不是兩個。賬戶關聯規則是身份判定的一部分,搞錯了會造出重複使用者,幾個月後以離奇丟失的資料浮出水面。
會話才是真正要緊的憑證
登入之後,每個請求攜帶的是會話而不是密碼。它的過期、儲存與失效規則定義了真實的安全姿態。退出後仍然存活的會話、被移除的工作區成員還能繼續使用的會話,都是再精緻的登入介面也修補不了的認證失敗。
提前定好生命週期:會話活多久、使用者能否檢視並撤銷自己的活躍會話、改密碼、改郵箱或被移出工作區對它們有什麼影響。套件裡會話管理之所以是獨立模組,正因為這些決定容易被推遲、補做又很昂貴。
把會話與所請求的記錄連起來
登入不等於有權訪問所有記錄。在服務端解析使用者的工作區,並把該範圍帶入讀寫。任務識別符號或恢復連結是對工作的引用,不是取回它的許可——工作區邊界一文詳細講了邊界的那一側。
按固定順序解析範圍:先認證會話,再載入成員關係,然後帶著這個工作區上下文去讀或寫——絕不能反過來。中介軟體可以重定向匿名訪客,但無法為操作授權;檢查屬於實際碰到記錄的服務端 action 或路由 handler。
賬戶有完整生命週期,而不只是起點
開通是這條邊界的第一場考試。使用者註冊時,隨之而來的工作區與歸屬記錄必須能安全地建立不止一次——生命週期鉤子可能被供應商、重試或客服工具重放。重複的事件應該是空操作,而不是重複的組織。
生命週期的末端值得同樣的用心。改郵箱、重置密碼、移除成員、刪除賬戶、匯出資料,每個都是帶著自己濫用場景的小流程——能用兩次的重置連結、洩露隊友記錄的匯出。supastack 正是為此內建了 GDPR 匯出與會話管理;無論你基於什麼構建,都要給這些平淡無奇的流程留預算。
測試整個生命週期,包括終點
一次成功的登入測試有用但不完整。演練無效憑證、過期或複用的驗證碼、匿名請求與跨工作區訪問。驗證退出登入會使會話失效,且迴歸的客戶端不能繼續用此前授權的介面執行受保護工作。
區分 handler 測試與部署驗收。記憶體介面卡可以確立真實認證 handler 的語義,卻不能證明 Postgres 持久化或供應商回撥。在聲稱完整登入流程可用之前,用已部署的依賴驗證配置的 origin、回撥路徑、會話恢復與退出。
- 無效憑證以及過期或複用的驗證碼被拒絕。
- 匿名與跨工作區請求拿不到任何歸屬資料。
- 退出登入會使會話失效——過期的客戶端無法繼續行動。
- 生命週期鉤子重放時,已開通的記錄保持冪等。
- 真實供應商的回撥在配置的 origin 上可用——經過驗證,而非想當然。
常見認證問題
下面的問題,會在登入表單做完、系統必須持續運轉之後浮現。
- 中介軟體足以保護路由嗎? —— 中介軟體只是方便的重定向,不是授權層。每個服務端 action 和路由都要自己解析會話與工作區;頁面級守衛只是藏起介面,並沒有為操作授權。
- 自己造認證還是用庫? —— 會話語義很少是 SaaS 的差異化所在。像 Better Auth 這樣有維護的庫,放在清晰的模組邊界後面,能給你經過測試的原語,同時把要緊的決定——範圍、生命週期——留在你的程式碼裡。
- 會話和工作區是什麼關係? —— 會話標識的是人,工作區標識的是他可以觸碰的記錄。每個請求都在服務端解析成員關係,絕不信任客戶端發來的工作區 ID。
- B2B 客戶對認證有什麼期待? —— 帶角色的團隊工作區、OAuth 登入、會話可見性與可撤銷性,以及審計軌跡。雙因素與通行金鑰對管理員角色也越來越是標配。
- 生產環境裡是什麼弄壞認證? —— 通常是邊緣地帶:只存在於本地的回撥 URL、開通兩次的鉤子、比成員關係活得還久的會話。要測流程的末端,而不只是開頭。