사용자가 어떤 웹 서비스를 통해 구글 캘린더, 트위터와 같은 외부 웹 서비스 기능을 사용하고 싶을 때, 웹 서비스는 외부 웹 서비스에 사용자의 정보를 가지고 접근할 수 있어야 한다. 가장 쉬운 방법은 외부 웹 사이트에 등록된 사용자의 id, password를 갖고 접근하는 것이다. 하지만 이 방법은 보안적으로 굉장히 취약하다. 이를 해결한 방법이OAuth이다. 외부 웹 서비스가 accessToken을 발급하고, 우리는 OAuth를 이용해 이 accessToken을 받을 수 있다. accessToken은 다음과 같은 장점을 가진다.
해당 사이트의 id, password와 같은 정보가 없다.
꼭 필요한 기능의 권한만 받을 수 있다.
용어
위에서 설명한 주최자에 대한 용어는 다음과 같다.
사용자: Resource Owner
외부 웹 사이트: Resource Server (또는 Authorization Server)
우리의 웹 사이트: Client
Client 등록
Client가 Resource Server에 접속하려면 사전에 등록을 해놓아야 한다. 이 포스트에서는 가장 대중적으로 많이 사용하는 구글을 기준으로 설명한다. 추후에 Naver나 카카오와 같은 서비스의 등록 방법도 소개할 예정이다.
등록할 때 공통적으로 입력을 받는 정보는 다음과 같다.
Client Id: Resource server가 Client를 식별하는 식별자
Client Secret: Id에 대한 비밀번호
Authorized redirect URIs: Resource Server가 권한을 부여하는 과정에서 Authorize code를 주는데, 그것을 이 URI로 전달해준다. 이 주소가 아닌 다른 주소로 요청을 하면 Resource Server는 해당 요청을 무시한다.
왼쪽 메뉴 중 [API 및 서비스] - [사용자 인증 정보] - [사용자 인증 정보 만들기] - [OAuth 클라이언트 ID] - [동의 화면 구성]버튼 클릭
[외부] 선택 후 [만들기]
앱 이름, 사용자 지원 이메일, 개발자 연락처 정보 등록 후 [저장 후 계속] 앱 도메인 옵션을 통해 동의화면에 정보를 추가할 수 있다.
[범위 추가 또는 삭제] - email, profile, openid 선택 후 [업데이트] - [저장 후 계속]
테스트 사용자는 따로 추가 필요 없으므로 [저장 후 계속] - [대시보드로 돌아가기]
이 단계까지 거치면 사용자 인증 정보를 만들기 전 OAuth 동의 화면을 만든 것이다.
다시 왼쪽 메뉴 중 [사용자 인증 정보] - [사용자 인증 정보 만들기] - [OAuth 클라이언트 ID]
애플리케이션 유형 : 웹 애플리케이션 이름: 프로젝트 이름 입력 승인된 리디렉션 URI : callback URI를 입력한다. 인증을 받은 후 이 URI로 리다이렉션된다. [만들기] 클릭
그러면 위와 같이 클라이언트 ID와 클라이언트 보안 비밀번호가 생성된다. 이 정보를 통해 추후에 client에서 resource server로 접근을 할 수 있다.
위와 같은 방법으로 client를 등록할 수 있다. 페이스북, 깃허브와 같은 다른 사이트도 위와 거의 유사한 방식으로 등록을 진행한다.
승인
Resource Server에 Client를 등록하면 양쪽 모두 Client ID, Client Secret, redirect url을 알게 된다. (Client는 승인 전 redirect url에 해당하는 페이지를 구현해놓아야 한다.) 승인을 받는 과정을 단계별로 알아볼 것이므로 차근차근 따라오면 된다.
Resource Owner의 승인
Resource Owner는 Resource Server의 기능을 사용하기 위해 client에게 로그인을 요청한다.
Client는아래와 같은 버튼을 보여준다. 각 버튼에는 다음과 같은 주소가 연결되어 있다. https://resource.server/?client_id={클라이언트 ID}&scope={사용하고자 하는 기능}&redirect_uri={리디렉션 uri}
Resource Owner가 위 주소로 Resource Server에 접속하면, 로그인 여부에 따라 Resource Server가 Resource Owner에게 로그인을 요청한다.
로그인에 성공하면 Resource Server는 위 주소의 client_id 값이 등록되어 있는지 확인한다.
client_id가 등록되어 있다면 redirect_uri도 같은지 확인한다. 다르면 작업을 끝낸다.
Resource Server는 Resource Owner에게 "Client에게 이러이러한 권한을 줍니까?" 라고 동의를 구한다.
허용 받으면 Resource Server는 Resource Owner가 어떤 기능을 허용했는지 저장한다.
Resource Server의 승인
Resource Server는 바로 accessToken을 발급하지 않고 임시 비밀번호인 authorization code를 발급한다.
Resource Server는 response의 헤더에 Location: https://client/callback?code={authorization code}를 넣고 전송해 client의 callback uri로 접속하게 한다.
두 방식 중에서 curl 명령어를 사용하여 http 헤더의 bearer 값으로 access token을 넘겨주는 방식이 표준화된 방식이기 때문에 더 선호된다고 한다.
Refresh token
Access token은 일주일, 한달과 같이 특정한 유효기간이 있다. 이 기간이 만료되면 더이상 이 토큰을 이용해 api를 호출할 수 없게 된다. 이때 refresh token을 이용해 access token을 갱신할 수 있다. 아래는 OAuth 2.0에서 access token과 refresh token이 동작하는 방식을 표현한 그림이다.
출처:OAuth 2.0 공식 레퍼런스 access token이 만료되기 전까지는 access token으로 통신을 하다가 만료되면 refresh token을 통해 access token을 새로 발급받는다. (이때 refresh token도 함께 갱신해 보내는 서버도 있다.)
OAuth와 같이 다른 서비스와의 연합을 통해 사용자를 식별하는 인증 체계를federated identity라고 한다. 주요한 서비스들은 이런 방식을 쉽게 구현할 수 있는 방법을 제공한다. 한편 많은 API는Restful하게 만들어지고 있으므로 Restful의 의미에 대해 공부하면 더 좋다.