Skip to content
Anonymous

Auth.js (Auth-Astro) 認證架構:如何在邊緣端實現安全的 OAuth 整合

分享 DueWise 如何在 Astro 架構中整合 Auth.js,解決 Cloudflare Edge Runtime 下的驗證挑戰,並實作多供應商登入。

#Auth.js #Astro #OAuth #Security #Cloudflare

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% 的重活:

  1. 內建供應商: 支援 Google, GitHub, Apple 等主流 OAuth。
  2. 安全機制: 自動處理跨站請求偽造 (CSRF) 與加密 Session Cookie。
  3. 無伺服器對好: 專為 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 掃碼技術:如何利用瀏覽器相機實現超市般的極速建檔」。