nestjs-jwt-guard
v1.0.1
Published
Bearer-JWT authentication for NestJS, built on @nestjs/jwt — a configurable guard, @Public(), and a token-issuance helper.
Downloads
220
Maintainers
Readme
nestjs-jwt-guard
Bearer-token authentication for NestJS, built on the official @nestjs/jwt: a configurable guard, @Public(), and a token-issuance helper — wired with a single forRoot().
🔆 ESM-only. Requires Node ≥ 20 and NestJS 10 / 11 / 12.
This is the bearer-token half (verify + issue). For username/password login (user lookup + password hashing), pair it with the token-agnostic credentials companion (
nestjs-credentials).
Install
npm install nestjs-jwt-guard @nestjs/jwt@nestjs/common, @nestjs/core, and reflect-metadata are peer dependencies (already in any Nest app).
Quick start
Register once — it configures @nestjs/jwt and registers the guard globally:
import { Module } from '@nestjs/common';
import { JwtAuthModule } from 'nestjs-jwt-guard';
@Module({
imports: [
JwtAuthModule.forRoot({
jwt: { secret: process.env.JWT_SECRET, signOptions: { expiresIn: '15m' } },
}),
],
})
export class AppModule {}Every route now requires a valid Authorization: Bearer <token>. Mark exceptions with @Public():
import { Public } from 'nestjs-jwt-guard';
@Public()
@Post('login')
login() { /* … */ }Issue tokens with the injectable helper:
import { JwtAuthService } from 'nestjs-jwt-guard';
constructor(private readonly auth: JwtAuthService) {}
async login(user: User) {
return { accessToken: await this.auth.sign({ sub: user.id, role: user.role }) };
}Read the principal — the decoded payload is attached to req.user (configurable):
@Get('me')
me(@Req() req: AuthenticatedRequest) {
return req.user; // { sub, role, … }
}DB-driven config (forRootAsync)
JwtAuthModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (config: ConfigService) => ({
secret: config.getOrThrow('JWT_SECRET'),
signOptions: { expiresIn: '15m' },
}),
});Configuration
JwtAuthModule.forRoot({
jwt: { /* @nestjs/jwt config — secret/keys, signOptions, … */ },
getToken: (req) => req.headers.authorization?.slice(7), // default: Bearer header
validate: (payload, req) => payload, // map/validate → req.user; null ⇒ 401
attachTo: 'user', // request property (default)
verifyOptions: { audience: 'api' }, // forwarded to verifyAsync
registerGuard: true, // register globally via APP_GUARD
isGlobal: true, // module is global
});| Option | Default | Description |
| --- | --- | --- |
| jwt | — | @nestjs/jwt config, passed to JwtModule.register (required) |
| getToken | Bearer header | Extract the raw token from the request |
| validate | identity | Map/validate the decoded payload into the principal; return null/undefined ⇒ 401, or throw your own error |
| attachTo | 'user' | Request property the principal is attached to |
| verifyOptions | — | Extra options forwarded to JwtService.verifyAsync |
| registerGuard | true | Register the guard globally via APP_GUARD |
| isGlobal | true | Register the module globally |
validate runs outside the verify try/catch, so a custom validator can throw its own (non-401) error and have it propagate untouched.
Per-route use
Disable the global guard (registerGuard: false) and apply per-controller instead — the guard and JwtService are exported:
@UseGuards(JwtAuthGuard)
@Controller('admin')
export class AdminController {}API
Module
| Export | Description |
| --- | --- |
| JwtAuthModule.forRoot(options) | Configure @nestjs/jwt (via jwt) + the guard synchronously. See Configuration. |
| JwtAuthModule.forRootAsync(options) | Build the @nestjs/jwt config from injected deps (useFactory). |
Enforcement & issuance
| Export | Description |
| --- | --- |
| JwtAuthGuard | The bearer-token guard. Registered globally by default; exported for per-route @UseGuards. |
| JwtAuthService | sign(payload, options?) — issue a token via the configured JwtService. |
| @Public() | Marks a route/controller as exempt from the guard. |
| IS_PUBLIC_KEY | The metadata key @Public() sets (for custom reflection). |
Advanced & types
| Export | Description |
| --- | --- |
| JWT_AUTH_OPTIONS | DI token holding the resolved guard behavior. |
| resolveGuardOptions(behavior?) | Merge behavior over the defaults → ResolvedGuardOptions. |
| defaultGetToken, defaultValidate | The default Bearer-header extractor and identity validator. |
| JwtAuthOptions, JwtAuthAsyncOptions, JwtAuthGuardBehavior, ResolvedGuardOptions | Option types. |
| TokenExtractor, PayloadValidator, JwtPayload, AuthenticatedRequest | Supporting types. |
Related Projects
- nestjs-credentials — Token-agnostic username/password verification — a
UserStoreseam + pluggablePasswordHasher. Verify there, mint the JWT here. - nestjs-oauth2-password — The stateful OAuth2 ROPC alternative: opaque, server-stored, revocable access + refresh tokens with an RFC 6749 token endpoint.
- nestjs-accesscontrol — The official NestJS integration for AccessControl v3: RBAC + ABAC with fluent CRUD decorators and attribute filtering.
- nestjs-http-envelope — A uniform, configurable response & error envelope for NestJS.
- nestjs-configuard — The NestJS integration for configuard: DB-backed, typed, ABAC-filtered runtime config.
- accesscontrol — Role & attribute-based access control (RBAC + ABAC) for Node.js.
- configuard — Turn flat config rows from a database table into a nested, typed configuration object.
License
MIT © Onur Yıldırım
