ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • OAuth란?
    network, security 2021. 9. 20. 00:04

    OAuth가 왜 필요할까?

    이전에 내 카드 사용 내역을 토스에서 확인하기 위해 사용하는 카드를 토스에 연동할 일이 있었다. 카드 사진을 찍으라고 해서 그건 별 생각 없이 찍었는데, 이어서 비밀번호 4자리까지 입력하라고 하는 것이 아닌가? 순간적으로 굉장히 찝찝했다. "이걸 알려주는 게 맞나..?"

     

    토스가 카드 비밀번호까지 알게 된다면 사실상 내 카드에 대한 모든 정보를 알고 있는 셈이기 때문에 내 카드를 충분히 도용할 수 있을 것이다. 토스라는 서비스에 대한 신뢰가 있기 때문에 결국 비밀번호를 입력하고 카드 연동까지 완료하긴 했지만, 사용자로서 그렇게 기분 좋은 경험은 아니었다.

     

    토스에게 내 카드 사용 내역을 알려주고는 싶지만, 그렇다고 해서 내 비밀번호까지 알려주고 싶은 건 아니다. 토스는 내가 허락한 아주 한정된 정보만 알았으면 한다. 이런 필요성을 위해서 탄생한 것이 바로 OAuth이다. 내가 허락한 영역에 대해서는 나를 대신해서 토스와 같은 어플리케이션이 자유롭게 내 정보를 사용할 수 있도록 하는 것이다. (누구나 접해봤을 예이기 때문에 토스를 예로 들었지만, 토스가 나에게 비밀번호를 물어본 이유를 정확히는 모른다. 아직 OAuth를 지원하지 않는 금융사들이 많아서 이렇게 한 것이 아닐까 하는 뇌피셜을 가져보지만, 혹시 다른 이유가 있다면 미리 죄송합니다!)

     

    OAuth 2.0이 정의된 RFC6749에서는 OAuth를 다음과 같이 소개하고 있다.

     

    The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service, either on behalf of a resource owner by orchestrating an approval interaction between the resource owner and the HTTP service, or by allowing the third-party application to obtain access on its own behalf. This specification replaces and obsoletes the OAuth 1.0 protocol described in RFC 5849.

     

    볼드체로 표시된 단어를 집중해서 읽어보면 OAuth가 제한된 리소스에 대한 인가를 핵심 내용으로 하는 프로토콜이라는 것을 알 수 있다. (참고로 이 글에서 지칭하는 OAuth는 OAuth 2.0을 지칭한다. OAuth 1.0과 2.0은 목표는 같지만 구체적인 내용은 다르다. 현 시점에서는 2.0을 사용하는 것이 맞으므로 2.0 내용을 기준으로 설명하도록 하겠다.)

     

    OAuth 2.0의 대략적인 flow

    설명에 앞서 개인적으로 OAuth를 이해하는 데 큰 도움이 되었던 영상을 추천한다.

    • 6분짜리 훌륭한 introduction: 이 짧은 영상 하나만으로 OAuth가 무엇인지 감을 잡을 수 있다.
    • 1시간짜리 굉장히 훌륭한 강연: Okta라는 곳에서 일하는 Nate라는 분이 정말 천상과 같은 설명을 해주신다. 본 글에서는 이 강연의 내용과 Okta의 웹페이지를 많이 참고하였다.

     

    OAuth에는 다음과 같은 세 가지 역할이 존재한다.

    • Resource owner: 나와 같은 사용자이다.
    • Client: 토스와 같은 어플리케이션(third-party application)이다. 사용자의 허락을 받아서 다른 서비스에 접근하고자 한다.
    • Authorization server & Resource server: 우리의 예에서는 카드사를 가리킨다. 이 서버는 인가를 담당하는 authorization server와 인가받은 사용자에게 허락된 영역에 한해 접근을 허용하는 resource server가 있다. 둘은 같은 서버일 수도, 다른 서버일 수도 있다.

     

    OAuth flow에는 Authorization Code Grant, Implicit Grant, Password Grant, Client Credentials Grant 등 여러 종류가 있지만, 이 중에서 우리는 OAuth의 전형적인 형태이며 서버 애플리케이션에서 많이 사용하는 authorization code grant를 중점적으로 살펴볼 것이다.

     

    SPA(Single Page App), 네이티브 모바일 앱 등은 서버 어플리케이션과 다른 방식을 사용한다. 이런 어플리케이션의 authorization code grant에서 중요한 client secret이라는 기밀 정보를 안전하게 저장할 수 없다는 한계 때문에, access token를 안전하게 발급받기가 힘들다. 이 때문에 보안적으로 좀 더 약한 방식을 사용하거나 PKCE(Proof Key for Code Exchange) 등 보안을 강화하기 위한 장치를 좀 더 써야 한다. (기회가 되면 이 내용을 다른 글에서 다뤄보면 좋을 것 같다)

     

    Authorization code grant의 과정은 다음 그림 한 장으로 설명할 수 있다. (앞서 소개한 강연에서 스샷을 떠왔다.)

    정말 깔끔한 다이어그램!

    1. (이 단계는 위 그림에는 나와 있지 않지만) Yelp(client)는 OAuth flow를 사용하기 위해서 접근하고 싶은 서비스에 자신을 등록한다. callback uri를 정보를 함께 등록해야 하며, client idclient secret을 발급받게 된다. (서론에서 사용했던 예제를 가져오자면, 토스는 OAuth를 제공하는 금융사에게 자신을 client로 등록하는 과정을 거쳐야한다.)
    2. Yelp를 사용하던 중 유저가 "Connect with Google" 버튼을 클릭한다. 이 순간, client는 구글(authorization server)에 요청을 보내게 된다. 이 때 callback uriscope를 함께 보낸다. (토스가 금융사에 authorize 요청을 보낸다.)
    3. 유저는 구글이 제어하는 화면으로 이동한다. (인증이 풀려 있어서 인증이 필요하다면) 인증을 한다. (토스 사용자가 은행 또는 카드사의 앱으로 이동한다)
    4. 구글은 유저에게 Yelp가 요청한 scope에 대한 접근 권한을 허락할 것인지를 물어본다. (금융사는 토스 사용자에게 물어본다)
    5. 유저가 yes를 선택하면, Yelp가 제공한 callback uri로 다시 이동한다. 이때 query parameter 형태로 authorization code가 발급된다. (토스는 authorization code를 발급받는다. 사용자는 토스로 이동한다)
    6. Yelp는 구글(authorization server)에 요청하여 access token을 발급받는다. 이때 직전 단계에서 발급받은 authorization code와 함께 자신이 Yelp임을 증명할 수 있는 client secret을 담아서 보낸다. (토스는 금융사로부터 access token을 발급받는다)
    7. Yelp는 구글 API 서버(resource server)에 대한 요청 헤더에 이 access token을 함께 보내서 해당 유저에 대한 제한적인 접근을 한다. (토스는 사용자의 거래 히스토리를 가져와서 편리한 서비스를 제공한다)

    근데 이 과정을 유심히 본다면 누구나 궁금해할만한 점이 하나 있다. 굳이 authorization code를 발급받는 과정과 access token을 발급받는 과정을 분리해둔 이유가 뭘까? 괜히 쓸데없이 복잡해보인다. 

     

    그 이유는 보안 때문이다. access token을 가지고 있으면 허락된 scope에 대해서는 (token의 유효기간이 허락하는 한) 자유롭게 접근할 수 있기 때문에, 인가된 client가 아닌 제3자가 탈취하면 안 되는 정보이다. 그런데 위 단계 중에서 2~5 단계는 유저와 interaction을 하고 있는 환경, 즉 브라우저와 같은 front channel에서 일어난다. 만약 5단계에서 authorization code가 아니라 access token이 발급되어 버린다면 이 정보를 탈취하는 게 너무 쉽다. 유저의 정보에 대한 도용과 수정이 쉽게 일어날 수 있는 것이다.

     

    따라서 authorization code grant flow는 authorization code를 먼저 발급받은 후에, 실제 access token은 server-to-server로 발급받는 방식을 사용한다. client secret은 client와 authorization server만이 공유하는 정보이기 때문에 client secret만 안전하게 보관할 수 있다면 OAuth flow를 안전하게 수행할 수 있다. client secret을 안전하게 보관하는 것은 서버 어플리케이션에서는 어렵지 않으며, 이는 유저와의 편리한 interaction과 보안이라는 두 마리 토끼를 다 잡을 수 있는 방법이다. 위 그림에서 실선과 점선의 차이가 바로 이러한 front channel과 back channel를 구분한 것이다.

     

    우리 모두가 사용하는 구글에서도 당연히 이러한 flow에 따라 OAuth를 지원하고 있다. 내 애플리케이션에서 google API를 사용할 필요가 있다면 구글의 OAuth 가이드를 차근차근 따르면 된다. 우리가 살펴본 내용들이 잘 설명되어 있다. 

     

    OpenID Connect는 무엇인가

    OAuth를 찾아보다 보면 OpenID Connect라는 놈도 따라나온다. OpenID Connect는 기존 OAuth 2.0에서 추가적인 기능을 지원하기 위한 확장판이라고 보면 된다.  

     

    우리가 살펴본 OAuth의 핵심 기능은 인가(Authorization)이다. 하지만 모두가 다음과 같은 화면에 익숙할 것이다

    머릿속에 떠오르는 아무 서비스의 소셜 로그인 화면

     

    여기에서 밀리의 서재는 네이버 서비스에서 가지고 있는 유저의 다양한 정보에 접근하고 싶은 것이 아니다. 대다수가 네이버 아이디는 이미 있을테니 회원가입의 장벽이 낮아지고, 네이버에서 이미 잘 관리하고 있는 회원 관리 서비스에 편리하게 탑승하는 것이 목적이다. 필요한 건 이 유저가 누구인지 파악할 수 있는 최소한의 identity 정보이다. 

     

    이런 기능은 인가(Authorization)보다는 인증(Authentication)에 가깝다. 앞에서 설명했듯이 OAuth의 원래 목적은 인가이지만, 이렇게 인증의 용도로도 정말 많이 사용되게 되었다. 이러한 케이스를 보다 편리하게 지원하고 규격화하기 위한 것이 OpenID Connect이다. OpenID Connect에서는 한마디로 스스로를 "(Identity, Authentication) + OAuth 2.0 = OpenID Connect" 라고 설명하고 있다. 인증을 위한 기능과 구현 방식 등을 규격함으로써, 인증으로서의 OAuth를 제공하고 활용하고 싶은 이들의 삶을 보다 편리하게 해준 셈이다. 

     

     

    다음 번에는...

    이번 글은 OAuth에 대한 매우 일반적인 개괄이었다. 알아본 것에서 그치지 않고 직접 OAuth를 활용하는 서비스를 구현해보면 좋을 것 같다. 이 글에서 다루지 못한 내용들을 추가적으로 다뤄보면 좋겠다.

     

     

     

     

    'network, security' 카테고리의 다른 글

    server throttling을 알아보자  (0) 2022.05.01
    SameSite 설정에 대해서 알아보자  (0) 2022.01.24

    댓글

Designed by Tistory.