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.