iT邦幫忙

2025 iThome 鐵人賽

DAY 18
0
自我挑戰組

我獨自開發 - Supabase 打造全端應用系列 第 18

第十八關 - 提升魔力波長MAX:Supabase Auth 進階設定

  • 分享至 

  • xImage
  •  

封面

在上一篇文章中,我們學會了 Supabase Auth 的基本使用方式。但要打造一個真正適合生產環境的應用程式,還需要了解更多進階設定。

為什麼需要進階設定?

雖然 Supabase Auth 的預設設定已經相當安全且實用,但每個應用程式都有其獨特的需求:
包括一般設定、密碼安全性、速率限制,以及當遇到問題時該如何除錯。這些知識將幫助你建立更安全、更穩定、更符合實際需求的身份驗證系統。

簡單來說

就像買了一台新車,除了會開車之外,還需要知道如何調整座椅、設定導航、了解各種安全功能。

魔力波長的強弱:直接反映了該個體的實力等級。一個 S 級獵人的魔力波長,會比 E 級獵人的波長來得更強烈、更具壓迫感。

一般設定(General Configuration)

網站 URL 設定

網站 URL 是 Supabase Auth 用來產生確認連結、密碼重設連結等的基礎網址。正確設定網站 URL 對於郵件確認和重導向功能至關重要。
就像你家的地址,當郵差(Supabase)要寄確認信或重設密碼連結給用戶時,需要知道要寄到哪裡。

// 在 Supabase Dashboard 中設定
// Authentication > URL Configuration

// Site URL: https://yourdomain.com
// Redirect URLs: 
// - https://yourdomain.com/auth/callback
// - http://localhost:3000/auth/callback (開發環境)

會話設定

// 在 Supabase Dashboard 中可以設定的會話選項:
// Project Settings > JWT Keys

// JWT expiry (JWT 過期時間)
// 預設:3600 秒 (1 小時)
// 建議:根據應用程式安全需求調整,一般為 1-24 小時

社交登入設定

Google OAuth 設定

Google 是最常用的社交登入提供者之一。

1. Google Cloud Console 設定

  1. 前往 Google Cloud Console
  2. 創建新項目或選擇現有項目
  3. 啟用 API 和服務
  4. 前往「憑證」頁面
  5. 點擊「建立憑證」> 「OAuth 2.0 用戶端 ID」
  6. 選擇應用程式類型:「網頁應用程式」

URI 設置:

已授權的 JavaScript 來源:

http://localhost:54321

已授權的重新導向 URI:

http://127.0.0.1:54321/auth/v1/callback
http://localhost:54321/auth/v1/callback
https://your-project.supabase.co/auth/v1/callback  (生產環境)

2. Supabase CLI 設定

.env.local 文件中添加:

# Supabase 配置
NEXT_PUBLIC_SUPABASE_URL=http://127.0.0.1:54321
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_anon_key

# Google OAuth 憑證
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret

supabase/config.toml 中添加:

[auth]
enabled = true
site_url = "http://localhost:3000"
additional_redirect_urls = ["http://127.0.0.1:3000", "http://localhost:3000"]

[auth.external.google]
enabled = true
client_id = "env(GOOGLE_CLIENT_ID)"
secret = "env(GOOGLE_CLIENT_SECRET)"
redirect_uri = ""
skip_nonce_check = true

在 Supabase Dashboard > Authentication > Sign In / Providers > Google 設定參數:

若在 config.toml 中添加,則不需要在 Supabase Dashboard 中設定。
Supabase Dashboard 設定會自動,將 Client ID 和 Client Secret 輸入到 Supabase 的設定中。

// 設定的參數:
// Client ID (從 Google Cloud Console 取得)
// Client Secret (從 Google Cloud Console 取得)

3. 基本 Google 登入實作

async function signInWithGoogle() {
  const { data, error } = await supabase.auth.signInWithOAuth({
    provider: 'google',
    options: {
      redirectTo: 'https://yourdomain.com/auth/callback'
    }
  })
  
  if (error) {
    console.error('Google 登入失敗:', error.message)
  }
}

4. 進階 Google OAuth 設定

