Integrate Supabase with Clerk
You will learn the following:
- Use Clerk to authenticate access to your Supabase data
- Access Clerk user IDs in your Supabase RLS policies
- Customize a Clerk JWT template to suit your use case with Supabase
Integrating Supabase with Clerk gives you the benefits of using a Supabase database while leveraging Clerk's authentication, prebuilt components, and webhooks. To get the most out of Supabase with Clerk, you must implement custom Row Level Security (RLS) policies.
RLS works by validating database queries according to the restrictions defined in the RLS policies applied to the table. This guide will show you how to create RLS policies that restrict access to data based on the user's Clerk ID. This way, users can only access data that belongs to them. To set this up, you will:
- Create a function in Supabase to parse the Clerk user ID from the authentication token.
- Create a
user_id
column that defaults to the Clerk user's ID when new records are created. - Create policies to restrict what data can be read and inserted.
- Use the Clerk Supabase integration helper in your code to authenticate with Supabase and execute queries.
This guide will have you create a new table in your Supabase project, but you can apply these concepts to your existing tables as well.
Choose your own adventure
For interacting with the Supabase dashboard, you can either use the Supabase interface or the SQL Editor. The SQL Editor is a more direct way to interact with your database, but the Supabase interface provides a more user-friendly experience.
Create a SQL query that checks the user ID
Create a function named requesting_user_id()
that will parse the Clerk user ID from the authentication token. This function will be used to set the default value of user_id
in a table and in the RLS policies to ensure the user can only access their data.
- In the sidebar of your Supabase dashboard, navigate to Database > Functions.
- Select Create a new function.
- In the Add a new function sheet, make the following changes:
- Set Name of function to
requesting_user_id
. - Set Return type to
text
. - Toggle Show advanced settings on.
- Set Language to
sql
. - Populate the Definition with the following sql:
- Select Confirm.
- Set Name of function to
- In the sidebar of your Supabase dashboard, navigate to SQL Editor, and paste the following into the editor:
- To execute the query and create the
requesting_user_id()
function, select Run.
Create a table and enable RLS on it
Next, you'll create a tasks
table and enable RLS on that table. The tasks
table will also contain a user_id
column that will use the requesting_user_id()
function you just created as it's default value. This column will be used in the RLS policies to only return or modify records scoped to the user's account.
In the left navigation, select Table Editor and select Create a new table. In the sheet that appears in the right, configure the following settings:
- Name:
tasks
. - Toggle on Enable Row Level Security (RLS).
- Set up the Columns with the following configuration:
Name Type Default value Primary Additional settings (Gear icon) id int8 NULL Checked Is identity name text user_id text requesting_user_id() - Select Save.
- In the sidebar of your Supabase dashboard, navigate to SQL Editor.
- To create the
"tasks"
table and enable RLS on it, run the following two queries:
Create ID-based RLS policies
Create RLS policies that permit users to read and insert content associated with their user IDs only.
In the sidebar, navigate to Authentication > Policies. Create policies that allow your users to read and insert data into the tasks
table:
- Select Create policy to create the
SELECT
policy:- Name: "Select tasks policy".
- For Policy Command, select SELECT.
- For Target roles, select authenticated.
- Replace the "-- Provide a SQL expression for the using statement" with the following:
- Select Save policy.
- Select Create policy to create the
INSERT
policy:- Name: "Insert task policy".
- For Policy Command, select INSERT.
- For Target roles, select authenticated.
- Replace the "-- Provide a SQL expression for the with check statement" with the following:
- Select Save policy.
- In the sidebar of your Supabase dashboard, navigate to SQL Editor
- Run the following queries to add policies for all statements issued on
"tasks"
:
Get your Supabase JWT secret key
To give users access to your data, Supabase's API requires an authentication token. Your Clerk project can generate these authentication tokens, but it needs your Supabase project's JWT secret key first.
To find the JWT secret key:
- In the sidebar, navigate to Project Settings > API.
- Under the JWT Settings section, save the value in the JWT Secret field somewhere secure. This value will be used in the next step.
Create a Supabase JWT template
Clerk's JWT templates allow you to generate a new valid Supabase authentication token for each signed in user. These tokens allow authenticated users to access your data with Supabase's API.
To create a JWT template for Supabase:
- Navigate to the Clerk Dashboard.
- In the navigation sidebar, select JWT Templates.
- Select the New template button, then select Supabase from the list of options.
- Configure your template:
- The value of the Name field will be required when using the template in your code. For this tutorial, name it
supabase
. - Signing algorithm will be
HS256
by default. This algorithm is required to use JWTs with Supabase. Learn more in their docs. - Under Signing key, add the value of your Supabase JWT secret key from the previous step.
- You can leave all other fields at their default settings or customize them to your needs. See the JWT template guide to learn more about these settings.
- Select Save from the notification bubble to complete setup.
- The value of the Name field will be required when using the template in your code. For this tutorial, name it
Install the Supabase client library
Add the Supabase client library to your project.
Set up your environment variables
- In the sidebar of the Supabase dashboard, select Settings > API.
- Add the Project URL to your
.env.local
file asSUPABASE_URL
. - In the Project API keys section, add the value beside
anon
public
to your.env.local
file asSUPABASE_KEY
.
Fetch Supabase data in your code
The following example shows the list of tasks for the user and allows the user to add new tasks.
The createClerkSupabaseClient()
function uses Supabase's createClient()
method to initialize a new Supabase client, but modifies it to inject the Clerk token you created with the Supabase JWT template into the request headers sent to Supabase. The requesting_user_id()
function that was created in the Supabase dashboard will parse this token to use it when querying data from the tasks
table.
The following example uses the Next.js SDK to access the useUser()
and useSession()
hooks, but you can adapt this code to work with any React-based Clerk SDK.
The following example uses the Next.js SDK to demonstrate how to integrate Supabase with Clerk in a server-side rendered application.
The createClerkSupabaseClientSsr()
function is stored in a separate file so that it can be re-used in multiple places, such as within page.tsx
or a Server Action file. This function uses the auth().getToken()
method to get the Clerk token and inject it into the request headers sent to Supabase.
The following files render the /ssr
page and handle the "Add task" form submission. Use the following tabs to view the code for each page.
Test your integration
Run your project and sign in. Test creating and viewing tasks. Sign out and sign in as a different user, and repeat.
If you have the same tasks across multiple accounts, double check that RLS is enabled, or that the RLS policies were properly created. Check the table in the Supabase dashboard. You should see all the tasks between both users, but with differing values in the user_id
column.
Feedback
Last updated on