繁體中文(台灣)
  • 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,然後在發送請求時使用該 JWT 作為驗證標頭。收到請求後,Supabase 自動驗證 JWT 的有效性,並允許在隨後的過程中訪問其中包含的數據。

首先,我們可以從 Supabase 控制台的“專案設定”中獲取 Supabase 提供的 JWT 秘鑰:

Supabase API settings page

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

接下來,導航到 Supabase 控制台中的 SQL 編輯器並創建一個函數以檢索請求中攜帶的 userId:

Create get user ID function

圖中的代碼如下所示:

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

通過這個函數,Supabase 可以確定當前訪問資料庫的使用者。

創建行級安全性策略

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

  1. 導航到 Supabase 控制台中的表格編輯器頁面並選擇 posts 表格。
  2. 點擊表格頂部的“新增 RLS 策略”。
  3. 在提示的窗口中,點擊“創建政策”。
  4. 輸入一個策略名稱並選擇 SELECT 策略命令。
  5. 在以下代碼的 using 區塊中輸入:
Create RLS policy

通過利用這些策略,在 Supabase 中可實現數據訪問控制。

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

與 Logto 的基本整合過程

如前所述,由於 Supabase 利用 RLS 來進行訪問控制,與 Logto(或任何其他驗證服務)的整合關鍵在於獲取授權使用者的 user id 並將其傳送給 Supabase。整個過程如下圖所示:

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

Logto 整合

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

通常,用這些框架和語言構建的應用程式大致可以分為:本機應用程式、SPA(單頁應用程式)、傳統 Web 應用程式和 M2M(機器到機器)應用程式。你可以訪問 Logto 入門教程頁面,根據你使用的技術棧將 Logto 整合到你的應用程式中。然後,按照本文後續說明,根據你的應用程式類型將 Logto 整合到你的專案中。

本機應用程式或 SPA

本機應用程式和 SPA 都在你的設備上運行,登錄後獲得的憑證(訪問令牌)存儲在你的設備上。

因此,在將你的應用程式與 Supabase 整合時,你需要透過你的後端服務與 Supabase 互動,因為你不能在每個使用者的設備上暴露敏感資訊(如 Supabase JWT secret)。

假設你正在使用 React 和 Express 構建你的 SPA。你已經按照 Logto React SDK 指南 將 Logto 成功整合到你的應用程式中(你可以參考我們的 react 範例中的代碼)。此外,你已經根據 保護你的 API 的 Node (Express) 文檔將 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 檢索用戶信息並構建用於與 Supabase 交互的對應 JWT。

機器到機器應用程式

機器到機器(M2M)通常用於當你的應用程式需要直接與資源伺服器通信時,例如提取每日文章的靜態服務等。

你可以使用 機器到機器: 使用 Logto 進行認證 指南進行機器到機器應用程式認證。Supabase 與機器到機器應用程式的集成與本地應用程式和單頁應用程式的集成類似(如“本地應用程式或單頁應用程式”部分所述)。它涉及從 Logto 獲取訪問令牌,然後通過受保護的後端 API 驗證它。

然而,需要注意的是,本地應用程式和單頁應用程式通常是為最終使用者設計的,因此獲得的使用者 ID 代表使用者本身。然而,機器到機器應用程式的訪問令牌代表的則是應用程式本身,其訪問令牌有效負載中的 sub 欄位是 M2M 應用程式的客戶端 ID,而不是特定的使用者。因此,在開發過程中,區分那些數據是為機器到機器應用程式設計的至關重要。

如果你希望特定的 M2M 應用程式代表整個服務訪問 Supabase 進而繞過 RLS 限制,你可以使用 Supabase 的 service_role 秘鑰創建 Supabase 客戶端。這在你想執行一些管理或自動化任務時很有用,因為這些任務需要在不受為個別使用者設置的行級安全性策略限制的情況下訪問所有數據。

service_role 秘鑰可以在與 JWT 秘鑰相同的頁面上找到:

Service role secret

創建 Supabase 客戶端時,使用 service_role 秘鑰,然後該客戶端可以訪問數據庫中的所有數據:

總結

在本文中,我們深入探討將 Logto 與 Supabase 整合,並闡明了關鍵見解和重要的整合方面。我們探討了像 JWT 驗證和行級安全性策略這樣的概念,指導你如何在你的 Supabase 驅動的應用程式中無縫地引入 Logto。希望通過這些知識,你能夠自信地增強應用程式的安全性、功能,甚至可以通過附加功能擴展你的專案。