OAuth의 개념 및 흐름 정리

이소은·2022년 10월 10일
0

CS 기본기 잡기

목록 보기
1/1

최근에 안드로이드 프로젝트에서 Google 소셜 로그인을 구현하기 위해 찾아보던 중, OAuth에 대한 기본 흐름부터 파악할 필요를 느끼게 되었다. 이번 글에서는 OAuth 2.0 의 흐름 위주로 정리해보려 한다.



OAuth가 뭐지? 왜 쓰지?

OAuth는 (Open Authorization 2.0)으로 인증을 위한 개방형 표준 프로토콜이다.

OAuth 정의

Third-Party 프로그램에게 리소스 소유자를 대신하여 리소스 서버에서 제공하는 자원에 대한 접근 권한을 위임하는 방식

위의 OAuth에 대한 정의를 보면, 모르는 용어가 너무 많다. 리소스 소유자, 리소스 서버, 접근 권한 위임..하나하나 살펴보자.


OAuth에서 등장하는 Role
  1. 리소스 소유자 (Resource Owner): 보호된 자원에 접근할 수 있는 자격을 부여해주는 주체로, OAuth에서 클라이언트를 인증하는 역할을 수행한다. 인증이 완료되면 권한 획득 자격을 클라이언트에게 부여한다. == A 애플리케이션을 사용하는 찐 사용자
  2. 클라이언트 (Client): 보호된 자원을 사용하려고 접근 요청하는 애플리케이션, 서비스 == A 애플리케이션
  3. 리소스 서버 (Resource Server): 사용자의 보호된 자원을 호스팅하는 서버 == 네이버, 구글 등
  4. 권한 서버 (Authorization Server): 인증 & 인가를 수행하는 서버로, 클라이언트의 접근 자격을 확인하고 Access Token을 발급하는 역할을 수행

OAuth 주요 용어
  1. 인증 (Authentication): 접근 자격이 있는 지 검증
  2. 인가 (Authorization): 자원에 접근할 권한을 부여 , 인가까지 완료되면 Access Token이 클라이언트에게 부여된다.
  3. Access Token: 리소스 서버로부터 리소스 소유자의 보호된 자원을 획득할 때 사용 만료 기간이 있는 Token
  4. Refresh Token: Access Token 만료시 이를 갱신하기 위해 쓰는 Token (일반적으로 Access Token보다 만료 기간이 더 길다.)

즉, OAuth는 웹 사이트 계정 인증에 네이버, 구글 등 유명한 타 서비스의 계정을 사용하는 인증 방식이다. 다음 사진처럼 '구글 아이디로 로그인', '네이버 아이디로 로그인' 등과 같이 다양한 웹과 모바일 어플리케이션에서 OAuth 방식을 사용하고 있는걸 많이 보았을 것이다.



그럼 이런 카카오 로그인, 구글 로그인을 왜 쓸까? 사실 개발을 하다보면 가장 신경 쓸 부분이 회원가입, 로그인 쪽이다. 보안 쪽도 신경써야 하고.. 할게 너무 많다. 차라리 믿을 수 있는 큰 회사의 인증 방식을 가져다 쓰는게 사용자, 개발자에게 윈윈으로 좋을 것이다. 아무튼 이러한 이유로 OAuth를 택했다면, 이를 어떻게 구현하면 좋을 지도 고민해야 한다.

우리가 A라는 애플리케이션을 만들었고, 네이버 아이디로 로그인 하는 방식을 택했다고 하자. 그럼 사용자가 네이버 회원임을 어떻게 알 수 있을까?

가장 간단한 방법으로는 사용자의 네이버 아이디, 비밀번호를 받아서 A 애플리케이션에서 네이버에 대신 로그인을 해보면 된다. (물론 이 방식은 전혀 말이 안되는 방식이다.) 이러한 문제로 OAuth를 사용한다.

위에서도 정의를 살펴봤지만, OAuth는 A라는 애플리케이션에서 타사 서비스의 회원 정보를 보안상 안전하게 사용하기 위한 방법이다. 즉, 사용자가 자신의 네이버 계정 정보를 안전하게 A 애플리케이션에 전달해주는 방법이다. 사용자가 직접 자신의 네이버 아이디, 비밀번호를 A 애플리케이션에 알리지 않아도 네이버 계정을 A 애플리케이션이 안전하게 사용하기 위해서다!

이쯤되면 OAuth가 뭔지, 왜 필요한 지 대강 알아보았으니 큰 흐름을 순서대로 살펴보자.



OAuth 큰 흐름 알아보기

1. Access Token이 뭐지?

