요구사항
인턴십을 시작하면서 가장 먼저 마주한 업무는 인증/권한 서비스의 분리를 하는 작업이였습니다.
기존에 하나의 제품에서 관리되고 있었기 때문에 새로운 제품을 출시할 경우, 중복적인 회원 관리 로직을 구현해야 하고 제품을 이동할 때마다 고객은 새로운 로그인 절차를 거쳐야 하는 불편함을 감수해야 했습니다.
이러한 문제를 해결하기 위해서는 SSO를 지원하고, 이후에 추가할 여러 제품에 대한 회원 정보를 통합적으로 관리할 수 있도록 구조를 변경해야 하는 필요가 있다고 판단했습니다.
우선 독립적인 통합 인증/권한 서비스 제공을 위해 필요한 개념들을 학습하는 과정을 거쳤으며, 이 과정을 통해 얻은 여러 지식을 공유해보고자 합니다.
IAM 서버
IAM은 Identity and Access Management의 약자로 기업에서 오직 적합한 사람과 디바이스만 원하는 애플리케이션과 리소스 및 시스템에 접근할 수 있도록 권한을 허용하는 프레임워크로 정의할 수 있습니다. 그리고 IAM에는 SSO, MFA와 같은 모든 사용자의 신원과 접근 권한을 항상 확인할 수 있는 다양한 정책과 서비스, 기술 등이 포함됩니다.
이를 토대로 IAM 서버를 정의해본다면 IAM에 포함되는 여러 정책, 서비스, 기술을 통해 사용자 정보를 관리, 통제하는 주체라고 말할 수 있습니다.
IAM 서버의 역할은 다음과 같습니다.
- Authentication(인증)
- 특정 리소스에 접근을 요청한 사람 또는 디바이스가 권한이 있는 주체인지 검증하는 과정을 의미한다.
- ex) 로그인, 로그아웃
- Authorization(인가)
- 서비스 접근은 가능하지만 서비스에서 요청한 기능이나 자원에 대해서 접근할 수 있는 권한이 있는지 검증하는 과정을 의미
- ex) 어드민 계정은 회원 삭제 가능, 일반 회원은 회원 삭제 불가능
공항을 예로 든다면 인증은 탑승수속 과정, 인가는 비행기 티켓 확인 과정과 같은 개념입니다.
- User Management
- 회원 정보 관리를 위한 기능을 제공
- Central User Repository
- 회원 정보를 통합적으로 저장
위와 같은 개념적인 내용을 토대로 요구사항으로 제시한 인증/권한 서비스는 IAM 서버와 동일시 봐도 된다고 판단했고 IAM 서버의 4가지 역할을 수행하는 서버를 구현하는 것으로 목표를 구체화 할 수 있었습니다.
OAuth 2.0
IAM 서버가 무엇인지 확인했으니 인증, 인가 프로세스를 어떻게 구현할 것인가를 더 고민해볼 필요가 있었습니다.
회원 정보 관리나 통합 저장의 경우는 엄청나게 복잡한 로직이 필요하지 않지만 인증, 인가의 경우는 프로세스의 복잡도와 중요도가 높은 부분이기 때문에 이미 검증된 프로토콜이 존재했습니다.
OAuth 2.0이란, 접근 권한 허가를 위한 개방형 표준 프로토콜로 아래 네 가지 주체들에 의해서 이뤄지는 권한부여 체계를 의미합니다.
본래 OAuth 2.0은 인가에 대한 프로토콜로 탄생했지만 인증에 대한 절차가 포함되어 있었기에 Open ID Connect(OIDC) 라는 프로토콜을 추가해 인증, 인가에 대한 프로세스를 모두 포함할 수 있도록 발전했습니다.
OAuth 2.0의 네 가지 주체
- Resource Owner (자원 소유자)
- 보호된 자원에 대한 접근 권한을 부여할 수 있는 주체, 사용자로서 계정의 일부에 대한 접근 권한을 부여하는 사람을 의미합니다.
- Client (클라이언트)
- Resource Owner를 대신하여 권한을 부여받아 사용자의 리소스에 접근하려는 어플리케이션을 의미합니다.
- Resource Owner를 Authorization Server의 로그인 페이지로 이동시키거나 인증 이후 사용자의 상호 작용 없이 Authorization Server로부터 직접 권한을 얻을 수 있습니다.
- Authorization Server (인가 서버)
- Client가 Resource Owner 계정에 대한 동의 및 접근을 요청할 때 상호 작용하는 서버로서 Client의 권한 부여 요청을 승인하거나 거부하는 서버를 의미합니다.
- Resource Owner가 Client에게 권한 부여 요청을 승인한 후, Access token 을 Client에게 부여합니다.(OIDC를 함께 사용할 경우, ID Token도 함께 부여합니다.)
- Resource Server (보호 자원 서버)
- 사용자의 Resource가 포함된 서버를 의미합니다.
- Access Token을 수락 및 검증할 수 있어야 하며 권한 체계에 따라 요청을 승인할 수 있어야 합니다.
OAuth 2.0 grant Type
Grant Type은 Client가 Authorization Server로부터 Access Token을 부여받기 위해 전달하는 값에 따라 아래 Type으로 나뉩니다.
- Authorization Code Grant Type
- Implicit Grant Type (Deprecated)
- Resource Owner Password Credentials Grant Type (Deprecated)
- Client Credentials Grant Type
- Refresh Token Grant Type
- PKCE-enhanced Authorization Code Grant Type
이 중 채택한 방식은 Authorization Code Grant Type입니다.
Authorization Code Grant Type은 Resource Owner와 Authorization Server간의 로그인 절차 진행 이후 임시 코드를 Client에게 전달해 임시 코드를 가지고 Access Token을 발급받는 방식입니다. 이러한 flow를 통해서 AccessToken이 외부 브라우저로 노출되지 않고 코드를 일회성으로 사용하기 때문에 보안적인 측면에서 가장 안전합니다.
Token 종류
- ID Token : OIDC를 함께 사용할 경우, Access Token과 함께 발급되는 토큰으로 인증된 사용자라는 것을 증명합니다.
- Access Token : 사용자의 접근 권한 정보를 담은 토큰으로 인가 검증 시 활용됩니다.
- Refresh Token: Access Token이 만료된 경우, 재발급을 위해 사용되는 토큰입니다.
OAuth 2.0의 인증, 인가 과정
- Resource Owner가 Client를 통해 Resource Server의 리소스 요청을 보낸다.
- Client는 Resource Owner의 로그인 여부를 체크하고, 로그인이 안되어 있다면 Authorization Server에서 제공하는 로그인 페이지로 redirect 시킨다.
- Resource Owner의 로그인 정보를 Authorization Server로 직접 보내 승인 요청을 한다.
- 검증된 사용자일 경우 Authorization Server는 authorization code를 Client에게 전송한다.
- Client는 authorization code를 다시 Authorization Server에 전송해 Access Token을 교환받는다.
- 이후 Resource Owner는 로그인된 상태로 다시 한번 Client를 통해 Resource Server에 대한 리소스 요청을 보낸다.
- Client는 해당 Resource Owner에 대한 Access Token을 가지고 있으므로 Access Token을 헤더에 포함해 Resource Server로 전달한다.
- Resource Server는 Access Token에 포함된 접근 권한 정보를 가지고 적절한 처리를 한 다음 응답한다.
결론
OAuth 2.0의 주체를 현재 프로젝트의 상황에 대입해본다면 각 주체는 다음과 같습니다.
- Resource Owner : 회원
- Client : Client 역할 및 API Gateway 역할을 수행하는 별도의 서버
- Authorization Server : IAM 서버
- Resource Server : 각 제품들
Resource Owner와 Resource Server의 경우, 현재 프로젝트에서 직접 구현해야 하는 대상은 아니지만 Client와 Authorization Server는 이번 프로젝트에서 구현해야 하는 범위에 속합니다. 그래서 각 주체의 역할을 수행할 서버를 어떻게 구현할 지 고민해야 했고 그 결과를 하나씩 공유하고자 합니다.