@madebylars.com/mbl-auth
v1.0.2
Published
Nuxt 4 auth module powered by Supabase — session management, role-based access control, and admin user management
Downloads
153
Readme
mbl-auth
A Nuxt 4 auth module powered by Supabase. Handles authentication, session management, role-based access control, and admin user management out of the box.
Features
- Cookie-based SSR sessions via
@supabase/ssr - Auto-imported composables:
useSupabaseClient,useSupabaseUser,useSupabaseSession,useSupabaseUserRole - Route middleware:
auth(authenticated users only) andadmin(admin role only) - OAuth and magic-link callback handling
- Built-in admin API for user management (list, assign roles, delete)
- Service role key kept strictly server-side
Quick Setup
Install the module and its peer dependencies:
npm install mbl-auth @supabase/supabase-js @supabase/ssrAdd it to your nuxt.config.ts:
export default defineNuxtConfig({
modules: ['mbl-auth'],
mblAuth: {
supabaseUrl: process.env.SUPABASE_URL,
supabaseKey: process.env.SUPABASE_ANON_KEY,
supabaseServiceKey: process.env.SUPABASE_SERVICE_KEY, // server-only
roles: ['admin', 'user'],
defaultRole: 'user',
redirect: {
login: '/login',
callback: '/confirm',
forbidden: '/forbidden',
},
},
})Get your keys from your Supabase project under Settings → API.
Composables
All composables are auto-imported.
useSupabaseClient()
Returns the typed Supabase client for auth operations and database queries.
const client = useSupabaseClient()
await client.auth.signInWithPassword({ email, password })
await client.auth.signOut()
await client.auth.signInWithOAuth({ provider: 'github' })useSupabaseUser()
Reactive ref to the current user. null when signed out.
const user = useSupabaseUser()
// user.value?.emailuseSupabaseSession()
Reactive ref to the current session, including the access token.
const session = useSupabaseSession()
// session.value?.access_tokenuseSupabaseUserRole()
Returns the current user's role and a helper to check it.
const { role, hasRole } = useSupabaseUserRole()
// role.value === 'admin'
// hasRole('admin', 'editor')Route Middleware
auth
Redirects unauthenticated users to redirect.login.
// pages/dashboard.vue
definePageMeta({ middleware: 'auth' })admin
Redirects unauthenticated users to redirect.login and non-admins to redirect.forbidden.
// pages/admin/users.vue
definePageMeta({ middleware: 'admin' })Admin User Management
The module exposes server API routes for managing users. All routes require an active admin session — a 403 is returned otherwise.
| Method | Route | Body | Description |
|--------|-------|------|-------------|
| GET | /api/admin/users | — | List all users with their roles |
| PATCH | /api/admin/users/:id | { role: string } | Update a user's role |
| DELETE | /api/admin/users/:id | — | Delete a user |
Roles are stored in Supabase app_metadata (server-side only, not user-editable). To promote a user to admin, call the PATCH endpoint from your admin UI:
await $fetch(`/api/admin/users/${userId}`, {
method: 'PATCH',
body: { role: 'admin' },
})useSupabaseAdminClient() (server-side)
Available in Nitro API routes and server middleware. Uses the service role key to bypass row-level security.
// server/api/something.ts
export default defineEventHandler(async (event) => {
const admin = useSupabaseAdminClient()
// full admin access to Supabase
})requireAdminRole(event) (server-side)
Throws 401/403 if the request is not from an authenticated admin. Use it to protect your own custom server routes.
export default defineEventHandler(async (event) => {
await requireAdminRole(event)
// safe to continue
})Module Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| supabaseUrl | string | '' | Your Supabase project URL |
| supabaseKey | string | '' | Supabase anon/public key |
| supabaseServiceKey | string | '' | Supabase service role key (server-only) |
| roles | string[] | ['admin', 'user'] | Valid role names |
| defaultRole | string | 'user' | Role assigned to new users |
| redirect.login | string | '/login' | Redirect target for unauthenticated users |
| redirect.callback | string | '/confirm' | OAuth / magic-link callback path |
| redirect.forbidden | string | '/forbidden' | Redirect target for insufficient role |
All options can be overridden at runtime via environment variables using Nuxt's standard runtimeConfig convention.
Contribution
# Install dependencies
npm install
# Generate type stubs
npm run dev:prepare
# Develop with the playground
npm run dev
# Build the playground
npm run dev:build
# Run ESLint
npm run lint
# Run Vitest
npm run test
npm run test:watch
# Release new version
npm run release