async function signInWithGoogleAdvanced() {
  const { data, error } = await supabase.auth.signInWithOAuth({
    provider: 'google',
    options: {
      // 重導向 URL - 登入成功後的重導向位置
      redirectTo: 'https://yourdomain.com/auth/callback',
      
      // OAuth 範圍 (Scopes) - 定義應用程式需要存取的 Google 服務
      scopes: 'openid email profile',
      
      // 查詢參數 - 控制 Google OAuth 流程的行為
      queryParams: {
        // 提示類型 - 控制用戶互動方式 (如: 是否顯示帳號選擇畫面)
        prompt: 'select_account',  // 'none' | 'consent' | 'select_account'
        
        // 存取類型 - 決定是否取得 refresh token
        access_type: 'offline',    // 'online' | 'offline'
        
        // 包含已授權的範圍 - 累積權限
        include_granted_scopes: 'true',  // 'true' | 'false'
        
        // 語言設定 - 設定 Google OAuth 介面語言
        hl: 'zh-TW',              // 語言代碼 (如: 'en', 'zh-CN', 'ja')
        
        // 回應類型 - OAuth 2.0 回應類型
        response_type: 'code',    // 'code' | 'token'
      },
    }
  })
  
  if (error) {
    console.error('Google 登入失敗:', error.message)
    return { success: false, error }
  }
  
  return { success: true, data }
}

5. OAuth 回調處理組件

建立 app/auth/callback/page.tsx 來處理 OAuth 回調。

export default function AuthCallback() {
  const router = useRouter()

  useEffect(() => {
    const handleCallback = async () => {
      const { error } = await supabase.auth.exchangeCodeForSession(
        new URLSearchParams(window.location.search).get('code') || ''
      )
      
      router.push(error ? '/auth/login?error=callback_failed' : '/auth/success-page')
    }

    handleCallback()
  }, [router])

  return (
    <div className="flex min-h-screen items-center justify-center">
      <div className="animate-spin h-8 w-8 border-2 border-blue-500 border-t-transparent rounded-full" />
    </div>
  )
}

密碼安全性(Password Security)

密碼強度設定

Supabase Auth 提供多種密碼安全性設定,包括最小長度、複雜度要求等,以確保用戶帳號的安全性。
就像設定家裡的門鎖,你可以選擇簡單的彈簧鎖或複雜的電子鎖,密碼政策就是決定「鎖的複雜程度」。

在 Supabase Dashboard 的 Authentication > Sign In / Providers > Auth Providers > Email 設定:

Minimum password length (最小密碼長度)

  • 預設:6 個字元
  • 建議:8 個字元或以上
  • 密碼長度少於此值將被拒絕為弱密碼,建議最少 6 個字元,推薦 8 個字元或以上

Password Requirements (密碼要求)

  • 可選擇:No required characters (預設) - 無特殊要求
  • 不符合至少一個要求的密碼將被拒絕為弱密碼

電子郵件 OTP 設定

Email OTP Expiration (電子郵件 OTP 過期時間)

  • 預設:3600 秒 (1 小時)
  • 電子郵件 OTP 或連結過期前的持續時間

Email OTP Length (電子郵件 OTP 長度)

  • 預設:6 位數字
  • 電子郵件 OTP 中的位數數量

速率限制(Rate Limits)

了解速率限制

速率限制是一種防護機制,限制特定時間內來自同一 IP 位址或用戶的請求數量,防止暴力破解攻擊、垃圾註冊等惡意行為。
就像銀行的提款機會限制你一天內的提款次數,速率限制確保沒有人能夠無限制地嘗試登入或註冊,保護系統不被濫用。

Supabase Auth 的預設速率限制

這些限制是基於 IP 位址計算的。
在 Supabase Dashboard > Authentication > Rate Limits 中可以調整:

Rate limit for sending emails (郵件發送限制)

  • 預設:2 次/小時
  • 從您的專案每小時可發送的郵件數量

Rate limit for sending SMS messages (簡訊發送限制)

  • 預設:30 次/小時
  • 從您的專案每小時可發送的簡訊數量

Rate limit for token refreshes (權杖刷新限制)

  • 預設:150 次/5分鐘 (每個 IP 位址)
  • 等同於 1800 次/小時
  • 在 5 分鐘間隔內每個 IP 位址可刷新的會話數量

