NestJS 12 | Role-Based Authorization

임종성·2021년 9월 20일
1

NestJS

목록 보기
12/13
post-thumbnail

지금까지 API에 대한 Access Control은 JWT를 활용하여 사용자의 로그인 여부를 확인하는 것이었습니다. 그러나 보통 WebSite는 사용자에게 모든 API에 대한 권한을 부여하지 않고, User의 Type(관리자 혹은 방문자 등), 즉 Role에 대해 선택적으로 권한을 부여합니다. 이번엔 사용자의 Role에 따라 Access를 허용하는 Guard를 작성하고 Custom Decorator까지 만들어보도록 하겠습니다.

Role-Based Access Control

Authorization은 사용자가 수행할 수 있는 작업을 결정하는 Process를 나타냅니다. 예를 들어, Admin User는 게시물을 작성, 수정, 삭제할 수 있지만 Admin이 아닌 일반 사용자는 게시물의 조회만 가능합니다.

Authorization은 Authentication(인증)과 독립적이지만, 인증 메커니즘이 필요합니다. Authorization을 처리하기 위해 다양한 접근 방식과 전략이 존재하지만, NestJS에서 제공하는 Guard를 활용하여 기본적인 역할 기반 엑세스 제어(Role-Based Access Control) 메커니즘을 구현해보도록 하겠습니다.

Add Role to User

RBAC Mechanism을 구현하기 위해서 먼저 사용자의 역할을 정의해줘야 합니다. 본 Project는 제품의 공급망 관리(Supply Chain Management) 시스템을 구축하는 것입니다. 따라서 이 시스템을 사용하는 User는 전체 System을 관리하는 Genuio 와 제품의 공급을 책임지고 조회하는 Manufacturer로 구분됩니다.

userType column을 생성하여 사용자의 역할을 추가합니다. 굳이 Enum은 사용하지 않고, commentgenuiomanufacturer로 Type을 지정한다는 코멘트를 남깁니다.

Role Decorator

이제 @Role Decorator를 작성하여 route Handler에 Custom Metadate를 붙이고, 특정 Route에 Access하기 위한 Role을 지정할 수 있게 해줍니다.AllowedRole Type을 정의하고, SetMetadata를 통해 roles라는 metadata를 사용할 수 있는 기능을 제공합니다.

Role Guard

Route에 Access하기 위한 Role을 지정해줬으니, 이제 User에게 권한 부여를 할 수 있는지에 대한 Validation을 해주기 위해 RoleGuard를 작성합니다.

  • Relfector를 사용하여 우리가 정의한 roles custom metadata에 접근한 후 AllowedRole Type의 Data를 추출하여 requiredRoles에 할당해줍니다.
  • Role이 필요없는 Route라면 requiredRoles가 존재하지 않을 것이므로 true를 반환합니다.
  • JwtGuard를 통과한 후 request객체에서 user 정보를 추출합니다.
  • rolesAny라면 누구나 Access 가능하다는 뜻이므로 true를 반환합니다.
  • userTyperoles에 포함되었는지 여부를 반환하여 검사합니다.

이제 다음과 같이 Controller에서 RoleGuard@Role Decorator를 적용할 수 있습니다.

Decorator Composition

현재 Swagger, Guard 등 Decorator들이 너무 많아 직관적이지 않고 코드가 지저분해 보입니다. 따라서 Auth에 필요한 Decorator를 한번에 묶어 제공해봅시다.

Role, wtAuthGuard, RoleGuard 3개의 데코레이터를 모두 묶어 나열하여 applyDecorators로 적용합니다. 주의할 점은 RoleGuard가 실행될 때 request 객체에 user가 존재해야 하므로 JwtAuthGuard가 먼저 실행되어야 한다는 점입니다. 조금 더 깔끔해진 Controller를 봅시다.


참고자료
NestJS Auth - Authorization
NestJS Doc

profile
어디를 가든 마음을 다해 가자

0개의 댓글