You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/quick-starts/database/supabase/README.mdx
+275Lines changed: 275 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -3,6 +3,281 @@ slug: /quick-starts/supabase
3
3
sidebar_label: Supabase
4
4
sidebar_custom_props:
5
5
description: Integrate Logto with Supabase.
6
+
logoFilename: 'supabase.svg'
6
7
---
7
8
8
9
# Integrate Logto with Supabase
10
+
11
+
## Supabase basics
12
+
13
+
Supabase utilizes [Postgres's Row-Level Security](https://www.postgresql.org/docs/current/ddl-rowsecurity.html) to control data access permissions. In simple terms, by creating Row Level Security policies for tables in the database, we can restrict and manage who can read, write, and update data in a table.
14
+
15
+
Let's assume you have a table named "posts" in your database, with the following content:
16
+
17
+

18
+
19
+
The `user_id` field in the table represents the user to whom each post data belongs. You can restrict each user to only access their own post data based on the `user_id` field.
20
+
21
+
However, before this can be implemented, Supabase needs to be able to identify the current user accessing the database.
22
+
23
+
### Add user data to the Supabase requests
24
+
25
+
Thanks to Supabase's support for JWT, when our application interacts with Supabase, we can generate a JWT containing user data using the JWT secret provided by Supabase. We then use this JWT as the Authentication header when making requests. Upon receiving the request, Supabase automatically verifies the validity of the JWT and allows access to the data contained within it throughout subsequent processes.
26
+
27
+
Firstly, we can obtain the JWT secret provided by Supabase from the “Project Settings” in the Supabase dashboard:
28
+
29
+

30
+
31
+
Then, when we use the Supabase SDK to make requests to Supabase, we utilize this secret to generate our JWT and attach it as the Authentication header to the request. (Please note that this process occurs within your application's backend service, and the JWT secret should never be exposed to third parties).
As the code shows, in Supabase, you can retrieve the payload of the JWT we generate by calling `request.jwt.claims`. The `userId` field inside the payload is the value we have set.
80
+
81
+
With this function, Supabase can determine the user who is currently accessing the database.
82
+
83
+
### Create Row-Level Security policy
84
+
85
+
Next, we can create a Row-Level Security policy to restrict each user to only access their own post data based on the `user_id` field in the posts table.
86
+
87
+
1. Navigate to the Table Editor page in the Supabase dashboard and select the posts table.
88
+
2. Click on "Add RLS Policy" at the top of the table.
89
+
3. In the prompted window, click "Create policy".
90
+
4. Input a Policy Name and choose the SELECT Policy command.
91
+
5. In the `using` block of the code below, enter:
92
+
93
+
```sql
94
+
auth.user_id() = user_id
95
+
```
96
+
97
+

98
+
99
+
By leveraging such policies, data access control within Supabase is achieved.
100
+
101
+
In real-world applications, you would create various policies to restrict user actions such as data insertion and modification. However, this is beyond the scope of this article. For more information on Row-Level Security (RLS), please refer to [Secure your data using Postgres Row Level Security](https://supabase.com/docs/guides/database/postgres/row-level-security).
102
+
103
+
### Basic integration process with Logto
104
+
105
+
As mentioned earlier, because Supabase utilizes RLS for its access control, the key to integrating with Logto (or any other authentication service) lies in obtaining the user id of the authorized user and sending it to Supabase. The entire process is illustrated in the diagram below:
106
+
107
+
```mermaid
108
+
sequenceDiagram
109
+
Participant U as End user
110
+
Participant Logto
111
+
Participant B as App backend service
112
+
Participant Supabase
113
+
114
+
U->>Logto: Sign in with Logto
115
+
Logto-->>U: `access_token`
116
+
U->>B: Request data with `access_token`
117
+
B->>B: Retrieve `user_id` from `access_token`
118
+
B->>B: Generate jwt by `user_id` & `Supabase JWT secret`
119
+
B->>Supabase: Request data with jwt
120
+
Supabase-->>B: Responded data
121
+
B-->>U: Responded data
122
+
```
123
+
124
+
Next, we will explain how to integrate Logto with Supabase based on this process diagram.
125
+
126
+
## Logto integration
127
+
128
+
Logto offers integration guides for various frameworks and programming languages.
129
+
130
+
Generally, apps built with these frameworks and languages fall into categories such as Native apps, SPA (single-page apps), traditional web apps, and M2M (machine-to-machine) apps. You can visit the [Logto quick starts](../../quick-starts) page to integrate Logto into your application based on the tech stack you are using. Afterward, follow the instructions below to integrate Logto into your project based on the type of your application.
131
+
132
+
### Native app or SPA
133
+
134
+
Both native apps and SPAs run on your device, and the credentials (access token) obtained after login are stored locally on your device.
135
+
136
+
Therefore, when integrating your app with Supabase, you need to interact with Supabase through your backend service because you cannot expose sensitive information (like Supabase JWT secret) on each user's device.
137
+
138
+
Let's assume you're building your SPA using React and Express. You've successfully integrated Logto into your application by following the [Logto React SDK Guide](../../quick-starts/react/) (you can refer to the code in our [react sample](https://github.com/logto-io/js/tree/master/packages/react-sample)). Additionally, you've added Logto access token validation to your backend server according to the [Protect your API on Node (Express)](../../../docs/recipes/protect-your-api/node/) documentation.
139
+
140
+
Next, you'll use the access token obtained from Logto to request user data from your backend server:
Now, you can use the `getSupabaseClient` described above to attach the `userId` to the JWT used in subsequent requests to Supabase. Alternatively, you can create a middleware to create a Supabase client for requests that need to interact with Supabase:
In the subsequent processing flow, you can directly call `ctx.supabase` to interact with Supabase:
221
+
222
+
```jsx
223
+
constfetchPosts=async (ctx) => {
224
+
cosnt { data } =awaitctx.supabase.from('posts').select('*');
225
+
226
+
return data;
227
+
}
228
+
```
229
+
230
+
In this code, Supabase will return only the post data belonging to the current user based on the previously set policies.
231
+
232
+
### Traditional web app
233
+
234
+
The main difference between a traditional web app and a Native app or SPA is that a traditional web app renders and updates pages solely on the web server. Therefore, user credentials are managed directly by the web server, while in Native apps and SPAs, they reside on the user's device.
235
+
236
+
When integrating Logto with a traditional web app in Supabase, you can directly retrieve the logged-in user's id from the backend.
237
+
238
+
Taking a Next.js project as an example, after you integrate Logto with your project following the [Next.js SDK Guide](../../quick-starts/next-app-router/), you can use the Logto SDK to retrieve user information and construct the corresponding JWT for interacting with Supabase.
Machine-to-machine (M2M) is often used when your app needs to communicate directly with resource servers, such as a static service that pulls daily posts, etc.
261
+
262
+
You can use the [Machine-to-machine: Auth with Logto](../../quick-starts/m2m/) guide for machine-to-machine app authentication. The integration between Supabase and Machine-to-machine apps is similar to that of Native apps and SPAs (as described in the "[Native app or SPA](#native-app-or-spa)" section). It involves obtaining an access token from Logto and then validating it through a protected backend API.
263
+
264
+
However, it's important to note that Native apps and SPAs are typically designed for end-users, so the user id obtained represents the user itself. However, the access token for machine-to-machine apps represents the application itself, and the `sub` field in the access token payload is the client id of the M2M app, not a specific user. Therefore, during development, it's crucial to distinguish which data is intended for M2M apps.
265
+
266
+
Further more, if you want a specific M2M app to access Supabase on behalf of the entire service to bypass RLS restrictions, you can use Supabase's `service_role` secret to create a Supabase client. It’s useful when you want to make some administrative or automated tasks that require access to all data without being restricted by the Row-Level Security policies set up for individual users.
267
+
268
+
The `service_role` secret can be found on the same page as the JWT secret:
269
+
270
+

271
+
272
+
When creating a Supabase client, use the `service_role` secret, then this client can access all data in the database:
0 commit comments