繁體中文(香港)
  • oidc
  • supabase
  • auth
  • rls
  • jwt

與 Supabase 的整合

了解如何將 Logto 與 Supabase 整合,以提升應用程式的認證體驗。

Yijun
Yijun
Developer

Logto 是一個現代身份認證服務提供商,為應用程式提供安全、全面且用戶友好的登錄支援。它還提供大量的 SDK 和多個框架及程式語言的整合指南,使你能夠在數分鐘內無縫地將企業級身份認證服務整合到你的應用程式中。

本文主要著眼於詳述如何將 Supabase 與 Logto 整合。

Supabase 基本概念

Supabase 利用 Postgres 的行級安全性 來控制資料存取權限。簡單來說,通過為資料庫中的表創建行級安全性策略,我們可以限制和管理誰能讀取、寫入和更新表中的數據。

假設你的資料庫中有一個名為 “posts” 的表,內容如下:

Posts table

表中的 user_id 欄位代表每篇文章數據所屬的用戶。你可以根據 user_id 欄位限制每個用戶僅能訪問他們自己的文章數據。

然而,在這能夠實施之前,Supabase 需要能夠識別當前訪問資料庫的用戶。

新增用戶數據到 Supabase 請求中

由於 Supabase 支援 JWT,當我們的應用程式與 Supabase 互動時,我們可以使用 Supabase 提供的 JWT 密鑰生成包含用戶數據的 JWT 作為認證標頭來進行請求。接收到請求後,Supabase 自動驗證 JWT 的有效性,並在後續過程中允許訪問其中的數據。

首先,我們可以從 Supabase 儀表板中的 “專案設置” 獲取 Supabase 提供的 JWT 密鑰:

Supabase API settings page

然後,當我們使用 Supabase SDK 向 Supabase 發出請求時,我們使用此密鑰生成我們的 JWT,並將其附加作為請求的認證標頭。(請注意,此過程發生在你的應用程式的後端服務中,JWT 密鑰絕不應暴露給第三方)。

接下來,導航至 Supabase 儀表板中的 SQL Editor 並創建一個函數以檢索請求中攜帶的 userId:

Create get user ID function

圖中使用的代碼如下:

如代碼所示,在 Supabase 中,可以通過調用 request.jwt.claims 檢索我們生成的 JWT 的有效載荷。在有效載荷中的 userId 欄位即是我們設定的值。

有了這個函數,Supabase 可以確定當前訪問資料庫的用戶。

創建行級安全策略

接下來,我們可以創建一個行級安全策略,根據帖子表中的 user_id 欄位限制每個用戶僅能訪問他們自己的文章數據。

  1. 導航至 Supabase 儀表板中的表編輯頁面,並選擇帖子表。
  2. 點擊表格頂部的 "Add RLS Policy"。
  3. 在提示窗口中點擊 "Create policy"。
  4. 輸入策略名稱並選擇 SELECT 策略命令。
  5. 在代碼的 using 區塊中輸入:
Create RLS policy

通過使用此類策略,可以實現 Supabase 內的數據存取控制。

在實際應用中,你會創建各種策略來限制用戶行動,比如數據插入和修改。然而,這超出了本文的範疇。更多有關行級安全(RLS)的信息,請參閱 使用 Postgres 行級安全保護你的數據

Logto 的基本整合過程

如前所述,由於 Supabase 利用行級安全(RLS)進行存取控制,與 Logto(或任何其他認證服務)的整合關鍵在於獲取已授權用戶的用戶 id 並將其發送到 Supabase。整個過程在下圖中説明:

接下來,我們將根據此過程圖解釋如何將 Logto 與 Supabase 整合。

Logto 整合

Logto 為多種框架和程式語言提供整合指南。

通常,使用這些框架和語言構建的應用程式分為如原生應用、SPA(單頁應用)、傳統 Web 應用和 M2M(機器對機器)應用等類別。你可以訪問 Logto 快速入門 頁面,根據你所使用的技術棧將 Logto 整合到你的應用程式中。之後,按照以下說明,根據你的應用程式類型,將 Logto 整合到你的專案中。

