Migration Guide
This guide will help you migrate from v1.x
to v2.x
, which introduces support for Supabase's new JWT signing keys.
🔐 What are JWT Signing Keys?
Supabase has introduced a major security improvement by moving from symmetric to asymmetric JWT (JSON Web Token) signing. This change brings security and performance improvements in how your applications handle authentication.
The Problem with Symmetric Keys
Previously, Supabase used a single shared secret key for both creating and verifying tokens. This meant your app had to constantly call supabase.auth.getUser()
to check if sessions were valid, creating network delays calling the Supabase Auth server.
The Solution with Asymmetric JWT Signing Keys
The new system uses two separate keys:
- A private key (kept secure by Supabase) for creating tokens.
- A public key (safe to share in your application) for verifying them.
Your application can now verify user sessions locally without contacting Supabase servers, making it faster and more reliable. This new key is named as publishable key
on Supabase.
Key Benefits
This upgrade eliminates authentication bottlenecks, improves security, and makes your applications work better at the edge (no extra calls to the Supabase Auth server).
🚨 Breaking changes
useSupabaseUser
Type Changes 1.
useSupabaseUser
now returns JWT claims instead of the full User object.
- Before (v1.x):
useSupabaseUser
returned the fullUser
object from auth.getUser() - After (v2.x):
useSupabaseUser
returnsClaims
object from auth.getClaims() as a JWT Payload
{
id: "11111111-1111-1111-1111-111111111111",
aud: "authenticated",
role: "authenticated",
email: "example@email.com",
email_confirmed_at: "2024-01-01T00:00:00Z",
phone: "",
confirmed_at: "2024-01-01T00:00:00Z",
last_sign_in_at: "2024-01-01T00:00:00Z",
app_metadata: {},
user_metadata: {},
identities: []
}
{
session_id: "11111111-1111-1111-1111-111111111111",
sub: "11111111-1111-1111-1111-111111111111",
aud: "authenticated",
role: "authenticated",
email: "example@email.com",
aal: "aal1",
amr: [],
exp: 1715769600,
iat: 1715766000,
is_anonymous: false,
iss: "https://project-id.supabase.co/auth/v1",
phone: "+13334445555",
app_metadata: {},
user_metadata: {},
// identities is missing
// last_sign_in_at is missing
// confirmed_at is missing
// email_confirmed_at is missing
}
auth.getUser()
but if you only need basic info (email, role...) no changes are required.2. Environment variables changes
Remaining key → SUPABASE_KEY
is now storing the publishable key
instead of the anon key
New key → SUPABASE_SECRET_KEY
is now storing the secret key
of your Supabase project
Deprecated key → SUPABASE_SERVICE_KEY
was previously storing the service_role key
but is now deprecated in favor of SUPABASE_SECRET_KEY
📋 Migration Steps
1. Types changes
The first thing you need to do is to ensure the useSupabaseUser
changes do not affect your existing code.
2. Environment variables changes
The Good news ☀️ is that everything will continue to work as-is with your existing SUPABASE_KEY
(aka anon key
).
Same for SUPABASE_SERVICE_KEY
, if you're using it to bypass Row Level Security, you will face a deprecation warning but it will still work.
SUPABASE_KEY
and your secret key as SUPABASE_SECRET_KEY
.2.a. Enable JWT Signing Keys in Supabase Dashboard
Before migrating your environment variables, you need to enable JWT signing keys and thus create your JWT and API keys in your Supabase project:
2.b. Use your new keys in your .env
file
SUPABASE_KEY=<your_publishable_key>
SUPABASE_SECRET_KEY=<your_secret_key>