ABOUT ME

Today
Yesterday
Total
  • Nestjs로 구현하는 Authentication & Authorization(4)
    개발이야기 2021. 4. 11. 16:13

    이 포스트는 NestJS를 사용하여 로그인 API를 구현하는 방법을 정리한 글이다. NestJS 의 공식문서를 참고하였으며 passport, typeorm 을 사용한다. 아래와 같이 4개의 글로 나누어 작성하였으며 이 글에서는 네번째로 passport를 사용하여 권한처리를 하는 방법을 정리하였다.

     

    전체 코드는 github에 업로드 되어 있다.

    1. User Controller 수정

    권한처리를 위해 User Controller를 다음과 같이 수정한다.

      @Get()
      @Role("admin")
      @UseGuards(RolesGuard)
      @UseGuards(JwtAuthGuard)
      findAll(): Promise<User[]> {
        return this.userService.findAll();
      }

    권한처리를 적용할 함수 위에 권한처리를 위한 설정을 한다. 테스트를 위해 모든 사용자 정보를 반환하는 findAll 함수를 관리자 권한을 가진 사람만이 요청할 수 있도록 설정한다.

    2. 권한처리

    2.1 Role Decorator

    // roles.decorator.ts
    
    export const ROLES_KEY = 'roles';
    export const Role = (role: string) => SetMetadata(ROLES_KEY, role);

    decorator를 사용하여 입력받은 role을 메타데이터에 저장한다.

    2.2 Roles Guard

    // roles.guard.ts
    
    @Injectable()
    export class RolesGuard implements CanActivate {
      constructor(private reflector: Reflector) {}
    
      canActivate(context: ExecutionContext): boolean | Promise<boolean> | Observable<boolean> {
        const requiredRole = this.reflector.getAllAndOverride<string>(ROLES_KEY, [
          context.getHandler(),
          context.getClass(),
        ]);
        console.log(requiredRole);
        if (!requiredRole) {
          return true;
        }
    
        const { user } = context.switchToHttp().getRequest();
        console.log(user);
        return requiredRole === user.role;
      }
    }

    RolesGuard는 CanActivate를 구현하는 Guard class이다. 생성자에서 Reflrector를 먼저 선언한다. Reflector는 helper class로 reflrector를 사용하면 metadata의 정보를 읽어올 수 있다. Role("admin") 데코레이터를 사용하여 "admin"을 metadata에 이미 저장하였다. 이 값을 확인하여 user객체에 있는 권한과 일치하면 findAll 함수를 실행하고 일치하지 않으면 예외를 던진다.

     

    그렇다면 user객체는 어디에서 읽어오는가?

    2.3 JWT Auth Guard

    Nestjs에서 Guard는 역순으로 실행된다. 즉, 데코레이터를 사용하여 선언할 때 아래쪽에 선언된 Guard가 먼저 실행된다.

    GET http://localhost:3000/user/
    Authorization: "Bearer " + {accessTokenAdmin}

    따라서 위와 같은 요청이 들어오면 먼저 JwtAuthGuard에서 토큰을 검증한 후 토큰에 저장된 정보를 반환한다. 이는 JwtStrategy의 validate 함수에서 이루어진다. 반환된 정보는 request 객체 안에 user라는 이름으로 들어가고 이후 RolesGuard에서 user객체 안의 role값을 읽어서 권한을 확인한다.

    댓글

Designed by Tistory.