앞에서 OAuth 용어에서 언급한 Token이 두 가지가 있다. 그 중 Access Token이 바로 OAuth의 핵심이다. Access Token은 임의의 문자열 값으로, 이 문자열이 무엇인지는 Token을 발급해준 서비스, 여기서는 네이버만 알 수 있다. 이 Access Token을 이용해서 해당 Token과 관련된 사용자의 계정 정보를 네이버에 요청하는 것이다. 그럼 네이버는 이 Access Token을 검증하고, 올바른 Token이라면 해당 사용자의 계정을 A 애플리케이션에게 넘겨준다.


그림으로 나타내면 다음과 같다. A 애플리케이션 (우리 서비스)이 네이버에 Access Token을 넘기면, 네이버는 이 Token을 검증하고 해당 Token과 관련된 사용자의 계정 정보를 넘겨준다.



2. Access Token을 어떻게 네이버로부터 받지?

우리에게 가장 중요한 이 Access Token을 어떻게 받을 수 있을까? 네이버가 줘야 하는데.. Access Token은 사용자의 계정 정보와 관련된 문자열이니까 해당 사용자가 네이버에 로그인을 해야 네이버에서도 이 Token을 발행할 것이다.

아!! 그러면 A 애플리케이션에서 네이버 아이디로 로그인 버튼을 만들어서, 사용자가 이 버튼을 누르면 네이버 로그인 페이지로 이동시켜서 네이버에 로그인하도록 하면 되겠다!!


사용자가 네이버에 로그인을 하면, 네이버는 아이디 & 비밀번호를 통해 해당 사용자가 네이버 계정을 갖고 있음을 확인한다. 이후 이 사용자에 대해 Access Token을 발급한다. 그럼 이 Token을 어떻게 A 애플리케이션에서 받을 수 있을까?

무식하게 생각하면 네이버가 Token 문자열을 로그인 페이지에 출력해서 사용자가 이 Token 문자열을 복붙해 A 애플리케이션에 입력하는 방법이 있을 것이다. (물론 이렇게 매번 로그인 할 때 마다 Token을 사용자가 복붙하도록 하면 해당 서비스는 폭망하겠지)


사용자가 직접 Token을 복붙하지 않고 쥐도 새도 모르게 네이버로부터 Access Token을 A 애플리케이션에서 받을 수 있는 더 좋은 방법이 뭐가 있을까?


*Redirect를 이용해 볼까?

HTTP의 Status Code에는 Redirect에 대한 것이 있다. Redirect란, 서버에서 클라이언트에게 어디로 가라고 지정된 주소로 보내버리는 것이다. Redirect를 이용하면 사용자는 가만히 있는데, 웹이나 앱이 자동으로 페이지를 이동한다. 이 Redirect 방식을 이용하면 사용자가 직접 페이지를 이동하면서 Token을 복붙할 필요가 없어진다.

다시 정리하면,

  1. A 애플리케이션에서 '네이버 아이디로 로그인' 버튼을 만듦 =>

  2. 사용자가 해당 버튼 클릭 =>

  3. 네이버 로그인 페이지로 이동 =>

  4. 사용자가 로그인 =>

  5. 네이버가 로그인 정보를 확인 후 사용자에게 Access Token을 발급 =>

  6. 네이버가 A 애플리케이션으로 Redirect 시켜줌 =>

  7. 사용자는 가만히 있는데 다시 A 애플리케이션으로 넘어옴!

    이때 5번 단계에서 Access Token을 6번 과정의 URL에 묶어서 query string으로 주면 된다. 근데.. 네이버가 Redirect 할 대상인 A 애플리케이션은 어떻게 알지? 바로 앞에서 네이버가 A에게 줄 Access Token을 URL로 보낸 것처럼, 우리가 1번 단계에서 네이버에게 Redirect할 URL을 qurey string으로 제공해 주면 되지 않을까?


자 위에서 정리한걸 다시 정리해보자!!

  1. A 애플리케이션에서 '네이버 아이디로 로그인' 버튼을 만듦 =>

  2. 사용자가 해당 버튼 클릭 =>

  3. 네이버 로그인 페이지로 이동 + 네이버 로그인 페이지로 이동시 Redirect_uri를 query string으로 제공 =>

  4. 사용자가 로그인 =>

  5. 네이버가 로그인 정보를 확인 후 Access Token을 발급 =>

  6. 네이버가 A 애플리케이션으로 Redirect 시켜줌 + A 애플리케이션으로 이동 시 Access Token을 query string으로 제공 =>

  7. 사용자는 가만히 있는데 Access Token을 가진채 다시 A 애플리케이션으로 넘어옴!


[네이버 소셜로그인 시 Redirect_URI를 건내는 예시 사진 - 3번 단계에 해당]


