Using Supabase RLS with a custom auth provider
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:
- Obtain the Supabase JWT secret
- When the user authenticates, set a cookie containing a signed JWT from the server
- Call
setAuth()
from the client to make requests as the user - 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.
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.
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 🙂