@Public()
Package: @nauth-toolkit/nestjs
Type: Method and Class Decorator
Decorator that marks a route or controller as public, allowing it to bypass the AuthGuard.
Import from NestJS Package
import { Public } from '@nauth-toolkit/nestjs';
Overview
The @Public() decorator sets metadata on a route to indicate it should skip authentication. It's particularly useful when using a global AuthGuard.
Key Features:
- Skip authentication for specific routes
- Works with global or controller-level guards
- Clean, declarative syntax
- No manual guard configuration needed
Usage
Basic Usage
import { Controller, Get, Post, Body, UseGuards } from '@nestjs/common';
import { AuthGuard, Public } from '@nauth-toolkit/nestjs';
@Controller('auth')
@UseGuards(AuthGuard) // Applied to all routes
export class AuthController {
@Public() // This route skips authentication
@Post('/login')
async login(@Body() dto: LoginDTO) {
return this.authService.login(dto);
}
@Public() // This route also skips authentication
@Post('/signup')
async signup(@Body() dto: SignupDTO) {
return this.authService.signup(dto);
}
@Get('/profile') // This route requires authentication
async getProfile(@CurrentUser() user: IUser) {
return { user };
}
}
With Global Guard
When using a global AuthGuard, mark public routes explicitly:
// app.module.ts
import { Module } from '@nestjs/common';
import { APP_GUARD } from '@nestjs/core';
import { AuthGuard } from '@nauth-toolkit/nestjs';
@Module({
providers: [
{
provide: APP_GUARD,
useClass: AuthGuard, // Applied globally
},
],
})
export class AppModule {}
// Controllers can now use @Public()
@Controller('api')
export class ApiController {
@Public()
@Get('/health')
getHealth() {
return { status: 'ok' };
}
@Get('/protected') // Requires auth (global guard)
getProtected(@CurrentUser() user: IUser) {
return { data: 'protected' };
}
}
Common Use Cases
Health Check Endpoints
import { Controller, Get } from '@nestjs/common';
import { Public } from '@nauth-toolkit/nestjs';
@Controller()
export class HealthController {
@Public()
@Get('/health')
checkHealth() {
return {
status: 'ok',
timestamp: new Date().toISOString(),
};
}
@Public()
@Get('/ping')
ping() {
return 'pong';
}
}
Authentication Endpoints
import { Controller, Post, Body } from '@nestjs/common';
import { Public } from '@nauth-toolkit/nestjs';
@Controller('auth')
export class AuthController {
constructor(private readonly authService: AuthService) {}
@Public()
@Post('/login')
login(@Body() dto: LoginDTO) {
return this.authService.login(dto);
}
@Public()
@Post('/signup')
signup(@Body() dto: SignupDTO) {
return this.authService.signup(dto);
}
@Public()
@Post('/forgot-password')
forgotPassword(@Body() dto: ForgotPasswordDTO) {
return this.authService.forgotPassword(dto);
}
@Public()
@Post('/reset-password')
resetPassword(@Body() dto: ResetPasswordDTO) {
return this.authService.resetPassword(dto);
}
// Not public - requires authentication
@Post('/change-password')
changePassword(
@CurrentUser() user: IUser,
@Body() dto: ChangePasswordDTO,
) {
return this.authService.changePassword(user.sub, dto);
}
}
Public API Endpoints
import { Controller, Get, Query } from '@nestjs/common';
import { Public } from '@nauth-toolkit/nestjs';
@Controller('blog')
export class BlogController {
@Public()
@Get('/posts')
getPublicPosts(@Query('page') page: number = 1) {
return this.blogService.getPublicPosts(page);
}
@Public()
@Get('/posts/:slug')
getPublicPost(@Param('slug') slug: string) {
return this.blogService.getPublicPost(slug);
}
// Not public - requires auth
@Post('/posts')
createPost(
@CurrentUser() user: IUser,
@Body() dto: CreatePostDTO,
) {
return this.blogService.createPost(user.sub, dto);
}
}
Documentation Endpoints
import { Controller, Get, Res } from '@nestjs/common';
import { Public } from '@nauth-toolkit/nestjs';
import { Response } from 'express';
@Controller('docs')
export class DocsController {
@Public()
@Get()
serveDocs(@Res() res: Response) {
return res.sendFile('docs/index.html');
}
@Public()
@Get('/api-spec')
getApiSpec() {
return {
openapi: '3.0.0',
info: { title: 'API', version: '1.0.0' },
// ... OpenAPI spec
};
}
}
Mixed Authentication
Support optional authentication (public but user-aware):
import { Controller, Get } from '@nestjs/common';
import { Public, CurrentUser } from '@nauth-toolkit/nestjs';
import type { IUser } from '@nauth-toolkit/nestjs';
@Controller('posts')
export class PostsController {
@Public()
@Get()
getPosts(@CurrentUser() user?: IUser) {
if (user) {
// Authenticated - show personalized content
return this.postsService.getPersonalized(user.sub);
} else {
// Anonymous - show public content
return this.postsService.getPublic();
}
}
}
Implementation Details
The decorator uses NestJS metadata:
import { SetMetadata } from '@nestjs/common';
export const IS_PUBLIC_KEY = 'isPublic';
export const Public = () => SetMetadata(IS_PUBLIC_KEY, true);
The AuthGuard checks for this metadata:
// In AuthGuard
const isPublic = this.reflector.getAllAndOverride<boolean>(
IS_PUBLIC_KEY,
[context.getHandler(), context.getClass()]
);
if (isPublic) {
return true; // Skip authentication
}
Testing
Public routes don't need authentication mocking:
import { Test, TestingModule } from '@nestjs/testing';
describe('HealthController', () => {
let controller: HealthController;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [HealthController],
}).compile();
controller = module.get<HealthController>(HealthController);
});
it('should return health status', () => {
const result = controller.checkHealth();
expect(result.status).toBe('ok');
});
});
Best Practices
- Use for auth endpoints (login, signup, password reset)
- Use for health checks and monitoring endpoints
- Use for public content (blog posts, documentation)
- Don't overuse - most routes should require auth
- Document public routes clearly in your API docs
- Consider rate limiting for public endpoints
- Use with global guard for cleaner code
Security Considerations
- Validate input even on public routes
- Rate limit public endpoints to prevent abuse
- CSRF protection still applies (if using cookies)
- Don't expose sensitive data on public routes
- Monitor usage of public endpoints
Related APIs
- AuthGuard - Respects
@Public()metadata @CurrentUser()Decorator - Extract user (optional with@Public())- AuthGuard - Setting up global authentication
See Also
- NestJS Metadata - Official documentation
- AuthGuard - Complete route protection guide
- Configuration - Authentication configuration