단, 이 방식을 사용하면 XSS 공격, 피싱 등 해커가 Redirect_URI를 자기가 원하는 사이트로 바꿔버리면 사용자의 Access Token을 갈취할 수 있다 ㅠㅠ 따라서 이를 방지하기 위해, A 애플리케이션 등 각 클라이언트는 OAuth를 사용하기 위해 네이버 (OAuth 제공할 주체 == 리소스 서버)에 등록 절차를 밟아야 한다. 네이버의 로그인 기능을 사용하겠다고 등록하는 과정에서 Redirect_URI도 사전에 등록하여, 약속된 Redirect_URI가 아니라 다른 피싱 사이트 URI에서 네이버에 로그인 페이지를 요청하면, 네이버가 이상함을 감지하고 로그인 페이지로 보내지 않을 것이다.


3. 네이버로부터 받은 Access Token을 어떻게 다시 네이버에게 주지?

아..드디어 Access Token을 네이버로부터 받았다!!! 그러면 이제 이 Access Token을 다시 네이버에게 주고 사용자의 계정 정보를 최종적으로 받아야 한다. 그러면 네이버에게 이 Access Token을 어떻게 줄까?


네이버 로그인을 사용할 경우, 네이버에게 Access Token을 전달하는 API가 다음 그림과 같이 존재한다.



이 API를 이용해서 네이버에게 Access Token을 넘겨주면 네이버는 해당 사용자의 계정 정보를 돌려준다.


4. 서비스 보면 자동 로그인을 유지하는 경우가 많던데.. 매번 앱을 쓸 때마다 로그인을 해야 하나? 사용자가 너무 귀찮아하지 않을까? => Refresh Token을 사용하자

Access Token은 정의에도 나와있듯이, 일정 기간이 지나면 만료가 되어 새로 Token을 발급받기 위해 사용자가 다시 로그인을 해야 하는 불편함이 있다. 이를 해결하고 로그인을 보다 오래 유지하기 위해 Refresh Token이 있다. (Access Token의 유효기간이 보통 몇 시간이라고 하면, Refresh Token은 이보다 더 길다.)


만약, Access Token의 사용 기간이 만료되면, Client (A 애플리케이션)가 갖고 있는 Refresh TokenAuthorization Server (네이버, 구글 등)에게 보낸다. 그러면 Authorization Server가 새로운 Access Token, 혹은 Refresh Token을 제공하여 로그인을 유지시켜준다. (Refresh Token의 사용 기간도 만료된다면, 사용자는 새로 로그인을 해야하며 Refresh Token도 탈취될 가능성이 있기 때문에 보통 2주 정도의 유효기간을 설정한다.)


위와 같은 과정을 거치면 A 애플리케이션인 Client에서도 Refresh Token을 회원 DB에 저장해두다가, Access Token이 만료되면 Authorization Server에게 저장하고 있던 Refresh Token을 보낸다. Authorization Server도 저장하고 있던 Refresh Token과 HTTP 요청으로 받은 Refresh Token을 비교해서 Token이 서로 동일하고 유효 기간이 지나지 않았다면 새로 Access Token을 발급해 준다.



OAuth 최종 정리

최종적으로 정리를 하자면, OAuth를 사용하기 위해선 다음의 순서를 거쳐야 한다.

  1. OAuth를 제공해 줄 주체 (네이버, 구글, 카카오 등)에 자사 서비스 (A 애플리케이션) 등록하기

    => 이때, Redirect_URI를 사전에 등록한다.

    => 주체에 따라 Client Id비밀번호 등 다른 정보를 A 애플리케이션에 줄 수도 있다. (Redirect URI 줄 때 같이 줘야 함)

  2. Access Token을 네이버로부터 받기

    => 사용자를 A 애플리케이션에서 네이버 로그인 페이지로 이동시킨 후 (Redirect URI를 네이버에게 같이 제공), 사용자가 네이버 로그인을 성공적으로 마치면 Redirect를 통해 다시 A 애플리케이션으로 돌아온다. 이때 네이버로부터 Access Token을 받아온다.

  3. 네이버에게 Access Token 주고 사용자의 계정 정보 받기

    => 네이버의 OAuth API 를 이용해 Access Token을 전달 후, 해당 사용자에 대한 계정 정보를 돌려 받는다.

  4. Access Token의 유효 기간이 너무 짧아 생기는 불편을 최소화 하기 위해 Refresh Token을 같이 활용


[전 과정을 그림으로 나타내면 다음과 같다.]

[그림 출처: https://velog.io/@piecemaker/OAuth2-%EC%9D%B8%EC%A6%9D-%EB%B0%A9%EC%8B%9D%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90]


큰 흐름은 다음과 같으나, 어떤 서비스를 사용하느냐에 따라 상세 구현은 달라질 수 있다. 하지만 OAuth는 표준이므로 웬만해선 큰 흐름은 비슷하다고 한다!

다양한 블로그와 사이트를 참고해 OAuth 개념 및 흐름을 정리 했는데, 다음에는 구글 OAuth를 안드로이드와 스프링부트에서 사용하는 법을 정리해 볼 예정이다.



Reference

profile
안드로이드 개발자

0개의 댓글