Install & Compatibility
Where this runs
tested against v? · npm install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslnode 18–226 runs
build_error
glibcnode 18–226 runs
build_error
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
SupabaseAuthStrategy
✓ import { SupabaseAuthStrategy } from 'nestjs-supabase-auth';
✗ const SupabaseAuthStrategy = require('nestjs-supabase-auth');
This is the primary class to extend for your custom Supabase Passport strategy. NestJS applications are predominantly ESM/TypeScript-first.
PassportStrategy
✓ import { PassportStrategy } from '@nestjs/passport';
✗ import { Strategy } from '@nestjs/passport';
`PassportStrategy` is a factory function provided by `@nestjs/passport` used to create a NestJS-compatible Passport strategy from a base strategy (like `SupabaseAuthStrategy`).
ExtractJwt
✓ import { ExtractJwt } from 'passport-jwt';
✗ import * as ExtractJwt from 'passport-jwt';
`ExtractJwt` provides helper methods to extract the JWT from the request, commonly `fromAuthHeaderAsBearerToken()`.
AuthGuard
✓ import { AuthGuard } from '@nestjs/passport';
✗ import { AuthGuard } from '@nestjs/common';
`AuthGuard` is imported from `@nestjs/passport` to create route-level guards that apply the defined Passport strategy.
This quickstart demonstrates how to define and register a custom Supabase Passport strategy, apply it to a NestJS route using a guard, and access the validated user payload from the request. It includes environment variable placeholders for setup.
import { Injectable, Module } from '@nestjs/common';
import { PassportStrategy, AuthGuard } from '@nestjs/passport';
import { ExtractJwt } from 'passport-jwt';
import { SupabaseAuthStrategy } from 'nestjs-supabase-auth';
import { PassportModule } from '@nestjs/passport';
import { Controller, Get, UseGuards, Request } from '@nestjs/common';
// --- Strategy Definition (supabase.strategy.ts) ---
@Injectable()
export class SupabaseJwtStrategy extends PassportStrategy(
SupabaseAuthStrategy,
'supabase',
) {
public constructor() {
super({
supabaseUrl: process.env.SUPABASE_URL ?? 'https://your-project-ref.supabase.co',
supabaseKey: process.env.SUPABASE_KEY ?? 'YOUR_SUPABASE_ANON_KEY',
supabaseOptions: {},
supabaseJwtSecret: process.env.SUPABASE_JWT_SECRET ?? 'YOUR_SUPABASE_JWT_SECRET',
extractor: ExtractJwt.fromAuthHeaderAsBearerToken(),
});
}
async validate(payload: any): Promise<any> {
// This method is called after JWT verification. 'payload' contains the decoded JWT.
// You can perform additional user validation or data fetching here.
// Ensure the `sub` claim (user ID) is present.
if (!payload || !payload.sub) {
throw new Error('Invalid JWT payload: Missing user ID.');
}
// IMPORTANT: Call super.validate(payload) if you need the base strategy's validation logic
// or omit it if you fully override the validation.
// super.validate(payload); // Base validation might be empty or specific to the original strategy.
// Return the validated user payload. NestJS will attach this to req.user.
return { userId: payload.sub, email: payload.email, ...payload };
}
authenticate(req: Request) {
// This method can be overridden for custom authentication logic before validation.
// In most cases, the default Passport.js flow is sufficient.
super.authenticate(req);
}
}
// --- Auth Module (auth.module.ts) ---
@Module({
imports: [PassportModule],
providers: [SupabaseJwtStrategy],
exports: [SupabaseJwtStrategy, PassportModule], // Export PassportModule if other modules need it
})
export class AuthModule {}
// --- Protected Controller (user.controller.ts) ---
const SUPABASE_AUTH_GUARD = 'supabase'; // Define the guard name consistently
@Controller('user')
export class UserController {
@UseGuards(AuthGuard(SUPABASE_AUTH_GUARD))
@Get('profile')
getProfile(@Request() req) {
// req.user will contain the object returned by the validate method
return req.user;
}
}
// --- Main Application (main.ts or app.module.ts, simplified for quickstart) ---
// This setup assumes AuthModule is imported into AppModule.
// You would also need to configure your NestJS application to load environment variables.
// Example App Module might look like:
// @Module({
// imports: [AuthModule],
// controllers: [UserController],
// })
// export class AppModule {}
// To run this, you'd typically have a NestJS app initialized with `nest new`,
// then add these files and configure environment variables:
// SUPABASE_URL=https://<your-project-ref>.supabase.co
// SUPABASE_KEY=<your-anon-public-key>
// SUPABASE_JWT_SECRET=<your-jwt-secret-from-supabase-settings>
Errors
Common errors & fixes
Error: Cannot find module 'passport-jwt' or '@nestjs/passport'
Required peer dependencies for `nestjs-supabase-auth` are not installed.
fixRun `npm install passport passport-jwt @nestjs/passport @types/passport-jwt --save-dev` to install all necessary peer dependencies.
401 Unauthorized: Invalid Token or jwt malformed
The JWT provided in the 'Authorization: Bearer <token>' header is either missing, malformed, expired, or signed with a different secret than `supabaseJwtSecret` configured in the strategy.
fixEnsure the client is sending a valid, unexpired Supabase access token. Double-check that `supabaseJwtSecret` in your `SupabaseJwtStrategy` exactly matches the 'JWT Secret' found in your Supabase project's API Settings.
TypeError: Cannot read properties of undefined (reading 'user')
The `req.user` object is undefined, typically because the Passport strategy's `validate` method did not return a user object or the authentication guard was not correctly applied.
fixVerify that your `SupabaseJwtStrategy`'s `validate` method explicitly returns an object (e.g., `{ userId: payload.sub, ... }`). Also, ensure `@UseGuards(AuthGuard('supabase'))` is correctly applied to your controller methods or resolvers. Nest can't resolve dependencies of the SupabaseJwtStrategy (?). Please make sure that the argument at index [0] is available in the AuthModule context.
This usually indicates that `PassportModule` is not imported into your `AuthModule`, or `@Injectable()` is missing on your strategy.
fixEnsure `PassportModule` is imported into your `AuthModule`'s `imports` array (`imports: [PassportModule]`). Also, confirm `SupabaseJwtStrategy` has the `@Injectable()` decorator.
Audit
Dependencies
passportrequiredCore Passport.js library, required for authentication middleware.
passport-jwtrequiredPassport strategy for authenticating with a JSON Web Token, which Supabase uses.
@nestjs/passportrequiredNestJS integration for Passport.js, providing utilities like `PassportStrategy`.
@types/passport-jwtoptionalTypeScript type definitions for `passport-jwt`.