Rate limit for token verifications (權杖驗證限制)

  • 預設:30 次/5分鐘 (每個 IP 位址)
  • 等同於 360 次/小時
  • 在 5 分鐘間隔內每個 IP 位址可進行的 OTP/Magic link 驗證數量

Rate limit for anonymous users (匿名用戶限制)

  • 預設:30 次/小時 (每個 IP 位址)
  • 每小時每個 IP 位址可進行的匿名登入數量

Rate limit for sign ups and sign ins (註冊和登入限制)

  • 預設:30 次/5分鐘 (每個 IP 位址)
  • 等同於 360 次/小時
  • 在 5 分鐘間隔內每個 IP 位址可進行的註冊和登入請求數量(不包括匿名用戶)

Rate limit for Web3 sign up and sign-in (Web3 登入限制)

  • 預設:30 次/5分鐘 (每個 IP 位址)
  • 每個 IP 位址在 5 分鐘內可進行的 Web3 (使用 Solana 登入) 註冊或登入請求數量

除錯與錯誤碼(Debugging & Error Codes)

常見錯誤碼

Supabase Auth 提供詳細的錯誤碼和訊息,幫助開發者快速識別和解決問題。了解這些錯誤碼對於建立穩健的錯誤處理機制至關重要。
就像醫生看病時的診斷代碼,每個錯誤都有特定的「症狀編號」,讓你能快速找到「病因」和「治療方法」。

{
  // 身份驗證錯誤
  'invalid_credentials': {
    message: '電子郵件或密碼錯誤',
    action: 'CHECK_CREDENTIALS',
    userMessage: '請檢查您的電子郵件和密碼是否正確'
  },
  
  // 用戶相關錯誤
  'user_not_found': {
    message: '找不到該用戶',
    action: 'REDIRECT_TO_SIGNUP',
    userMessage: '此電子郵件尚未註冊,請先註冊帳號'
  },
  
  'user_already_registered': {
    message: '用戶已經註冊',
    action: 'REDIRECT_TO_SIGNIN',
    userMessage: '此電子郵件已經註冊,請直接登入'
  },
  
  // 會話相關錯誤
  'session_not_found': {
    message: '會話已過期',
    action: 'REDIRECT_TO_LOGIN',
    userMessage: '登入已過期,請重新登入'
  },
  
  'refresh_token_not_found': {
    message: '刷新權杖遺失',
    action: 'FORCE_LOGOUT',
    userMessage: '登入狀態異常,請重新登入'
  },
  
  // 速率限制錯誤
  'over_email_send_rate_limit': {
    message: '郵件發送頻率超限',
    action: 'SHOW_RETRY_TIMER',
    userMessage: '郵件發送過於頻繁,請稍後再試'
  },
  
  'over_sms_send_rate_limit': {
    message: '簡訊發送頻率超限',
    action: 'SHOW_RETRY_TIMER',
    userMessage: '簡訊發送過於頻繁,請稍後再試'
  },
  
  // 驗證相關錯誤
  'email_not_confirmed': {
    message: '電子郵件尚未確認',
    action: 'RESEND_CONFIRMATION',
    userMessage: '請先確認您的電子郵件'
  },
  
  'invalid_token': {
    message: '無效的權杖',
    action: 'REQUEST_NEW_TOKEN',
    userMessage: '驗證連結已過期或無效,請重新申請'
  },
  
  // 密碼相關錯誤
  'weak_password': {
    message: '密碼強度不足',
    action: 'SHOW_PASSWORD_REQUIREMENTS',
    userMessage: '密碼需要包含大小寫字母、數字和特殊符號'
  },
  
  'password_too_short': {
    message: '密碼長度不足',
    action: 'SHOW_PASSWORD_REQUIREMENTS',
    userMessage: '密碼長度至少需要 8 個字元'
  }
}

小結

透過適當的配置,可以建立一個真正適合生產環境的身份驗證系統。

... to be continued

有任何想討論歡迎留言,或需要指正的地方請鞭大力一點,歡迎訂閱、按讚加分享,分享給想要提升開發效率的朋友


上一篇
第十七關 - 魔力波長:Supabase Auth
系列文
我獨自開發 - Supabase 打造全端應用18
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言