Nuxt + Supabase Security Blueprint

Share

To secure a Nuxt + Supabase stack, you need to: (1) configure @nuxtjs/supabase module with proper redirect options, (2) use serverSupabaseClient and serverSupabaseUser in server routes, (3) enable RLS on all tables as defense-in-depth, (4) keep the service key server-side only in runtimeConfig, and (5) verify auth in all server API routes. This blueprint covers Nuxt 3 server routes with Supabase integration.

TL;DR

Nuxt with @nuxtjs/supabase provides great DX but requires understanding server vs client contexts. Key tasks: use serverSupabaseClient in API routes, enable RLS on all tables, protect server routes with middleware, and use useSupabaseUser() for reactive auth state on the client.

Module Configuration Nuxt

nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@nuxtjs/supabase'],

  supabase: {
    redirectOptions: {
      login: '/login',
      callback: '/confirm',
      exclude: ['/', '/about', '/blog/*'],
    },
  },

  runtimeConfig: {
    // Server-only
    supabaseServiceKey: process.env.SUPABASE_SERVICE_KEY,
    public: {
      supabaseUrl: process.env.SUPABASE_URL,
      supabaseKey: process.env.SUPABASE_ANON_KEY,
    },
  },
})

Server API Routes Nuxt Supabase

server/api/posts.post.ts
export default defineEventHandler(async (event) => {
  const client = await serverSupabaseClient(event)
  const user = await serverSupabaseUser(event)

  if (!user) {
    throw createError({ statusCode: 401, message: 'Unauthorized' })
  }

  const body = await readBody(event)

  const { data, error } = await client.from('posts').insert({
    title: body.title,
    author_id: user.id,  // Use verified user ID
  }).select().single()

  if (error) throw createError({ statusCode: 400, message: error.message })

  return data
})

Route Middleware Nuxt

middleware/auth.ts
export default defineNuxtRouteMiddleware((to) => {
  const user = useSupabaseUser()

  if (!user.value) {
    return navigateTo('/login')
  }
})

Client middleware is UX only. Always verify auth server-side in API routes. RLS provides the actual security layer for database access.

Security Checklist

Pre-Launch Checklist

RLS enabled on all tables

Auth verified in all server routes

serverSupabaseClient used server-side

Service key never exposed to client

Environment variables configured

Alternative Stacks

Consider these related blueprints:

Building with this stack?

Scan for RLS and auth issues.

Start Free Scan
Security Blueprints

Nuxt + Supabase Security Blueprint