OAuth 2.0
작성일
웹 서핑을 하다보면 Google, Facebook 등의 소셜 로그인 기능을 쉽게 찾아볼 수 있다. 클릭 한 번으로 간편하게 로그인할 수 있으며 연동되는 애플리케이션에서 Google, Facebook 등이 제공하는 기능을 간편하게 사용할 수 있다는 장점이 있다.
이 때 사용되는 프로토콜이 바로 OAuth
다.
OAuth란
OAuth는 인터넷 사용자들이 비밀번호를 제공하지 않고 다른 웹사이트 상의 자신들의 정보에 대해 웹사이트나 애플리케이션의 접근 권한을 부여할 수 있는 공통적인 수단으로서 사용되는 접근 위임을 위한 개방형 표준이다.
OAuth에는 3가지 주체가 있다.
- 사용자, User: 내 사이트를 이용하고자 하는 사용자
- 내 사이트, mine: xxxxx.com
- 그들의 서비스, Their: Google, Facebook, Twitter 등
OAuth를 이용하면 우리의 서비스가 그들이 만든 서비스와 상호작용할 수 있다.
User는 mine을 통해 accessToken으로 그들의 서비스에 접근할 수 있다. 최종적으로는 OAuth를 통해 accessToken을 얻어낼 수 있다.
OAuth 주요 용어
OAuth에는 3가지 주체가 있다고 했다. 3가지 주체를 OAuth 용어에 맞게 해석하면 다음과 같다.
- 사용자(User) ⇒ Resource Owner
- 내 사이트(mine) ⇒ Client
- 그들의 서비스(Their) ⇒ Resource Server
Resource Server
, Resource Owner
, Client
이 세가지의 관계가 OAuth의 핵심
이다.
Resource Owner
웹 서비스를 이용하는 사용자, 자원을 소유한 사람 (자원은 개인정보라고 생각하면 된다.)
Client
개인이 만든 애플리케이션 서버
Resource Server
사용자의 개인정보를 가지고 있는 서버 (Google, Facebook 등)
Authorization Server
인증과 관련된 처리를 전담하는 서버
공식 메뉴얼에서는 Resource Server와 Authorization Server를 구분하여 보여주지만 우리는 합쳐서 Resource Server라고 부르겠다.
OAuth2.0 등록
Client가 Resource Server를 이용하기 위해선 Resource Server에게 사전에 승인을 받아야한다. 이를 등록(Register)
한다고 하며, 서비스(Google, Facebook 등)마다 등록하는 방법은 다르다.
하지만 아래 세가지 요소를 공통적으로 갖는다.
client id
, client secret
, authorized redirect URIs
Client ID
애플리케이션을 식별하는 식별자 ID를 의미한다.
Client Secret
식별하는 값에 대한 비밀번호. 즉, Client ID에 대한 비밀번호이다. Client ID는 외부에 노출될 수 있으나 Client Secret은 절대 외부에 노출되면 안된다.
Authorized redirect URIs
authorized는 ‘권한을 부여하다’라는 뜻이다.
Resource Server만 갖는 정보이며 Client에 권한을 부여하는 과정에서 나중에 Authorized code를 전달하는 통로이다. 나중에 Clinet ↔ Resource Server 유효성 검사에서 이 redirect URIs도 체크되며 해당 주소가 아닐 경우 Resource Server는 해당 Client가 아니라고 판단한다.
Scope
Resource Server에서 사전에 사용 가능하도록 미리 정의한 기능
Resource Owner의 승인
등록을 통해 Resource Server는 client id, client secret, redirectURL을 알게 되었고, Client는 client id와 client secret을 알게 되었다.
Resource Server에 4가지 기능이 있다고 가정하고 각각의 기능을 A, B, C, D라고 할때 client는 Resource Server의 모든 기능이 필요한게 아니고 B와 C 기능만 필요하다고 하다고 가정한다. 그렇다면 모든 기능에 대한 인증을 받는게 아니라 최소한의 인증만 받는게 효율적이다.
Resource Owner가 Client에 접속한다. 이때 Resource Server의 기능 중 하나인 페이스북 글쓰기 기능을 사용하려고 한다고 가정하자. 그렇다면 아래와 같이 ‘페이스북으로 로그인하기’라는 페이지가 보이게 된다.
버튼의 링크는 아래와 같다. 이 링크를 통해 Resource Owner는 Resource Server로 접속하게 된다.
http://resource.server/?client_id=1&scope=B,C&redirect_uri=http://client/callback
Resource Server는 Resource Owner의 현재 로그인 여부를 확인한다. 로그인이 안되어있으면 로그인을 요청한다. 로그인이 완료되면 그때서야 요청한 링크의 client id와 redirect URL를 Resource Server의 client id와 redirect URL과 비교한다. 같다면 Resource Owner에게 scope에 해당하는 기능을 부여할 것인지를 확인하는 메시지를 전송한다. (향후 redirect_uri를 통해서 Resource Server는 Client에게 임시비밀번호인 Authorization code를 제공한다.)
허용버튼을 누르면 (Resource Owner에서 Resource Server로 요청) Resource Server에 user id, scope 저장됨
Resource Server의 승인
임시비밀번호인 authorization code를 Redirect URL
을 통해 Resource Server에서 Resource Owner에게 전송한다.
헤더에 Location 값을 전달하는 것을 redirection
이라고 한다. (여기서 ?code=3은 authorization code 이다.) Resource Server가 Resource Owner의 웹 브라우저에게 저 주소(http://client/callback?code=3)로 이동하라고 명령한 것이다.
Resource Owner의 웹 브라우저는 Location의 헤더값에 의해서 사용자가 인식하지도 못하게 주소(http://client/callback?code=3)로 redirect 한다. 주소 중 ?code=3을 통해 Client는 authorization code 값이 3이라는 것을 알게 된다.
Client는 Resource Owner를 통하지 않고 Resource Server로 직접 접근한다. 직접 접근할때 authorization code와 client id, client secret 값을 같이 전송한다. 이제 Resource Server는 authorization code와 client id, client secret 값이 일치하는지 확인하고 일치하면 access token
을 발급한다. 그리고 필요없어진 Authorization code는 지운다.
그렇게 토큰을 받은 Client는 사용자에게 최종적으로 로그인이 완료되었다고 응답한다.
OAuth의 목적은 최종적으로
Access Token을 발급
하는 것이다.
이제 Client는 Resource Server의 API를 요청해 Resource Owner의 ID와 같은 사용자 정보를 가지고 올 수 있다. 그리고 Access Token의 기간이 만료되면 Refresh Token을 이용해서 Access Token을 재발급 받는다.
OAuth 흐름 정리
- Resource Owner는 서비스(client)를 이용하기 위해 로그인 페이지에 접근한다.
- 그럼 서비스(Client)는 Resource Owner에게 로그인 페이지를 제공하게 된다. 로그인 페이지에서 사용자는 ‘구글/페이스북으로 로그인’ 버튼을 누른다.
-
Resource Owner가 로그인 버튼을 클릭하게 되면 특정한 url이 구글/페이스북 서버쪽으로 보내지게 된다.
(특정한 url: http://resource.server/?client_id=1&scope=B,C&redirect_uri=http://client/callback)
-
Resource Owner가 보낸 client_id와 redirect_uri를 Resource Server에 등록된 정보와 비교한다. 확인이 완료되면 Resource Server로 부터 전용 로그인 페이지로 이동하여 사용자에게 보여준다.
-
ID/PW로 로그인을 하게되면 Client가 사용하려는 기능(scope)에 대해 Resource Owner의 동의(승인)을 요청한다. 즉, scope에 해당되는 권한을 클라이언트에게 부여할 것인지 사용자에게 재차 확인한다.
위 이미지가 의미하는 것은 다음과 같다.
‘Client는 Resource Owner를 대신해 해당 기능(scope)를 사용하려고 합니다. 동의하시겠습니까?’
동의를 누르면 Resource Owner는 Client가 해당 기능 사용에 위임했다는 것을 의미한다.
- 하지만, 이미 Owner가 Client에게 권한 승인을 했더라도 아직 Server가 허락하지 않았다. 따라서, Resource Server도 Client에게 권한 승인을 하기위해 Authorization code를 Redirect URL을 통해 사용자에게 응답하고
- 사용자는 그대로 Client에게 다시 보낸다.
- 이제 Client가 Resource Server에게 직접 url(client_id, client_secret, authorization code 등)을 보낸다.
- 그럼 Resource Server는 Client가 전달한 정보들을 비교해서 일치한다면, Access Token을 발급한다. 그리고 필요없어진 Authorization code는 지운다.
- 그렇게 토큰을 받은 Client는 사용자에게 최종적으로 로그인이 완료되었다고 응답한다.