Documentation Index Fetch the complete documentation index at: https://mintlify.com/supabase/supabase/llms.txt
Use this file to discover all available pages before exploring further.
Supabase Auth is a complete authentication system that handles user sign-ups, logins, and session management. It’s built on top of PostgreSQL and integrates seamlessly with Row Level Security for authorization.
Architecture
Supabase Auth consists of four major layers:
Client Layer : Your application code using Supabase SDKs or direct HTTP calls
Kong API Gateway : Routes requests and validates JWTs
Auth Service (GoTrue) : Manages authentication logic and token issuance
PostgreSQL Database : Stores user data in the auth schema
The Auth service is a fork of GoTrue , originally created by Netlify and enhanced by Supabase.
How Authentication Works
When a user signs in:
Client sends credentials to the Auth service via the API gateway
Auth service validates credentials against the database
Upon success, Auth service issues a JWT (JSON Web Token)
Client stores the JWT and includes it in subsequent requests
Kong gateway validates the JWT on each request
PostgreSQL uses the JWT to enforce Row Level Security policies
Authentication Methods
Supabase Auth supports multiple authentication methods:
Email and Password
The traditional username/password approach:
// Sign up a new user
const { data , error } = await supabase . auth . signUp ({
email: 'user@example.com' ,
password: 'secure-password' ,
options: {
data: {
first_name: 'John' ,
last_name: 'Doe'
}
}
})
// Sign in an existing user
const { data , error } = await supabase . auth . signInWithPassword ({
email: 'user@example.com' ,
password: 'secure-password'
})
Magic Links
Passwordless authentication via email:
// Send magic link to user's email
const { data , error } = await supabase . auth . signInWithOtp ({
email: 'user@example.com' ,
options: {
emailRedirectTo: 'https://example.com/welcome'
}
})
OAuth Providers
Supabase supports 20+ OAuth providers including:
Google
GitHub
Apple
Facebook
Twitter
Microsoft
Discord
And many more…
// Sign in with Google
const { data , error } = await supabase . auth . signInWithOAuth ({
provider: 'google' ,
options: {
redirectTo: 'https://example.com/auth/callback' ,
scopes: 'email profile'
}
})
// Sign in with GitHub
const { data , error } = await supabase . auth . signInWithOAuth ({
provider: 'github'
})
Phone Authentication
SMS-based authentication:
// Send OTP to phone number
const { data , error } = await supabase . auth . signInWithOtp ({
phone: '+1234567890'
})
// Verify the OTP
const { data , error } = await supabase . auth . verifyOtp ({
phone: '+1234567890' ,
token: '123456' ,
type: 'sms'
})
Anonymous Sign-In
Create temporary users without credentials:
const { data , error } = await supabase . auth . signInAnonymously ()
// Later, convert to permanent account
const { data , error } = await supabase . auth . updateUser ({
email: 'user@example.com' ,
password: 'secure-password'
})
User Management
User Object
The user object contains authentication data:
const { data : { user } } = await supabase . auth . getUser ()
console . log ( user )
// {
// id: 'uuid',
// email: 'user@example.com',
// user_metadata: { first_name: 'John', last_name: 'Doe' },
// app_metadata: { provider: 'email', ... },
// created_at: '2024-01-01T00:00:00Z',
// ...
// }
Store additional user information:
// Update user metadata
const { data , error } = await supabase . auth . updateUser ({
data: {
avatar_url: 'https://example.com/avatar.jpg' ,
theme: 'dark'
}
})
Profile Tables
Create a public profile table linked to auth.users:
create table public .profiles (
id uuid references auth . users (id) on delete cascade primary key ,
username text unique ,
avatar_url text ,
bio text ,
created_at timestamptz default now ()
);
alter table public . profiles enable row level security ;
-- Allow users to read all profiles
create policy "Profiles are viewable by everyone"
on profiles for select
using (true);
-- Allow users to update their own profile
create policy "Users can update own profile"
on profiles for update
using ( auth . uid () = id);
Create profiles automatically with a trigger:
create or replace function public .handle_new_user()
returns trigger
language plpgsql
security definer
as $$
begin
insert into public . profiles (id, username)
values ( new . id , new . raw_user_meta_data ->> 'username' );
return new;
end ;
$$;
create trigger on_auth_user_created
after insert on auth . users
for each row execute function public . handle_new_user ();
Session Management
Automatic Session Refresh
Supabase SDKs automatically refresh expired sessions:
// Sessions are automatically refreshed
const { data : { session } } = await supabase . auth . getSession ()
Manual Session Management
// Refresh session manually
const { data , error } = await supabase . auth . refreshSession ()
// Sign out (clears local session)
const { error } = await supabase . auth . signOut ()
// Sign out from all devices
const { error } = await supabase . auth . signOut ({ scope: 'global' })
Session Callbacks
Listen for auth state changes:
supabase . auth . onAuthStateChange (( event , session ) => {
console . log ( event , session )
// Events: SIGNED_IN, SIGNED_OUT, TOKEN_REFRESHED, USER_UPDATED, etc.
if ( event === 'SIGNED_IN' ) {
console . log ( 'User signed in:' , session . user )
}
if ( event === 'SIGNED_OUT' ) {
console . log ( 'User signed out' )
}
})
Multi-Factor Authentication (MFA)
Add an extra layer of security with TOTP-based MFA:
// Enroll a new factor
const { data , error } = await supabase . auth . mfa . enroll ({
factorType: 'totp'
})
// User scans QR code and enters verification code
const { data , error } = await supabase . auth . mfa . verify ({
factorId: data . id ,
challengeId: data . challenge_id ,
code: '123456'
})
// List enrolled factors
const { data , error } = await supabase . auth . mfa . listFactors ()
// Unenroll a factor
const { data , error } = await supabase . auth . mfa . unenroll ({
factorId: 'factor-id'
})
Server-Side Auth
Next.js (App Router)
import { createServerClient } from '@supabase/ssr'
import { cookies } from 'next/headers'
export async function createClient () {
const cookieStore = await cookies ()
return createServerClient (
process . env . NEXT_PUBLIC_SUPABASE_URL ! ,
process . env . NEXT_PUBLIC_SUPABASE_ANON_KEY ! ,
{
cookies: {
get ( name : string ) {
return cookieStore . get ( name )?. value
}
}
}
)
}
// Use in server components
const supabase = await createClient ()
const { data : { user } } = await supabase . auth . getUser ()
API Routes
// app/api/protected/route.ts
import { createClient } from '@/lib/supabase/server'
export async function GET () {
const supabase = await createClient ()
const { data : { user }, error } = await supabase . auth . getUser ()
if ( error || ! user ) {
return new Response ( 'Unauthorized' , { status: 401 })
}
return Response . json ({ user })
}
Authorization with RLS
Combine Auth with Row Level Security:
-- Only allow users to read their own data
create policy "Users can read own data"
on private_data for select
using ( auth . uid () = user_id);
-- Only allow authenticated users to insert
create policy "Authenticated users can insert"
on posts for insert
to authenticated
with check ( auth . uid () = author_id);
-- Only allow service role to delete
create policy "Service role can delete"
on posts for delete
to service_role
using (true);
Access user info in policies:
-- Access user email
auth . email ()
-- Access user role
auth . role ()
-- Access custom claims
auth . jwt () ->> 'custom_claim'
Auth Hooks
Customize authentication flows with hooks:
Before User Created : Modify user data before creation
Send Email : Customize email sending
Send SMS : Customize SMS sending
Password Verification : Custom password validation
Custom Access Token : Add custom claims to JWTs
MFA Verification : Custom MFA logic
Example custom access token hook:
// edge-functions/custom-access-token/index.ts
import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
serve ( async ( req ) => {
const { user } = await req . json ()
return new Response (
JSON . stringify ({
claims: {
role: user . email ?. endsWith ( '@admin.com' ) ? 'admin' : 'user' ,
subscription_tier: 'premium'
}
}),
{ headers: { 'Content-Type' : 'application/json' } }
)
})
Security Best Practices
Use RLS Always enforce authorization with Row Level Security policies.
Enable MFA Require multi-factor authentication for sensitive operations.
Validate Emails Enable email confirmation to verify user email addresses.
Rate Limiting Configure rate limits to prevent abuse and brute force attacks.
Next Steps
Social Auth Set up OAuth providers for social login
Server-Side Auth Implement authentication in server components
Auth Hooks Customize authentication flows with hooks
RLS Policies Secure your data with Row Level Security