200.Land

nest-api-gateway-roles.ts

The TypeScript code sets up a role-based access control in a NestJS application using a custom guard. It defines a RolesGuard class that leverages metadata reflection to determine the necessary roles for accessing particular routes. It retrieves the user roles from the AWS API Gateway request context, specified in the headers, and checks if the user has at least one of the roles required to access a route, thus facilitating role-based authorization.

import { Injectable, CanActivate, ExecutionContext } from "@nestjs/common";
import { SetMetadata } from "@nestjs/common";
import { Reflector } from "@nestjs/core";

export enum Role {
  User = "user",
  Admin = "admin",
}

export const Roles = (...roles: Role[]) => SetMetadata("roles", roles);

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

  canActivate(context: ExecutionContext): boolean {
    const requiredRoles = this.reflector.getAllAndOverride<Role[]>("roles", [context.getHandler(), context.getClass()]);
    if (!requiredRoles) {
      return true;
    }
    const headers = context.switchToHttp().getRequest().headers;
    const apigatewayEvent = headers["x-apigateway-event"];
    const user = JSON.parse(decodeURIComponent(apigatewayEvent))?.requestContext?.authorizer?.claims;
    return requiredRoles.some(role => user["cognito:groups"]?.includes(role));
  }
}