Using Supabase RLS with a custom auth provider

Grace Wang
3 min readJan 20, 2022

--

A quick write-up on how to take advantage of Supabase row level security (RLS) when using a custom authentication provider!

First off, what is Supabase? It’s an open-source Firebase alternative… It’s a backend-as-a-service… It’s a way to go from Postgres schema → REST API in minutes!

I love the product as I feel that the current state of software engineering is somehow simultaneously tedious and difficult, and Supabase goes a long way towards solving this. Case in point: pagination, something that’s often overlooked by less experienced engineers but is a slog to implement.

Supabase supports many authentication providers such as Facebook, Twitter, Github, and more. However, recently I’ve been building in the web3 space which relies on wallet authentication. I still wanted to take advantage of Supabase’s row level security though, so I don’t have to write additional middleware.

This required a few steps:

  1. Obtain the Supabase JWT secret
  2. When the user authenticates, set a cookie containing a signed JWT from the server
  3. Call setAuth() from the client to make requests as the user
  4. Use the JWT data in either your RLS policy or in column default values

1. Obtain the Supabase JWT Secret

This step is easy 🙂 The secret can be found in the Supabase Dashboard, under Settings > API > Config.

Settings > API > Config > JWT Secret

We need to use this particular secret to sign our JWTs because Supabase automatically verifies/decodes the JWT and sets Postgres config which we will use later in step 4.

2. Set a cookie with a signed JWT

When the user authenticates, your server will need to sign a JWT using the secret from step 1 and set it as a cookie.

The JWT payload can be any JSON and may look something like this for wallet authentication:

{
"address": "0x9B572394d0f7bE31967D02E84D1C1D19c5E7d3E1"
}

Example snippet assuming the jsonwebtoken package (imported as jwt) and Express:

const token = jwt.sign({ address: recoveredAddress }, process.env.JWT_SECRET);
res.status(200).setHeader('Set-Cookie', serialize('mytoken', token, { path: "/" }));

3. Call setAuth() from the client

When making calls to the Supabase API, make sure to call setAuth using the JWT from step 2 to make calls as the user.

Using the js-cookie package (imported as Cookies):

supabase.auth.setAuth(Cookies.get("mytoken"))

4. Use the JWT data!

Finally 🙂 You can reference the data from the JWT payload in either your RLS policy or in column default values.

RLS policy
Column default value

Make sure you use this syntax versus an older one (current_setting(”request.jwt.claim.address”, true)) which was used prior to Postgres 14. Read more here.

🥳

And that’s it! If this was helpful, consider following me on Twitter for more software & web3 content 🙂

--

--

Grace Wang

Dev, perpetually “starting something new” 🙂 Prev @Palantir, @PennEngineering