OAuth2.0은 권한 부여를 위한 산업 표준 프로토콜이다.
OAuth는 인증(Authentication)과 권한(Authorization)을 획득하는 것으로 볼 수 있다.
API 접근 위임에 대한 표준안을 만들기 위해 OAuth가 시작되었습니다.
사용자 입장에서는 써드파티의 서비스를 이용할 때 소셜플랫폼 아이디(이후 네이버로 가정)로 회원가입을 진행한다면 편할 것입니다. 그런데 써드파티에서 제공하는 로그인 폼에 네이버 아이디, 비밀번호를 입력해야 한다면 사용자는 신뢰할 수 없는 서비스에 보안정보를 입력하는 것이므로 꺼림칙할 것입니다. 이때 써드파티에서 안전하게 로그인을 진행하고 사용자 정보를 가져오도록 하는 표준을 제공하는 것이 OAuth의 목적입니다.
따라서 OAuth는 단순 로그인을 목적으로 하는 Authentication과 함께 Authorization을 진행하는 것을 목적으로 합니다. OAuth에서도 인증의 과정을 거치지만 이는 API 사용 인가에 대한 진행 과정으로 생각해야합니다.
이에 대한 비유를 NAVER D2에서 가져왔습니다.
사원증을 이용해 출입할 수 있는 회사를 생각해 보자. 그런데 외부 손님이 그 회사에 방문할 일이 있다. 회사 사원이 건물에 출입하는 것이 로그인이라면 OAuth는 방문증을 수령한 후 회사에 출입하는 것에 비유할 수 있다.
다음과 같은 절차를 생각해 보자.
나방문씨(외부 손님)가 안내 데스크에서 업무적인 목적으로 김목적씨(회사 사원)를 만나러 왔다고 말한다.
안내 데스크에서는 김목적씨에게 나방문씨가 방문했다고 연락한다.
김목적씨가 안내 데스크로 찾아와 나방문씨의 신원을 확인해 준다.
김목적씨는 업무 목적과 인적 사항을 안내 데스크에서 기록한다.
안내 데스크에서 나방문 씨에게 방문증을 발급해 준다.
김목적씨와 나방문씨는 정해진 장소로 이동해 업무를 진행한다.
위 과정은 방문증 발급과 사용에 빗대어 OAuth 발급 과정과 권한을 이해할 수 있도록 한 것이다. 방문증이란 사전에 정해진 곳만 다닐 수 있도록 하는 것이니, '방문증'을 가진 사람이 출입할 수 있는 곳과 '사원증'을 가진 사람이 출입할 수 있는 곳은 다르다. 역시 직접 서비스에 로그인한 사용자와 OAuth를 이용해 권한을 인증받은 사용자는 할 수 있는 일이 다르다.
위의 과정을 실제 OAuth Flow와 비교하여 살펴보겠습니다.
사전에 알아두어야 할 용어는 다음과 같습니다.
OAuth Roles
소셜로그인을 제공하는 플랫폼의 경우 Authorization server와 Resource Server를 분리하여 관리한다고 합니다.
OAuth Term
위의 단어들로 표현한 OAuth의 가장 기본적인 흐름은 다음과 같습니다.
위의 방식을 구체적으로 구현한 OAuth 인증의 종류는 총 4가지입니다.
가장 쉽게 구현되는 Implicit Grant를 살펴보고 문제점을 알아본 뒤,
가장 많이 사용되고 Implicit Grant의 취약점을 보완한 Authorization Code Grant에 대해 살펴보겠습니다.
rfc 스펙에 포함된 Implicit Grant Flow 다이어그램입니다.
Resource Owner가 Client를 통해 서비스를 이용하기 때문에, 두 주체를 User Agent로 표현한다고 보았습니다.
A - 클라이언트에서는 User Agent를 Authorization Endpoint로 보내며 플로우를 시작합니다. 클라이언트는 Client ID, Request Scope, Local State, Redirect URI(Authorization Server가 grant 혹은 deny 시에 User agent를 돌려보낼 URI)를 함께 보냅니다.
https://authorization-server.com/auth
?response_type=token
&client_id=29352910282374239857
&redirect_uri=https%3A%2F%2Fexample-app.com%2Fcallback
&scope=create+delete
&state=xcoiv98y3md22vwsuye3kch
B - Authorization server는 Client의 request에 대해 grant 혹은 deny 여부를 결정합니다. B는 두가지 플로우로 분절되어있습니다. Authorization Server에서 '로그인하시겠습니까?' 라는 카톡을 Resource Owner에게 보내면 Owner가 Accept 여부를 결정하여 Authenticate가 진행된다고 생각하시면 됩니다.
C - resource owner가 grant했다고 가정하면, Authorization server는 전달받은 Redirect URI를 통해 User Agent를 redirect 시킵니다. 이때 Redirection URI의 Fragment는 access token이 포함됩니다.
https://example-app.com/redirect
#access_token=g0ZGZmNj4mOWIjNTk2Pw1Tk4ZTYyZGI3
&token_type=Bearer
&expires_in=600
&state=xcoVv98y2kd44vuqwye3kcq
D, E → 이 과정을 통해 User Agent는 Redirection URI에서 Access Token을 획득하고 지정된 URI로 이동합니다.
G → 클라이언트는 Access Token을 얻어 Resource Server와 통신할 준비를 마쳤습니다.
Implicit Grant Type은 주로 사용의 편의성 때문에 사용됩니다. 특히 프론트 단에서 Authorization Code Grant Type보다 사용이 용이하기 때문에 채택됐습니다. 그러나 이러한 편의성으로 희생되는 security를 보완하는 과정에서 편의성이 저해되는 경우가 많았고, 애초의 장점을 잃는 경우가 많다고 합니다.
Security가 약해지는 가장 큰 이유는 Access Token이 URL을 통해 직접 전달되기 때문입니다. Access Token이 browser history에 남기 때문에 server는 token의 life-time을 짧게 설정해줘야합니다. 또한 Back Channel을 거치지 않기 때문에 RefeshToken을 받지 않습니다.* (Secure함이 보장되지 않기 때문에 Token을 갱신할 수 있는 RefeshToken 또한 주지 않는 것 같습니다.) 따라서 Client는 주기적으로 AccessToken을 얻는 귀찮은 과정을 거쳐야합니다.
이제 Implicit Grant를 사용할 유일한 이유는 Authorization Server가 CORS를 지원하지 않을 경우입니다. 추후 설명할 Authorization Code grant 방식에서 어플리케이션은 server에 HTTP POST 요청을 날려야합니다. Authorization server가 적절한 CORS 방식을 지원하지 않을 경우에는 Authorization Code grant 방식을 사용할 수 없기 때문에, Implicit flow로 접근합니다.
Implicit Flow에 대한 레퍼런스
What is the OAuth 2.0 Implicit Grant Type?
What Is a Back Channel?
Simply, a back channel is an outbound connection to a server on the Internet, automatically established by client software running a PC behind your firewall. It can also be as innocuous as some small bit of information ("cookies") left on a client desktop in an easily accessible location. The purposes of back channel connections and information gathering cookies are numerous, and can be classified as Useful, Questionable, and Evil.
→ 브라우저에서 서버와의 Connection으로 이해했습니다.
What does the term "Backchannel Request" means and how to make backchannel requests
rfc 스펙에 명시된 Authorization Code Grant 다이어그램
위에 명시된 Implicit flow와 비슷합니다. C부터 과정에 변화가 있습니다.
A - 클라이언트에서는 User Agent를 Authorization Endpoint로 보내며 플로우를 시작합니다. 클라이언트는 Client ID, Request Scope, Local State, Redirect URI(Authorization Server가 grant 혹은 deny 시에 User agent를 돌려보낼 URI)를 함께 보냅니다.
https://authorization-server.com/auth
?response_type=code
&client_id=29352915982374239857
&redirect_uri=https%3A%2F%2Fexample-app.com%2Fcallback
&scope=create+delete
&state=xcoiv98y2kd22vusuye3kch
B - Authorization server는 Client의 request에 대해 grant 혹은 deny 여부를 결정합니다. B는 두가지 플로우로 분절되어있습니다. Authorization Server에서 '로그인하시겠습니까?' 라는 카톡을 Resource Owner에게 보내면 Owner가 Accept 여부를 결정하여 Authenticate가 진행된다고 생각하시면 됩니다.
C - resource owner가 grant했다고 가정하면, Authorization server는 전달받은 Redirect URI를 통해 User Agent를 redirect 시킵니다. 이때 Redirection URI의 Fragment는 authorization code가 포함됩니다.
https://example-app.com/redirect
?code=g0ZGZmNjVmOWIjNTk2NTk4ZTYyZGI3
&state=xcoiv98y2kd22vusuye3kch
D - Client는 얻은 authorization 코드를 넣은 request를 authorization server의 token endpoint로 보내 access token을 요청합니다. 이 요청에는 code를 얻는데 사용됐던 redirect URL이 포함됩니다.
필요한 Param
E - Authorization server는 code와 URL을 검증하여 client를 authenticate 합니다. 유효하다면 server는 access token과 Optional하게 refresh token을 respond 해줍니다.
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3",
"token_type":"bearer",
"expires_in":3600,
"refresh_token":"IwOGYzYTlmM2YxOTQ5MGE3YmNmMDFkNTVk",
"scope":"create delete"
}
Implicit Flow에 비하여 additional layer of security를 제공하기 때문에 모바일 앱과 웹에서 주로 사용하는 방식입니다.
AccessToken은 브라우저와 서버의 통신을 통한 안전한 back channel에서 이루어지기 때문에 Attacker가 토큰을 intercept 하는 것으로부터 보호받을 수 있습니다.
API에 접속하기 위해서는 access token을 API 서버에 제출해서 인증을 해야 합니다. 이 때 사용하는 인증 방법이 Bearer Authentication 입니다. 이 방법은 OAuth를 위해서 고안된 방법이고, RFC 6750에 표준명세서가 있습니다.
예를들어 api 서버가 server.example.com이고, 접근해야 하는 path가 resource이고, access token이 mF_9.B5f-4.1JqM라면 아래와 같이 헤더 값을 만들어서 전송하면 됩니다.
GET /resource HTTP/1.1 Host: server.example.com Authorization: Bearer mF_9.B5f-4.1JqM
Bearer Authentication 에 대해서 살펴봅니다.
→ 최대한 공식문서와 공신력있는 도큐먼트를 레퍼런스로 하여 정리했습니다.
Authentication and Authorization
Authentication and Authorization
What is the OAuth 2.0 Authorization Code Grant Type?
OAuth 2.0 and OpenID Connect Overview
OAuth 2.0 암시적 허용 흐름 - Microsoft ID 플랫폼
Microsoft ID 플랫폼 및 OAuth 2.0 인증 코드 흐름 - Microsoft identity platform