Cognito를 사용하여 API gateway 접근 권한 부여하기

728x90

 

서론

Cognito의 역할



Cognito는 아래 그림과 같이 동작한다.




- 클라이언트 측에서 특정 경로로 접속하려고하는데, 그 경로가 권한이 부여되어있다면 접근이 제한된다.
- 클라이언트는 Cognito의 앱 클라이언트로 들어가서 로그인을 실행한다.
- 로그인에 성공하면 Cognito에서 인증 토큰을 발급하여 클라이언트 측으로 전송한다. 그리고 Cognito에 의해 Callback URL로 redirect되어 API gateway에 다시 접근하게 된다. 
- HTTP API gateway는 JWT 권한 부여자를 통해 헤더의 JWT를 인식하고 이를 Cognito에 보내서 알맞은 토큰인지 검증 요청한다.
- 토큰이 알맞은 토큰일 경우 라우팅으로 접속하여 어플리케이션을 실행시켜 응답을 클라이언트에게 돌려준다.


사전 준비 - Lambda, API gateway


본격적으로 Cognito 인증을 사용해보기 전에 API gateway와 어플리케이션부터 구현하고 정상동작하는지 확인한다.

Lambda 함수 생성


실제 프로젝트는 Fargate나 EC2를 사용하여 서버를 구동할 것이다. 하지만 지금은 연습삼아 만드는 임의의 어플리케이션이므로 접속하면 문자열을 반환하는 간단한 기능을 구현한다. 그러므로 본 작업은 lambda를 사용하여 구현한다.

AWS lambda 서비스에 접속하여 lambda를 새로 생성한다. node.js를 선택한다. (다른 언어로 구현해도 상관없다. 문자열을 출력하는 정말 간단한 어플리케이션을 만들 것이기 때문이다.)


문자열 문구를 'Hello from protected resources!'로 만들고 deploy를 눌러 적용해준다. 이렇게 하면 lambda 생성은 끝이다.

HTTP API gateway 생성


AWS API gateway 서비스에 접속한다. 새 HTTP API gateway를 생성한다. 이름은 임의로 작성해도 된다. 



통합은 Lambda를 선택하고 Lambda 함수는 방금 생성했던 lambda를 선택한다. 

 



경로도 추가해준다. 경로명은 임의로 추가해도 된다. 이렇게 생성하고 아래와 같이 나온다면 통합이 정상적으로 완료된 것이다.


API gateway에서 제공하는 URL을 복사해서 POSTMAN을 통해 접속 테스트 한다.

 


아래와 같이 정상적으로 응답하는 것을 확인할 수 있다.

 

 

Cognito 사용자 풀 생성 및 앱 클라이언트 호스팅


이제 Cognito의 사용자 풀과 앱 클라이언트를 생성할 차례다. 현재 AWS Cognito 인터페이스는 사용자 풀을 생성할 때 앱 클라이언트를 함께 생성하도록 만들어져 있다. 

사용자 풀 로그인 옵션은 이메일에 체크한다. 나머지는 크게 건들 것이 없으므로 패스한다. 간단히 테스트만 할 것이므로 MFA를 비활성화하는 것도 좋다. 



아래는 중요한 부분이다. 로그인 화면 생성과 관련된 부분이다. Cognito 호스팅 UI 사용에 체크하면 Cognito에서 제공하는 로그인 화면을 이용할 수 있다. Cognito 도메인에 앱 로그인 도메인 이름을 임의로 결정하여 작성한다.



허용된 콜백 URL도 입력해준다. 임의로 localhost:3000을 입력한다. 물론 localhost에 띄워진 어플리케이션이 없으므로 Not Found가 뜰 것이다. 하지만 JWT를 테스트하기엔 충분하다. JWT는 HTTP 요청의 헤더에 포함되어 보내질 것이기 때문이다.



OAuth 2.0 권한 부여 유형을 수정한다. 다른 부분에선 체크를 해제하고, 암시적 권한 부여에만 체크한다. 

 


이렇게 해서 생성을 눌러주면 정상적으로 사용자 풀과 앱 클라이언트가 생성된 것을 확인할 수 있다.



로그인을 테스트 해보려면 아래 앱 통합 탭을 누르고 아래로 쭉 내리면 앱 클라이언트 목록이 나온다. 앱 클라이언트 이름을 클릭한다. 

 


