특정 서비스에서 사용자를 대신해서 구글이나 트위터에 글을 남겨주려면 어떻게 해야 할까?
사용자로부터 구글, 트위터의 id, pw를 제공받아 우리의 서비스에 저장하고 활용할 수 있다.
하지만 이 방법은 안전하지 않다. 사용자가 우리 서비스를 신뢰하기 힘들며 구글, 트위터 입장에서도 마찬가지다.
이러한 문제를 해결하기 위해 구글은 AuthSub, 야후는 BBAAuth 등 각자 회사에서 개발한 방법을 사용했지만 이 방법들은 표준화되어 있지 않아서 개별적으로 개발, 유지보수 해야 한다는 단점이 있었다.
이런 문제를 해결하기 위해 등장한 것이 OAuth이다.
구글, 페이스북, 트위터와 같은 다양한 플랫폼의 특정한 사용자 데이터에 접근하기 위해 제 3자 클라이언트 (우리의 서비스) 가 사용자의 접근 권한은 위임받을 수 있는 표준 프로토콜이다.
용어 정리
Resource Owner : 우리서의 서비스를 이용하면서 구글, 페이스북 등의 플랫폼에서 리소스를 소유하는 사용자이다.
Autorization Server : Resource Owner를 인증하고, 클라이언트에게 엑세스 토큰을 발급한다.
Resource Server : 구글, 페이스북 과 같이 resource를 가지고 있는 서버이다.
위 둘은 별개의 서버로 구성할 수도, 하나의 서버로 구성할수도 있다.
Client : Resource Server의 자원을 이용하고자 하는 서비스이다. 우리가 개발하려는 서비스이다.
(Authorization Server, Resource Server 의 입장에서는 우리의 서버가 클라이언트이다)
OAuth 2.0 서비스를 이용하기 위해서는 Client를 Resource Server에 등록해야 한다. 이 때, redirect URI를 등록해야 한다.
Redirect URI는 사용자가 OAuth를 통해 인증을 마치고 사용자를 리다이렉션 시킬 위치이다.
OAuth 2.0은 인증에 성공한 사용자를 등록된 Redirect URI로만 리다이렉션 시킨다. 이유는 승인되지 않은 URI로 리다이렉트 시킬 경우 Authorization code를 탈취당할 수 있기 때문이다.
등록과정을 마치면 Client ID와 Client Sercret을 얻는다.
이 두가지는 Access Token을 획득하는데 사용된다
Client ID는 공개되어도 되지만 Client Secret은 공개되면 보안 사고로 이어질 수 있다.

Resource Owner가 우리 서비스에서 소셜 로그인(구글로 로그인하기 등) 버튼을 클릭해 로그인을 요청한다.
Client(우리 서비스)는 프로세스를 시작하기 위해 사용자의 브라우저를 Authorization Server로 보내야 한다.
클라이언트는 이 때 Autorization Server가 제공하는 Authorization URL에 response_type, client_id, redirect_uri, scope 등의 매개변수를 쿼리 스트링으로 포함해서 보낸다.
Resource Owner는 제공된 로그인 페이지에서 Id, Pw 등을 입력해서 인증한다.
인증에 성공하면, Authorization Server는 제공된 Redirect URI로 사용자를 리다이렉션 시킨다. 이 때, Redirect URI에 Authorization Code를 포함해서 사용자를 리다이렉션 시킨다.
Authorization Code는 클라이언트가 Access Token을 획득하기 위해 사용하는 임시 코드이다. 이 코드는 수명이 매우 짧다. (1~10분)
Client는 Authorization Server에 Authorization Code로 요청하고 Access Token을 응답받는다.
Client는 발급받은 Resource Owner의 코드를 저장하고 Resource Server에서 Resource Owner의 리소스에 접근하기 위해 Access Token을 사용한다.
Access Token은 유출되어서는 안되기 때문에 제 3자가 가로채지 못하도록 HTTPS 연결을 통해서만 사용될 수 있다.
POST /oauth/token HTTP/1.1
Host: authorization-server.com
grant_type=authorization_code
&code=xxxxxxxxxxx
&redirect_uri=https://example-app.com/redirect
&client_id=xxxxxxxxxx
&client_secret=xxxxxxxxxx
일반적으로 위와 같은 형태로 요청을 보내 교환한다.
필수인 매개변수는 다음과 같다.
grant-type : 항상 authorization_code로 설정
code : 발급받은 Authorization code
redirect_uri : redirect uri
client id : client id
client secret : client secret이 발급된 경우 포함해서 요청해야 한다
위 과정들을 성공적으로 마치면 Client는 Resource Owner에게 로그인 성공을 알린다.
이후 Resource Owner가 Resoure Server 의 리소스가 필요한 기능을 클라이언트에게 요청하면 클라이언트는 Resource Owner의 Access Token을 사용하여 제한된 리소스에 접근하고 Resource Owner에게 자사의 서비스를 제공한다.
OAuth 2.0은 스코프라는 개념을 통해 유저 리소스에 대한 클라이언트의 접근 범위를 제한한다. 스코프는 여러개가 될 수 있다.
예를 들어 우리의 서비스가 사용자의 구글 연락처를 받아오고 싶다면 OAuth 2.0 스코프에 스코프 문자열을 포함해서 OAuth 2.0 제공자에게 전달하면 된다. 그러면 Resource Owner는 권한 요청 화면을 만난다.
왜 굳이 클라이언트에게 바로 Access Token을 발급하지 않고 Authorization Code를 발급할까?
이유는 만약 이렇게 한다면 Redirect URI를 통해 바로 Access Token을 보내줘야 하는데 이렇게 하면 URL 자체에 데이터를 실어 보내는 방법 밖에 없다. 이런 방법은 민감한 데이터인 Access Token을 보내는데 적합하지 않다. 즉 보안상의 문제로 Authorization Code를 사용하는 것이다.