DEV Community

Danny Pule
Danny Pule

Posted on • Edited on

Exclude a route from Nest.js AuthGaurd (make any route publicly available)

Create a custom class called AuthGuard that extends from the AuthGaurd class exported by @nestjs/passport. Notice the inclusion of isPublic which allows you to add a decorator to routes that you want to be publicly accessible.

 

// auth.gaurd.ts import { ExecutionContext, Injectable } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; import { AuthGuard as PassportAuthGaurd } from '@nestjs/passport'; @Injectable() export class AuthGuard extends PassportAuthGaurd('jwt') { constructor(private readonly reflector: Reflector) { super(); } canActivate(context: ExecutionContext) { const isPublic = this.reflector.get<boolean>( 'isPublic', context.getHandler() ); if (isPublic) { return true; } return super.canActivate(context); } } 
Enter fullscreen mode Exit fullscreen mode

 

Use this gaurd as a global gaurd in main.ts or wherever you bootstrap your application. This will lockdown all routes and make them accessible by authenticated users only.

 

// main.ts const reflector = app.get(Reflector); app.useGlobalGuards(new AuthGuard(reflector)); 
Enter fullscreen mode Exit fullscreen mode

 

Create a decorator called Public which will allow you make any route public.

 

// public.decorator.ts import { SetMetadata } from '@nestjs/common'; export const Public = () => SetMetadata('isPublic', true); 
Enter fullscreen mode Exit fullscreen mode

 

Finally add the @Public() decorator to any routes that need to be publicly accessible by unauthenticated users.

 

// auth.controller.ts @Post('/signup') @Public() async signUp( @Body(ValidationPipe) signUpDto: SignUpDto ): Promise<{ accessToken: string; user: User }> { // code ... } @Post('/signin') @Public() signIn( @Body(ValidationPipe) authCredentialsDto: AuthCredentialsDto ): Promise<{ accessToken: string; user: User }> { // code ... } 
Enter fullscreen mode Exit fullscreen mode

Top comments (2)

Collapse
 
joe_p_7e01c699c0082b0f99d profile image
Joe P

This seems to only work on the route level. Is there a way to make this work on a controller level?

This does not work:

@Public() @Controller() export class AppController { @Get('ping') respondToPing() { return 'pong'; } } 
Enter fullscreen mode Exit fullscreen mode
Collapse
 
fsassiv profile image
FLAVIO SANTOS DE ANDRADE • Edited

I think a Custom Class decorator would be the solution for this.

1. Define the Decorator First, create a new file for your custom decorator. Let's call it custom-class.decorator.ts. typescript import { SetMetadata } from '@nestjs/common'; export const CustomClass = (value: string): ClassDecorator => { return SetMetadata('customClassKey', value); }; Here, SetMetadata is used to attach metadata to the class. 2. Apply the Custom Decorator Apply this decorator to any class where you want to use it. typescript import { CustomClass } from './custom-class.decorator'; @CustomClass('myCustomValue') export class ExampleService { // Your class logic here } 3. Access the Metadata To access this metadata, use the Reflector service in a guard, interceptor, or another provider. typescript import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; @Injectable() export class CustomGuard implements CanActivate { constructor(private reflector: Reflector) {} canActivate(context: ExecutionContext): boolean { const customValue = this.reflector.get<string>( 'customClassKey', context.getClass(), ); if (!customValue) { return true; } // Add your custom logic here console.log(`Custom value from decorator: ${customValue}`); return true; } } 4. Register the Guard Finally, apply the guard either globally, at the module level, or at the route level. typescript import { Module } from '@nestjs/common'; import { APP_GUARD } from '@nestjs/core'; import { ExampleService } from './example.service'; import { CustomGuard } from './custom.guard'; @Module({ providers: [ ExampleService, { provide: APP_GUARD, useClass: CustomGuard, }, ], }) export class AppModule 
Enter fullscreen mode Exit fullscreen mode