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); } }
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));
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);
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 ... }
Top comments (2)
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:
I think a Custom Class decorator would be the solution for this.