How to Add Authentication to Your Supabase App
Supabase Auth provides email/password, OAuth, magic links, and phone auth out of the box. It integrates directly with Row Level Security so authenticated users automatically get scoped database access. This guide covers the complete auth setup.
Find security issues automatically before attackers do.
Follow These Steps
Configure auth providers in Supabase dashboard
Enable the authentication methods you want to offer.
// Supabase Dashboard > Authentication > Providers
// Enable:
// - Email (with Confirm email ON)
// - Google OAuth
// - GitHub OAuth
// Configure redirect URLs:
// Site URL: https://yourdomain.com
// Redirect URLs: https://yourdomain.com/auth/callbackInstall Supabase auth helpers
Add the framework-specific auth helpers.
npm install @supabase/supabase-js @supabase/ssrCreate the Supabase client with auth support
Set up client and server Supabase clients with proper cookie handling.
// lib/supabase/client.ts
import { createBrowserClient } from '@supabase/ssr'
export function createClient() {
return createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)
}
// lib/supabase/server.ts
import { createServerClient } from '@supabase/ssr'
import { cookies } from 'next/headers'
export async function createServerSupabase() {
const cookieStore = await cookies()
return createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{ cookies: { getAll() { return cookieStore.getAll() } } }
)
}Implement signup, login, and OAuth
Create authentication functions.
// Sign up with email
const { data, error } = await supabase.auth.signUp({
email: 'user@example.com',
password: 'securepassword'
})
// Sign in with email
const { data, error } = await supabase.auth.signInWithPassword({
email: 'user@example.com',
password: 'securepassword'
})
// Sign in with Google
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'google',
options: { redirectTo: 'https://yourdomain.com/auth/callback' }
})Create the auth callback route
Handle the OAuth callback to exchange the code for a session.
// app/auth/callback/route.ts
import { createServerSupabase } from '@/lib/supabase/server'
import { NextResponse } from 'next/server'
export async function GET(request: Request) {
const { searchParams, origin } = new URL(request.url)
const code = searchParams.get('code')
if (code) {
const supabase = await createServerSupabase()
const { error } = await supabase.auth.exchangeCodeForSession(code)
if (!error) {
return NextResponse.redirect(`${origin}/dashboard`)
}
}
return NextResponse.redirect(`${origin}/login?error=auth_failed`)
}Protect server-side routes
Check authentication in Server Components and API routes.
// app/dashboard/page.tsx
import { createServerSupabase } from '@/lib/supabase/server'
import { redirect } from 'next/navigation'
export default async function Dashboard() {
const supabase = await createServerSupabase()
const { data: { user } } = await supabase.auth.getUser()
if (!user) redirect('/login')
// RLS automatically scopes this query to the user
const { data: posts } = await supabase.from('posts').select('*')
return <PostList posts={posts} />
}Link auth to RLS policies
Write RLS policies that use auth.uid() to scope data access.
CREATE POLICY "Users access own data" ON "posts"
FOR ALL TO authenticated
USING ((select auth.uid()) = user_id);With RLS and auth properly configured, every database query automatically returns only the current user's data.
What You'll Achieve
Your Supabase app has email, OAuth, and magic link authentication with proper session handling, protected routes, and RLS integration. Users can only access their own data through the combination of auth and RLS.
Common Mistakes to Avoid
Mistake
Using getSession() instead of getUser() for auth verification
Fix
getSession() reads from cookies which can be tampered with. Always use getUser() for server-side auth verification as it validates the JWT with Supabase.
Mistake
Not creating the auth callback route
Fix
OAuth and magic link flows require a callback route to exchange the code for a session. Without it, auth flows will fail silently.
Mistake
Forgetting to add redirect URLs in Supabase dashboard
Fix
OAuth redirects will fail if the callback URL is not listed in Supabase dashboard > Authentication > URL Configuration.
Frequently Asked Questions
Does Supabase Auth work with RLS automatically?
Yes. When a user is authenticated, their JWT is sent with every request. RLS policies can reference auth.uid() to scope queries to the authenticated user automatically.
Should I use email/password or OAuth?
Offer both. OAuth is more convenient for users and avoids password management. Email/password is essential as a fallback and for users who prefer it.
How do I handle auth in Server Components vs Client Components?
Use createServerClient for Server Components (reads cookies from the request). Use createBrowserClient for Client Components (manages cookies in the browser).
Ready to Secure Your App?
VAS automatically scans your deployed app for the security issues covered in this guide. Get actionable results in minutes.
Start Security Scan