Next.js + Supabase + Vercel Security Blueprint

Share

To secure a Next.js + Supabase + Vercel stack, you need to: (1) use the correct Supabase client for each context (browser vs server vs middleware), (2) enable RLS on all tables and verify auth in Server Actions using getUser(), (3) protect routes with middleware, (4) configure environment variables in Vercel with proper NEXT_PUBLIC_ prefixes, and (5) never expose the service_role key to clients. This blueprint covers Next.js App Router patterns with Supabase SSR.

TL;DR

This popular stack requires understanding Next.js App Router's different contexts and Supabase's RLS. Key security tasks: use correct Supabase client for each context (browser, server, middleware), enable RLS on all tables, verify auth in Server Actions with getUser(), configure Vercel environment variables properly, and never expose the service_role key to clients.

Supabase Client Configuration Supabase Next.js

lib/supabase/server.ts
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: {
        getAll() { return cookieStore.getAll() },
        setAll(cookiesToSet) {
          try {
            cookiesToSet.forEach(({ name, value, options }) =>
              cookieStore.set(name, value, options)
            )
          } catch { /* Server Component */ }
        },
      },
    }
  )
}

Server Action Security Next.js

Always verify auth in Server Actions
'use server'

import { createClient } from '@/lib/supabase/server'

export async function updateProfile(formData: FormData) {
  const supabase = await createClient()
  const { data: { user }, error } = await supabase.auth.getUser()

  if (error || !user) {
    throw new Error('Unauthorized')
  }

  await supabase.from('profiles').update({
    name: formData.get('name')
  }).eq('id', user.id)  // Use verified user ID
}

Security Checklist

Pre-Launch Checklist

RLS enabled on all tables

Correct Supabase client per context

Auth verified in all Server Actions

Middleware protects routes

Environment variables in Vercel

Service role key server-side only

Alternative Stacks

Consider these related blueprints:

Building with this stack?

Scan for RLS and auth issues.

Start Free Scan
Security Blueprints

Next.js + Supabase + Vercel Security Blueprint