Authenticate Supabase users in your Fastify app using their JWT access tokens — without repeating boilerplate logic.
Note: Supabase does not currently support JWKS-based (public key) verification. This plugin only supports static secret-based verification via
SUPABASE_JWT_SECRET.
- Verifies Supabase JWT tokens with a shared secret
- Attaches decoded JWT payload to
request.user - Optional
onVerifycallback to transform or validate token - Supports custom token extractors
- Type-safe and lightweight
- Decorator-based — use
app.authenticateon any route or scope
- Yayinliyor - A new book writing & reading platform from Turkiye.
Manually authenticating Supabase JWTs in Fastify means repeating the same logic across routes: header parsing, verification, error handling, and payload attachment.
This plugin simplifies all of that into a reusable decorator — making your codebase safer, DRYer, and easier to maintain.
npm install fastifyjs-supabase-auth
# or
yarn add fastifyjs-supabase-authimport Fastify from 'fastify';
import fastifySupabaseAuth from 'fastifyjs-supabase-auth';
const app = Fastify();
// Register the plugin globally
app.register(fastifySupabaseAuth, {
supabaseJwtSecret: process.env.SUPABASE_JWT_SECRET!,
});
// Protected route — uses app.authenticate as onRequest hook
app.get('/me', {
onRequest: [app.authenticate],
}, async (req, reply) => {
return { user: req.user };
});
// Public route — no hook, no auth
app.get('/health', async (req, reply) => {
return { status: 'ok' };
});import Fastify from 'fastify';
import fastifySupabaseAuth from 'fastifyjs-supabase-auth';
const app = Fastify();
// Register the plugin globally
app.register(fastifySupabaseAuth, {
supabaseJwtSecret: process.env.SUPABASE_JWT_SECRET!,
});
// All routes in this scope are protected
app.register(async (scoped) => {
scoped.addHook('onRequest', scoped.authenticate);
scoped.get('/profile', async (req, reply) => {
return { user: req.user };
});
scoped.put('/profile', async (req, reply) => {
return { message: 'Profile updated' };
});
}, { prefix: '/api' });
// Public routes
app.get('/health', async (req, reply) => {
return { status: 'ok' };
});See examples/example.ts for a full working demo.
| Name | Type | Default | Description |
|---|---|---|---|
supabaseJwtSecret |
string |
— | Required. Supabase JWT secret |
extractor |
(req) => string | null |
Bearer header | Optional. Function to extract JWT from request |
unauthorizedResponse |
boolean |
true |
Optional. Responds with 401 if token is missing/invalid |
onVerify |
(decoded) => Promise<any> |
— | Optional. Called with decoded payload before assignment |
MIT