Supabase Auth

使用 Supabase Auth 來為您的專案建置身分驗證系統,在架構設計、核心觀念、整合方法以及上線生產環境時,以下是您需要掌握的關鍵資訊。


1. 核心架構與安全機制

  • GoTrue 與 JWT 機制:Supabase Auth 底層是基於開源的 GoTrue 身分驗證 API。當使用者登入成功後,Supabase 會核發兩種憑證:代表使用者身分與權限的 JWT 存取權杖(Access Token),以及用於延長登入狀態的 更新權權杖(Refresh Token)
  • 與 PostgreSQL RLS(資料列級安全性)整合:這是使用 Supabase 最核心的安全設計。用戶登入後,客戶端 SDK 發送的所有資料庫請求都會自動帶上該使用者的 JWT。在 PostgreSQL 中啟用 RLS(Row Level Security) 後,您可以使用 auth.uid() 函數來驗證使用者身分。例如,限制使用者只能存取自己資料的 RLS 策略:
    CREATE POLICY "使用者只能操作自己的資料"
    ON profiles
    FOR ALL
    USING (auth.uid() = user_id);
    
  • 兩種 Client 權限
    • anon_key(公開匿名金鑰):安全防護強度低,僅能在開啟 RLS 的情況下供前端或客戶端使用。
    • service_role_key(伺服器管理金鑰):擁有繞過所有 RLS 策略的最高管理權限,絕對不能洩漏到前端或瀏覽器中

2. 支援的身分驗證方式

  • 帳號密碼:傳統的 Email 與密碼註冊與登入。
  • 無密碼驗證(Passwordless)
    • Magic Link:發送含有一次性登入連結的 Email 到使用者信箱。
    • 電話簡訊(OTP):支援透過 Twilio、MessageBird 等簡訊提供商發送驗證碼。
    • Passkeys(生物辨識,支援 WebAuthn):支援使用 FaceID、TouchID、裝置 PIN 碼或實體安全金鑰登入,具備強大的防釣魚安全性。
  • OAuth 2.0 第三方登入:支援 Google、GitHub、Apple、Discord 等數十種主流平台。亦支援自訂 OIDC(OpenID Connect)提供商,方便對接自建的身分驗證系統。
  • 企業單一登入(SAML SSO):適用於需要對接企業客戶(如 Okta、Azure AD)的身分驗證系統。

3. 現代化 SSR 開發流程:@supabase/ssr 與 PKCE 流

對於 Next.js, SvelteKit, Nuxt 或 Astro 等伺服器端渲染(SSR)框架,Supabase 已淘汰舊有的 auth-helpers 工具,改由 @supabase/ssr 套件統一處理。

  • PKCE 驗證流(Proof Key for Code Exchange)
    為了避免存取權杖在瀏覽器端傳遞時被竊取,SSR 環境預設採用 PKCE 流程。使用者點擊驗證連結後,會被引導至您的 /auth/callback 路由,並攜帶一個臨時的驗證碼(Auth Code)。伺服器收到此驗證碼後,再向 Supabase 交換真正的 Session。
  • Cookie 儲存替代 LocalStorage
    單頁應用(SPA)傳統上會將 Session 存於瀏覽器的 LocalStorage 中,但這會導致伺服器端無法讀取。@supabase/ssr 會自動將 Session 資訊安全地存在 Cookie 中,以便在前後端之間流暢傳遞。

4. 基礎開發步驟(以 Next.js / React 爲例)

以下為使用 @supabase/ssr 的標準整合配置:

步驟一:安裝套件

npm install @supabase/supabase-js @supabase/ssr

步驟二:建立 Server 端的 Supabase 實例

在 Server 端(例如 Next.js Route Handler 或 Server Action),需要手動處理 Cookie 的讀取與寫入:

import { createServerClient } from '@supabase/ssr'
import { cookies } from 'next/headers'

export function createClient() {
  const cookieStore = cookies()

  return createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        getAll() {
          return cookieStore.getAll()
        },
        setAll(cookiesToSet) {
          try {
            cookiesToSet.forEach(({ name, value, options }) =>
              cookieStore.set(name, value, options)
            )
          } catch {
            // 在某些 Server Component 情境下,若不允許直接寫入 Cookie 可安全忽略
          }
        },
      },
    }
  )
}

步驟三:實作驗證回呼(Callback)

建立 app/auth/callback/route.ts 路由,用來處理 PKCE 流程中的臨時代碼交換:

import { NextResponse } from 'next/server'
import { createClient } from '@/utils/supabase/server'

export async function GET(request: Request) {
  const { searchParams, origin } = new URL(request.url)
  const code = searchParams.get('code')
  const next = searchParams.get('next')?? '/'

  if (code) {
    const supabase = createClient()
    const { error } = await supabase.auth.exchangeCodeForSession(code)
    if (!error) {
      return NextResponse.redirect(`${origin}${next}`)
    }
  }

  // 若交換失敗,重導向至錯誤頁面
  return NextResponse.redirect(`${origin}/auth/auth-error`)
}

5. 上線生產環境(Production)必備核對清單 (Checklist)

  • 啟用資料列級安全性(RLS)
    確保所有新建立的資料庫資料表均已啟用 RLS。否則在預設情況下,任何人都可以繞過身分驗證,直接讀寫您的 Postgres 資料庫。
  • 設定自訂 SMTP 伺服器
    Supabase 內建的測試用郵件發送限制為每小時 3 封。在生產環境中,您必須配置自訂的 SMTP 服務(如 Resend、Mailgun、SendGrid 等),以防止使用者無法正常收到註冊、忘記密碼或 OTP 信件。
  • 配置合法的重導向 URL (Redirect URLs)
    請在 Supabase 後台 Authentication -> URL Configuration 中設定合法的網域(例如您的正式環境網域 https://your-domain.com)。未被列入白名單的網域將會被拒絕進行 OAuth 或 Magic Link 的跳轉。
  • 管理 API 密鑰安全
    Supabase 採行新型的 API 密鑰模型,原有的 JWT-based anonservice_role 正在逐步替換為可撤銷、可稽核的秘密密鑰(Secret Keys)。請務必避免將 service_role 金鑰上傳至公開代碼庫,若不慎洩漏,Supabase 支援自動撤銷功能。
  • 設置身分驗證鉤子(Auth Hooks)
    如果需要實作自訂的驗證邏輯(例如禁止特定網域的 Email 註冊,或是在核發 JWT 前加入自訂欄位),可以利用 PostgreSQL 函數(SQL Functions)並掛載至 Auth Hooks。

這套身分驗證架構兼顧了低維護成本、高自主性與擴充彈性,是替代付費身分驗證服務的常見選擇。