Auth & Tokens
Authentication is how your app knows who is talking to it. JWTs (JSON Web Tokens) are the standard. Understanding them is the difference between a secure app and a data breach waiting to happen.
Why Authentication Matters
Without authentication, every request to your app is anonymous. Anyone can read anyone's data. Anyone can modify anyone's records. Authentication proves identity — it answers "who is making this request?" before your app does anything.
Supabase handles the hard parts (password hashing, session management, email verification) so you never write security-critical code yourself. You get a battle-tested auth system with one import.
JWT Anatomy: Three Parts, One Token
A JWT has three parts separated by dots. Each part is base64url-encoded. Together they form a self-contained credential that proves who the user is without hitting a database on every request.
"typ": "JWT" } // token type
Tells the server which algorithm was used to create the signature. HS256 (HMAC with SHA-256) is the most common for Supabase.
"email": "builder@example.com", // custom claim
"role": "authenticated", // Supabase role
"iat": 1711152000, // issued at (Unix timestamp)
"exp": 1711155600 } // expires in 1 hour
The actual data. sub is the user ID — Supabase's auth.uid() extracts this for RLS. exp is when the token expires (default: 1 hour). The payload is NOT encrypted — anyone can decode it. It is only signed.
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret // your JWT secret (server-side only)
)
The server uses this to verify the token was not tampered with. If anyone changes the payload (e.g., swapping their user ID for another's), the signature will not match, and the server rejects the request.
The Auth Flow: Signup to Database Query
Here is exactly what happens from the moment a user signs up to the moment they read their own data — and how JWT + RLS work together at each step.
supabase.auth.signUp()Authorization: Bearer header with every API callauth.uid() from the JWT and scopes all queries to that user's rowsSupabase Auth in Code
The Supabase client handles token management automatically — storing tokens, refreshing expired ones, and attaching them to requests. You rarely need to touch JWTs directly.
import { createClient } from '@supabase/supabase-js'
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY
)
// Sign up a new user
const { data, error } = await supabase.auth.signUp({
email: 'builder@example.com',
password: 'secure-password-123'
})
// Sign in an existing user
const { data, error } = await supabase.auth.signInWithPassword({
email: 'builder@example.com',
password: 'secure-password-123'
})
// Get the current session (includes the JWT)
const { data: { session } } = await supabase.auth.getSession()
console.log(session.access_token) // This is the JWT!
// All subsequent queries automatically use the JWT
// RLS scopes results to this user's rows
const { data } = await supabase
.from('user_data')
.select('*') // returns only this user's rows
This lesson is for Pro members
Unlock all 520+ lessons across 52 courses with Academy Pro.
Already a member? Sign in to access your lessons.