Source:
ocean/docs/adr/005-supabase-jwt-authentication.md| ✏️ Edit on GitHub
ADR-005: Supabase JWT Authentication System
Status: Accepted
Date: 2025-07-28
Decision makers: Engineering Team
Context
We've encountered recurring confusion about Supabase's authentication system. The platform has migrated from legacy API keys to a modern JWT-based security model, but our codebase and scripts still reference outdated authentication methods.
Current State Investigation
Based on our Supabase project and Edge Functions:
- Two Authentication Systems: Supabase supports both JWT tokens AND API keys
- API Key System:
- Publishable Key (starts with
sb_publishable_): Safe for client-side use - Secret Key (starts with
sb_secret_): Server-side only, privileged access
- Publishable Key (starts with
- JWT System: User authentication tokens for authenticated requests
- Edge Functions: Use Deno 1.45.2 runtime with specific import requirements
Decision
We will use Supabase's dual authentication system with both API keys and JWT tokens:
1. Authentication Types
- Client-side: Use publishable key (sbpublishable*) for public operations
- Server-side/Edge Functions: Use secret key (sbsecret*) for privileged operations
- User Authentication: Use JWT tokens from Supabase Auth sessions
- Testing: Use secret key for server-side test operations
2. Environment Variables
# Modern Supabase environment variables
SUPABASE_URL=https://[project-ref].supabase.co
SUPABASE_PUBLISHABLE_KEY=sb_publishable_[key] # Client-safe operations
SUPABASE_SECRET_KEY=sb_secret_[key] # Server-side privileged access
# User JWT tokens are obtained dynamically through auth flow
3. Authentication Patterns
Client-side (React)
// Use Supabase Auth - no keys needed in client
const {
data: { user },
} = await supabase.auth.getUser()
const token = (await supabase.auth.getSession()).data.session?.access_token
Edge Functions
// Use secret key for privileged operations
const supabaseUrl = Deno.env.get('SUPABASE_URL')!
const supabaseSecretKey = Deno.env.get('SUPABASE_SECRET_KEY')!
const supabase = createClient(supabaseUrl, supabaseSecretKey)
// For user authentication from requests
const authHeader = req.headers.get('authorization')
const token = authHeader?.replace('Bearer ', '')
const {
data: { user },
} = await supabase.auth.getUser(token)
Testing Scripts
// For server-side testing, use secret key
const supabase = createClient(supabaseUrl, supabaseSecretKey)
// For user authentication testing
const { data, error } = await supabase.auth.signInWithOtp({
email: 'test@example.com',
})
4. Common Mistakes to Avoid
- ❌ Looking for
SUPABASE_ANON_KEY- useSUPABASE_PUBLISHABLE_KEYinstead - ❌ Using publishable key for server-side operations - use secret key
- ❌ Using secret key in client-side code - use publishable key
- ❌ Hardcoding any keys in code
- ❌ Using npm: imports in Edge Functions (use https://esm.sh/)
5. GraphQL Authentication
For our GraphQL endpoint, authentication should work as follows:
// No authentication required for health/metrics
if (url.pathname.endsWith('/health') || url.pathname.endsWith('/metrics')) {
// Public endpoints
}
// GraphQL queries require user authentication
const authHeader = req.headers.get('authorization')
if (!authHeader) {
return new Response('Unauthorized', { status: 401 })
}
Consequences
Positive
- Enhanced security with JWT-based authentication
- No client-side keys to manage or rotate
- Proper user-based access control
- Alignment with Supabase best practices
Negative
- Breaking change for existing scripts expecting anon keys
- Need to update all test scripts to use proper authentication
- More complex testing setup (need actual user sessions)
Implementation Notes
- Update environment variables to use proper API key naming:
- Replace
VITE_SUPABASE_ANON_KEYwithSUPABASE_PUBLISHABLE_KEY - Add
SUPABASE_SECRET_KEYfor server-side operations
- Replace
- Update test scripts to use:
- Secret key for server-side testing operations
- User JWT tokens for user-specific tests
- Document the dual authentication system in README
- Update CI/CD to use correct API key environment variables