Source:
ocean/docs/adr/0007-migrate-to-publishable-keys.md| ✏️ Edit on GitHub
ADR-0007: Migrate from Legacy JWT Keys to Publishable/Secret API Keys
Status
Accepted
Context
Currently using legacy JWT-based API keys (anon_key and service_role) which:
- Are tied to the legacy JWT secret that we want to rotate
- Don't have the same security protections as new publishable/secret keys
- Prevent us from fully migrating away from the legacy JWT secret
Supabase now offers a modern API key system:
- Publishable keys: For client-side use (replaces anon_key)
- Secret keys: For server-side use (replaces service_role)
Decision
Migrate from legacy JWT-based keys to the new publishable/secret key system to:
- Enable rotation of the legacy JWT secret
- Improve security with built-in protections
- Align with Supabase's recommended practices
Implementation
1. Client-Side Changes (Browser)
Replace VITE_SUPABASE_ANON_KEY with VITE_SUPABASE_PUBLISHABLE_KEY:
// Old
const supabase = createClient(url, anonKey)
// New
const supabase = createClient(url, publishableKey)
2. Environment Variables
Update all environment files:
# Remove
VITE_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
# Add
VITE_SUPABASE_PUBLISHABLE_KEY=pk_live_...
3. Server-Side (if applicable)
For any server-side operations, use secret keys instead of service_role:
# Remove
SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
# Add
SUPABASE_SECRET_KEY=sk_live_...
Migration Steps
- Generate new keys in Supabase Dashboard > Settings > API
- Update environment variables in all environments
- Deploy changes to all clients
- Monitor for any authentication issues
- Deactivate legacy keys after confirming all clients migrated
- Rotate legacy JWT secret once legacy keys are no longer in use
Consequences
Positive
- Can rotate legacy JWT secret without breaking existing clients
- Better security with built-in browser detection for secret keys
- Clearer distinction between public and private keys
- Aligned with Supabase best practices
Negative
- Requires updating all environment configurations
- Need to coordinate deployment across all environments
- Brief period where both key systems are active
Limitations to Consider
- New keys can't be used in Authorization Bearer header
- Edge Functions require
--no-verify-jwtflag with new keys - Realtime connections have 24-hour limitation with new keys
References
- Supabase API Keys Documentation
- Legacy JWT secret: vYgjE4DGRTi77K31JCTeqGkyKpE3UlpMrbyhgHIJjm9oKrSwK4zudfVZKyE6f9CnvmD0HtcagkiQaqOrqO7fjg==