user1688181
user1688181

Reputation: 492

NestJS RolesGuard not working as expected

I have implemented RoleGuard as follows with the help of official nestJS documentation:

@Injectable()
export class RolesGuard implements CanActivate {
  constructor(private readonly reflector: Reflector) {}

  canActivate(context: ExecutionContext): boolean {
    const roles = this.reflector.get<string[]>('roles', context.getHandler());
    if (!roles) {
      return true;
    }
    const request = context.switchToHttp().getRequest();
    const user = request.user;
    //console.log(request)
    const hasRole = () => user.role.some((role) => roles.includes(role));
    return user && user.roles && hasRole();
  }
}

and applied as follows:

@Get('get/all')
@UseGuards(AuthGuard('jwt'), RolesGuard)
@Roles('user')
async findAll(): Promise<Service[]> {
    return this.serviceServce.findAll()
}

This is my auth strategy:

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor() {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: false,
      secretOrKey: jwtConstants.secret,
    });
  }

  async validate(payload: any) {
    console.log(JSON.stringify(payload));
    return { userId: payload.sub, username: payload.username };
  }
}

And this is my auth service:

async login(user: any) {
    const payload = { email: user.email, sub: user.Id };
    return {
      access_token: this.jwtService.sign(payload),
    };
}

but it always returns:

{
    "statusCode": 403,
    "error": "Forbidden",
    "message": "Forbidden resource"
}

I debug for the request and the user is empty (request.user) in the documentation it says:

In the node.js world, it's common practice to attach the authorized user to the request object. Thus, in our sample code above, we are assuming that request.user contains the user instance and allowed roles.

I don't understand this part. How do I do that?

Upvotes: 1

Views: 5564

Answers (2)

Hao
Hao

Reputation: 6609

RolesGuard must be at the controller level. Docs is not very clear about it.

Once you move RolesGuard to controller of that handler which uses @Roles, you should be fine.

Upvotes: 1

kamilg
kamilg

Reputation: 753

Your AuthGuard should attach the user to the request. Missing user makes the RoleGuard fail and the very first condition in the return statement, thus not allowing to access. Can you show you auth implementation and how you attach the user to the request? (sorry for linking to my own comment but just prepared the code doing the very same with Nest & passport, you may find it useful)

Upvotes: 0

Related Questions