Clerk logo

Clerk Docs

Ctrl + K
Go to clerk.devGet API keys

Supabase

Learn how to integrate Clerk into your Supabase application

Learn more about Clerk and Supabase.

Overview

Supabase is the open source alternative to Firebase. It offers cloud-based access to a full PostgreSQL database as well as realtime subscriptions and storage solutions. Although Supabase offers a built-in authentication and user management service with Supabase Auth, it requires the user data to be stored in your own database. With Clerk, you can get the benefits of the backend services they provide without the hassle of managing your own user database.

The Clerk integration with Supabase enables you to authenticate requests to your Supabase database using a JSON Web Token (JWT) created with our JWT Templates feature.

This guide will walk you through the necessary steps to integrate Clerk as the external authentication provider for Supabase.

Get started

The first step is to create a new Clerk application from your Clerk Dashboard if you haven’t done so already. You can choose whichever authentication strategy and social login providers you prefer. For more information, check out our Set up your application guide.

After your Clerk application has been created, use the lefthand menu to navigate to the JWT Templates page.

Click on the button to create a new template based on Supabase.

This will pre-populate the default claims required by Supabase. You can include additional claims or modify them as necessary. Shortcodes are also available to make adding dynamic user values easy.

Note the name of the JWT template (which you can change) because this will be needed later.

Supabase requires that JWTs be signed with the H256 signing algorithm and use their signing key. You can locate the JWT secret key in your Supabase project under Settings > API in the Config section.

Reveal the JWT secret to copy it and then paste it in the Signing key field in the Clerk JWT template. ​​After the key is added, you can click the Apply Changes button to save your template.

Configure your client

To configure your client, you need to set some local environment variables. Assuming a React application, set the following:

REACT_APP_CLERK_FRONTEND_API=your-frontend-api
REACT_APP_SUPABASE_URL=your-supabase-url
REACT_APP_SUPABASE_KEY=your-supabase-anon-key

Note: If you’re using Next.js, replace the REACT_APP prefix with NEXT_PUBLIC

Your Clerk Frontend API can be found on the Clerk Dashboard home in the API Keys section.

To get the ones needed for Supabase, navigate to the same Settings > API page as before and locate the anon public key and URL.​

After setting those three environment variables, you should be able to start up your application development server.

Install the JavaScript client for Supabase with:

npminstall @supabase/supabase-js

You can then initialize the Supabase client by passing it the environment variables:

import { createClient } from '@supabase/supabase-js';
const supabaseUrl = process.env.REACT_APP_SUPABASE_URL;
const supabaseKey = process.env.REACT_APP_SUPABASE_KEY;
export const supabase = createClient(supabaseUrl, supabaseKey);
export default supabase;

In order to access the custom JWT, you can use the getToken function returned by the Clerk useAuth hook and pass it the name of your template (hopefully you remembered from earlier).

Note: The getToken({ template: <your-template-name> }) call is asynchronous and returns a Promise that needs to be resolved before accessing the token value. This token is short-lived for better security and should be called before every request to your Supabase backend. The caching and refreshing of the token is handled automatically by Clerk.

Call supabase.auth.setAuth(token) to override the JWT on the current client. The JWT will then be sent to Supabase with all subsequent network requests.

import { useAuth } from '@clerk/clerk-react';
import supabase from './lib/supabaseClient';
function App() {
const { getToken } = useAuth();
const fetchData = async () => {
// TODO #1: Replace with your JWT template name
const token = await getToken({ template: 'supabase' });
supabase.auth.setAuth(token);
// TODO #2: Replace with your database table name
const { data, error } = await supabase.from('your_table').select();
// TODO #3: Handle the response
};
return (
<div className="app">
<button onClick={fetchData}>Fetch data</button>
</div>
);
}

Access user ID in RLS policies

It is common practice to need access to the user identifier on the database level, especially when working with RLS policies in Postgres. Although Supabase provides a special function auth.uid() to extract the user ID from the JWT, this does not currently work with Clerk. The workaround is to write a custom SQL function to read the sub property from the JWT claims.

In the SQL Editor section of the Supabase dashboard, click New Query and enter the following:

create or replace function requesting_user_id()
returns text
language sql stable
as $$
select nullif(current_setting('request.jwt.claims', true)::json->>'sub', '')::text;
$$;

This will create a requesting_user_id() function that can be used within an RLS policy.

For example, this policy would check that the user making the request is authenticated and matches the user_id column of a todos table.

CREATE POLICY "Authenticated users can update their own todos"
ON public.todos FOR UPDATE USING (
auth.role() = 'authenticated'::text
) WITH CHECK (
requesting_user_id() = user_id
);

Next steps

Was this helpful?

Clerk © 2022