이처럼 앱 클라이언트 정보를 확인할 수 있다.



아래로 쭉 내리면 호스팅 UI가 있다. (사용자 풀을 생성할 때 함께 생성했었다.) 호스팅 UI 보기를 클릭한다.

 


Tada~ 아래와 같이 AWS에서 제공하는 로그인 화면이 보여진다. 사용자 풀을 생성할 때 입력한 Cognito 도메인이 그대로 나오는 것을 확인할 수 있다.

 

 

 




여기까지 진행하면 Cognito 생성은 완료된 것이다. 

Cognito - API gateway 연결


이제 Cognito와 API gateway를 연결하여 접근을 제한하고 인증된 사용자만 경로로 접속할 수 있도록 해본다.

HTTP API gateway 권한 부여자 설정


HTTP API gateway의 권한 부여자를 사용하면 특정 경로에 대한 접근을 제한할 수 있다. 생성했던 API를 들어가서 왼쪽 탭의 Authorizer로 들어간다. 생성한 경로를 눌러 권한 부여를 누른다.


발급자 URL에는 "Cognito 도메인/사용자 풀 ID"를 입력한다. 대상에는 앱 클라이언트 ID를 입력한다. 이렇게 해서 통합을 완료한다.

 


아래와 같이 뜨면 해당 경로에 대해 권한 부여자가 정상적으로 설정된 것이다.

 



POSTMAN으로 GET 요청을 보낸다. API gateway 스테이지에 나와있는 URL 주소를 가져와 방금 권한을 설정한 경로를 붙이고 GET 요청을 보내면 아래처럼 Unauthorized가 뜬다.

 


Unauthorized가 나오면 권한 설정이 정상적으로 작동하는 것이다. (헤더에 Authorization 정보가 없으므로)

Cognito App client 접속 및 JWT 활용


이번에는 권한을 가진 사용자가 jwt를 가지고 정상적으로 해당 경로에 접근하는 것을 실습하겠다. 우선 아까 만든 Cognito 사용자풀의 앱 클라이언트로 접속한다. 아래와 같이 로그인 화면이 나올것이다. 


sign up을 해서 회원가입을 해준다. 회원가입을 하면 사용자풀에 사용자 정보가 등록된다.

 



생성한 회원정보로 로그인을 시도한다. 로그인에 성공하면 콜백 URL인 localhost:3000으로 갈 것이다. 여기서 주소 옆에 보이는 쿼리스트링에 JWT 정보가 담겨있다.

 

 

제대로 된 JWT인지 확인하기


id_token과 access_token 그리고 만료기한 등 여러 정보가 담겨있는데, 여기서 id_token만 빼내어서 jwt.io에서 decode 테스트 해본다. jwt.io에서 제공하는 encode 탬플릿에 방금 복사해온 id_token 정보를 넣으면 오른쪽과 같이 해석해준다.

 


signature verified 가 뜨면 정상 JWT로 인식된 것이다. JWT가 정상적으로 인증되어야만 API에 정상적으로 접근 할 수 있다.



 

 

JWT로 인증하여 API에 요청을 보내고 정상적인 응답 받기


이전에 권한 설정을 하여 Blocking된 URL에 다시 GET 요청을 보내보자. 이번에는 HEADER에 key에는 Authorization을 입력하고 value에는 방금 복사했었던 JWT 토큰을 입력하자.




JWT를 Authorization 헤더에 넣고 보내면 아래와 같이 정상적으로 응답을 받을 수 있는 것을 확인할 수 있다.


 

마치며


본 글에서는 Lambda로 어플리케이션을 테스트했지만, 실제 서비스에서는 EC2, ECS 등의 컴퓨팅 자원을 연결하여 어플리케이션을 제공할 것이다. 사실 이렇게 경로 하나하나씩 권한을 설정하는 것은 대단히 번거롭고 시간이 많이 걸리는 작업이다. 그러므로 실제 서비스 배포시 경로 권한 설정은 AWS CDK를 이용하여 프로비저닝하는 것이 좋은 선택이 될 것이다. 현재 실습은 그냥 Cognito와 API gateway의 동작 구조를 파악하기 위해 해볼만할 것이다.