原生應用或 SPA

原生應用和 SPAs 都在你的設備上運行,登錄後獲取的憑證(存取憑證)存儲在你的設備上。

因此,當將應用與 Supabase 整合時,你需要通過後端服務與 Supabase 互動,因為你無法將敏感信息(如 Supabase JWT 密鑰)暴露在每個用戶的設備上。

假設你正在使用 React 和 Express 構建你的 SPA。你已經通過遵循 Logto React SDK 指南 成功將 Logto 整合到你的應用中(你可以參考我們的 react 示例 中的代碼)。此外,你已根據 保護你的 Node(Express)API 文檔將 Logto 存取憑證驗證添加到你的後端伺服器。

接下來,你將使用從 Logto 獲取的存取憑證向後端伺服器請求用戶數據:

在你的後端伺服器中,你已經使用中間件從存取憑證中提取登錄用戶的 id:

現在,你可以使用上述描述的 getSupabaseClientuserId 附加到用於後續請求 Supabase 的 JWT。或者,你可以創建一個中間件來為需要與 Supabase 互動的請求創建 Supabase 客戶端:

在接下來的處理流程中,你可以直接調用 ctx.supabase 來與 Supabase 互動:

在此代碼中,Supabase 將基於之前設置的策略,僅返回當前用戶所屬的文章數據。

傳統 Web 應用

傳統 Web 應用與原生應用或 SPA 的主要區別在於,傳統 Web 應用僅在 Web 伺服器上渲染和更新頁面。因此,用戶憑證由 Web 伺服器直接管理,而在原生應用和 SPA 中,它們位於用戶的設備上。

當使用 Supabase 將 Logto 與傳統 Web 應用整合時,你可以直接從後端獲取登錄用戶的 id。

以一個 Next.js 專案為例,在按照 Next.js SDK 指南 將 Logto 整合到你的專案後,你可以使用 Logto SDK 獲取用戶信息並構建相應的 JWT 來與 Supabase 互動。

機器對機器應用

機器對機器(M2M)通常用於當你的應用需要直接與資源服務器通信,如每日拉取文章的靜態服務等。

你可以使用 機器對機器:Logto 身份認證 指南來進行機器對機器應用認證。Supabase 與機器對機器應用的整合類似於原生應用和 SPA(如“原生應用或單頁應用”部分所述)。它涉及從 Logto 獲取存取憑證,然後通過受保護的後端 API 對其進行驗證。

然而,需注意的是,原生應用和 SPA 通常是為終端用戶設計的,因此獲得的用戶 id 代表用戶自身。然而,機器對機器應用的存取憑證代表應用自身,存取憑證有效載荷中的 sub 欄位是 M2M 應用的客戶端 id,而不是特定用戶。因此,在開發過程中,必需區分哪些數據是面向 M2M 應用的。

此外,如果希望特定的 M2M 應用代表整個服務訪問 Supabase,繞過 RLS 限制,可以使用 Supabase 的 service_role 密鑰來創建 Supabase 客戶端。這在你希望進行一些行政或自動化任務時很有用,這些任務需要訪問所有數據而不受對單個用戶設置的行級安全性策略限制。

service_role 密鑰可以在與 JWT 密鑰相同的頁面中找到:

Service role secret

創建 Supabase 客戶端時,使用 service_role 密鑰,此時這個客戶端可以訪問資料庫中的所有數據:

總結

在本文中,我們深入探討了將 Logto 與 Supabase 整合,揭示了關鍵見解和重要的整合方面。我們探討了如 JWT 認證和行級安全策略等概念,引導你通過將 Logto 無縫結合到你的 Supabase 驅動的應用程式的過程。藉由這些知識,我們希望你能自信地提高應用程式的安全性、功能性,甚至擴展你的專案,增添其他功能。