Auth.js (Auth-Astro) 認證架構:如何在邊緣端實現安全的 OAuth 整合
分享 DueWise 如何在 Astro 架構中整合 Auth.js,解決 Cloudflare Edge Runtime 下的驗證挑戰,並實作多供應商登入。
Auth.js (Auth-Astro) 認證架構:如何在邊緣端實現安全的 OAuth 整合
對於任何雲端同步應用程式來說,「身分驗證」是安全性的第一道門檻。在 DueWise 中,我們希望用戶能以最快、最安全的方式登入,因此我們選擇了 Auth.js (原 NextAuth.js) 的 Astro 版本:auth-astro。
然而,在 Cloudflare Pages 的 Edge Runtime 環境中實作 Auth.js 並非想像中容易。這篇文章將分享我們如何克服環境限制,建立起穩健的認證系統。
為什麼選擇 Auth.js?
傳統的身分驗證通常需要自行管理 Session、Cookie、JWT 加密以及資料庫中的用戶資料表。Auth.js 幫我們完成了 90% 的重活:
- 內建供應商: 支援 Google, GitHub, Apple 等主流 OAuth。
- 安全機制: 自動處理跨站請求偽造 (CSRF) 與加密 Session Cookie。
- 無伺服器對好: 專為 Serverless 環境設計,不依賴傳統的 Node.js Stateful Session。
核心配置實戰:auth.config.ts
在 DueWise 專案中,我們在根目錄定義了 auth.config.ts。這裡的一個關鍵技術點是如何在邊緣端正確讀取環境變數。
import GitHub from '@auth/core/providers/github';
import Google from '@auth/core/providers/google';
import { defineConfig } from 'auth-astro';
export default defineConfig({
providers: [
GitHub({
clientId: import.meta.env.GITHUB_CLIENT_ID,
clientSecret: import.meta.env.GITHUB_CLIENT_SECRET,
}),
Google({
clientId: import.meta.env.GOOGLE_CLIENT_ID,
clientSecret: import.meta.env.GOOGLE_CLIENT_SECRET,
}),
],
callbacks: {
session: ({ session, token }) => {
if (session.user) {
// 將分段的 token id 存入 session,方便後端 D1 查詢使用
(session.user as any).id = token.sub;
}
return session;
},
},
trustHost: true,
});
坑洞提醒:Trust Host 與 Secret
在 Cloudflare Pages 部署時,務必確保設置了 AUTH_TRUST_HOST=true。同時,AUTH_SECRET 必須是一個強隨機字串,用於加密 Cookie。如果沒有這兩者,Auth.js 在生產環境會拋出不可預知的 500 錯誤。
解決 Edge Runtime 的相容性問題
由於 Cloudflare Workers 缺少某些 Node.js 內建模組(如 crypto),早期的 Auth.js 會導致 Build 失敗。在 DueWise 中,我們採取了以下對策:
1. 使用 Vite Polyfill
如前文所述,透過 astro.config.mjs 中的 vite 設定,我們將缺少的模組指向兼容邊緣環境的實現。
2. 適配器管理 (Adapters)
雖然 Auth.js 支持多種資料庫適配器,但在 DueWise 的第一階段,我們使用了 JWT 會話機制,而非資料庫會話。這樣做的好處是「極速」。伺服器不需要查表就能驗證用戶身分,所有的身分資訊都存放在經過簽名的加密 Cookie 中。
用戶體驗:無縫的登入流 (The Auth Flow)
我們在 src/components/DueWiseMain.tsx 中封裝了登入邏輯:
import { signIn, signOut } from 'auth-astro/client';
const LoginButton = () => (
<button onClick={() => signIn('google')}>
使用 Google 快速登入
</button>
);
由於 DueWise 支援「在地模式 (Guest Mode)」,我們的邏輯是:用戶可以先在本地端使用 PWA。當他點擊「雲端同步」時,才觸發 OAuth 流程。登入成功後,狀態會從 useAppStore 更新,我們再將 IndexedDB 中的本地數據搬運至 D1。
安全性:API 路由的保護
為了確保 DueWise 的 API 不會被非法調用,我們在所有的 /api 路由中都加入了 Session 檢查:
import { getSession } from 'auth-astro/server';
export const POST: APIRoute = async ({ request }) => {
const session = await getSession(request);
if (!session) {
return new Response('Unauthorized', { status: 401 });
}
// 處理後續邏輯...
};
這種伺服器端檢查配合 httpOnly Cookie,確保了用戶數據的絕對安全。
個人心得:不要重新發明輪子
在早期版本中,我們曾嘗試手動實作完整的 OAuth Callback 處理。那是一段痛苦的記憶——處理各種各樣的 URL 編碼、參數拼接以及難以排查的驗證錯誤。轉向 Auth.js 後,這些問題都迎刃而解。
對於邊緣計算應用來說,Auth.js 雖然初步配置稍有門檻(因 Runtime 限制),但一旦跑通,其維護成本與安全性收益是巨大的。
結論
身分驗證是開發者的責任。透過 auth-astro 結合 Cloudflare Pages,我們可以建立一個既符合現代安全標準,又能快速響應的優質 PWA。
下一篇文章,我們將揭開硬體整合的秘密:「Barcode Scanning 掃碼技術:如何利用瀏覽器相機實現超市般的極速建檔」。