- 본 글은 생활코딩님의 [WEB2 - OAuth 2.0] 강의를 바탕으로 작성되었습니다.
📝 OAuth 2.0이란?
- OAuth 2.0에 대해 본격적으로 알아보기 전에 먼저 한 가지 예를 들어보겠습니다.
- 우선 나의 서비스
opentutorials.org
가 있다고 가정해봅시다(mine
). - 그리고 이 서비스를 사용하는 사용자가 있을 것입니다(
User
). - 또 하나는 나의 서비스가 연동하려는 '그들의' 서비스가 있을 것입니다(
Their
). 예를 들면 Google, FaceBook, Twitter 등이 있습니다. - 위 상태에서 우리는 사용자(
User
)가 우리 서비스(mine
)에 접속해서 글을 썻다거나 어떤 글을 보았다고 한다면 나의 서비스가 사용자를 대신해서 Google Calendar에 날짜를 기록한다거나 페이스북에 '글을 썻다', '글을 봤다'라는 사실을 공유하는 작업을 수행하고자 할 수도 있을 것입니다.
- 이를 위해서는 우리가 사용자(
User
)로부터 사용자가 사용하고 있는 그들의 서비스(Their
)에 접근할 수 있도록 허가를 받아야할 것입니다. 가장 쉬운 방법은 우리 서비스에서 사용자로부터ID
와Password
를 전달받아 저장하고 있다가, 실제로 그들의 서비스에 접근할 때 이를 사용하는 방법일 것입니다. 이는 아주 간단하고 그들의 서비스의 모든 기능을 사용할 수 있는 강력한 방법입니다. 하지만 반대로 상당히 위험한 방법이기도 합니다. - 사용자의 입장에서는 자신의 구글, 페이스북과 같은 서비스의 아이디와 비밀번호를 처음보는 서비스에 맡겨야하기 때문에 신뢰성의 문제가 생기게 됩니다. 심지어는 많은 사용자들이 우리 서비스에만 사용하는 것이 아니라 자신이 사용하는 거의 모든 서비스에 공통된 아이디와 비밀번호를 사용하기 때문에 이는 더욱 큰 문제를 야기하게 됩니다.
- 바로 이러한 상황에서 우리를 구원해줄 도구가 바로 OAuth입니다.
- OAuth를 사용하면 위와 같은 방법보다 훨씬 더 안전하게 우리가 만든 서비스를 그들의 서비스와 상호작용할 수 있게 됩니다.
- 이전에는 우리가 그들의 서비스(
Their
)에 있는 사용자(User
)ID
와Password
를 나의 서비스(mine
)에 저장하고 있었지만 OAuth는 그 대신에 사용자의 요청에 의해서 그들의 서비스가ID
,Password
가 아닌accessToken
이라고 하는 일종의 비밀번호를 발급합니다. - 이
accessToken
은 그들의 서비스의ID
와Password
가 아니며 그들의 서비스가 가지고 있는 모든 기능이 아닌 나의 서비스가 꼭 필요한 기능만 부분적으로 허용하는 비밀번호입니다. - 따라서 우리의 서비스는 이러한
accessToken
을 획득한 후 그것을 통해서 그들의 서비스에 접근하여 데이터를 가져오거나 수정하거나 삭제하는 작업을 할 수 있게 되는 것입니다.
- OAuth의 이러한 특징을 활용한다면 나의 서비스를 이용하는 회원들의
ID
와Password
를 처음부터 보관하지 않고도 회원을 식별할 수 있는 기능을 구현해낼 수 있습니다. - 위와 같은 로그인 버튼을 보신적이 있으실 텐데 이를 Federated Identity라고 하며 이것의 가장 기반이 되는 기술이 바로 OAuth입니다.
📝 OAuth 2.0 구분
- OAuth에는 크게 3개의 주체가 있습니다.
- 우선 위에서는 우리가 만든 서비스를
mine
, 우리의 사용자를User
, 그리고 이User
가 사용하는 그들의 서비스를Their
라고 표현했습니다.
- 이를 OAuth에서는 각각 우리가 제어하고자하는 자원을 갖고 있다는 뜻의
Resource Server
(Their
), 자원의 소유자라는 뜻의Resource Owner
(User
),Resource Server
에 접속해서 자원을 가져가는 클라이언트라는 뜻으로Client
(mine
)라고 부르며, 이 삼자간의 관계가 OAuth의 핵심이라고 볼 수 있습니다.
OAuth의 공식 메뉴얼을 보면 Authorization Server라는 주체가 추가로 있는 것을 확인할 수 있는데, Resource Server는 데이터를 가지고 있는 서버라면 Authorization Server는 인증과 관련된 처리를 전담하는 서버이고 공식 메뉴얼에서는 이 두 가지를 구분해서 설명하고 있지만 여기서는 그냥 이를 합쳐 Resource Server라고 설명하였습니다.
📝 OAuth 2.0 등록
Client
가Resource Server
를 이용하기 위해서는Resource Server
의 승인을 사전에 받아놓아야 하며 이를 등록(register)이라고 합니다.- 등록하는 방법은 서비스마다 조금씩 다르지만 공통적으로 아래와 같은 형식을 따르고 있습니다.
Client ID
는 우리가 만들고 있는 어플리케이션을 식별하는 식별자의 역할을 하며,Client Secret
은 이에 대한 비밀번호를 의미합니다.Client ID
는 외부에 노출되어도 괜찮으나Cilent Secret
의 경우 절대로 외부에 노출되지 말아야합니다. 다음으로Authorized redirect URIs
는Resource Server
가 우리에게 권한을 부여하는 과정에서authorize code
라는 값을 전달해주게 되는데 이때의 전달 경로를 의미합니다.- 아래는 카카오톡 서비스 등록의 예입니다.
📝 Resource Owner의 승인
- 우리의 서비스가 위 과정을 거쳐서 등록(register)을 하게 되면
Resource Server
와Client
는Client ID
와Client Secret
,Redirect URI
이라는 세 가지 핵심 정보를 공유하게 됩니다. 참고로Client
의 경우Redirect URI
에 해당되는 페이지를 구현해놓아야 할 것입니다.
- 여기서 하나만 더 짚고 가자면
Resource Server
가 가지고 있는 기능이 예를 들어 A, B, C, D 4가지라고 가정했을 때,Client
가Resource Server
의 모든 기능이 필요한 것이 아니라 B와 C에 해당되는 두 개의 기능만이 필요하다면 모든 기능에 대해서 인증을 받는 것이 아니라 최소한의 기능에 대해서만 인증 받는게 훨씬 효율적일 것입니다. - 만약
Resource Owner
가 우리의 서비스에 접속해서Resource Server
를 사용해야하는 상황이 발생한다면Client
는Resource Owner
에게 아래와 같은 화면을 보여주게 될 것입니다. 또는 사용자의 동의를 구하기 위한 메시지를 띄워줄 수도 있습니다.
- 뭐가 됐던간에 사용자가 동의를 해야만 그 다음 과정으로 진행할 수 있을 것입니다. 사용자가 위와 같은 버튼들을 클릭한다는 것은 그 동의를 받아내는 것과 마찬가지겠죠. 위 버튼들은 별거 없이 클릭 시 특정 링크를 타도록 구현해주면 됩니다.
- 링크를 자세히 보면
Client ID
값과 우리가 사용하고자 하는 기능 그리고Redirect URI
의 값을 제공하고 있는 걸 알 수 있습니다. Resource Owner
가 위 주소를 통해Resource Server
로 접근하게 되면Resource Server
는Resource Owner
가 현재 로그인 되어 있는지를 파악하여 로그인이 되어 있지 않으면 아래와 같이 로그인을 위한 페이지를 띄워줍니다.
- 이후
Resource Owner
가 로그인에 성공했다면Resource Server
는 그때서야 링크에서 제공하고 있는Client ID
값과Redirect URI
값을Resource Server
에 저장되어 있는Client ID
값과Redirect URI
값과 비교하여, 같다면Resource Owner
에게 링크의scope
에 해당되는 권한을Client
에게 부여할 것인지를 확인하는 메시지를 아래와 같이 띄워줍니다.
- 여기서 사용자가 허용(Allow) 버튼을 누르게 되면 '허용한다'라는 정보가
Resource Server
로 전송되고,Resource Server
는 해당 사용자가 특정 기능에 대한 작업을 허용하는 것에 동의하였다는 정보를 서버에 저장합니다.
- 여기까지가
Client
에서 사용자로부터Resource Server
에 접근하는데에 동의를 구하는 절차입니다.
📝 Resource Server의 승인
Resource Owner
에 대한 승인을 획득했으니 이번에는Resource Server
의 승인을 받아야합니다.Resource Server
는accessToken
을 바로 발급하는 것이 아니라 절차를 하나 더 수행합니다. 이때 사용하는 임시 비밀번호를authorization code
라고 합니다.
Resource Server
는 이authorization code
를 링크의 형태로Resource Owner
에게 전송합니다. 이는Resource Server
가Resource Owner
에게 위와 같은 주소로 이동하라고 명령한 것이라고 말할 수 있습니다.
- 그러면
Resouce Owner
의 웹 브라우저는 위의 Location Header 값에 의해서 사용자가 의식하지도 못한 찰나에 위 주소로 이동하게 됩니다. 그러면 위 주소의code
라는 값에 의해서Client
역시authorization code
를 가지게 됩니다. - 여기까지
Client
가Resouce Server
에게 응답해서accessToken
을 발급하기 바로 전 단계까지 도달했습니다. - 이제
Client
는Resouce Owner
를 통하지 않고Resource Server
에게 다음과 같은 주소로 직접 접근합니다.
- 그럼
Resource Server
는 링크에 포함되어 있는code
값을 확인하여authorization code
값이 3인 경우의Client ID
와Client Secret
그리고Redirect URI
값이 완전히 일치하는지 확인하고, 만약 모두 일치한다면 그때 다음 단계를 진행하게 됩니다. 그럼 그 다음 단계는 당연히accessToken
을 발급하는 단계가 될 것입니다.
📝 accessToken 발급
Resouce Server
의 승인까지 받았다면 이제 드디어accessToken
을 발급받을 때입니다.
authorization code
를 통해 인증을 마쳤기 때문에 이제Resource Server
와Client
는 이 값을 지우게 되고, 이 자리를accessToken
이 채우게 됩니다.Resource Server
는accessToken
을 생성하여Client
에게 전송하고Client
역시 이 값을 가지게 됩니다.- 해당
accessToken
은 기능 B와 C에 대한 작업 권한이 열려있는 user_id가 1인 사용자에 대한 접근을 허락하는 역할을 수행하게 됩니다.
- 이러한
accessToken
을 활용해서Resource Server
의 데이터를 조작하기 위해서는 우리 마음대로 할 수 있는 것이 아니라Resource Server
가Client
들에게 제공한 사용법을 따라야 합니다. 이러한 사용법을 우리는 API(Application Programming Interface)라고 부릅니다. - 즉, API는
Client
가Resource Server
를 호출해서 데이터를 조작하려 할 때, 그 접점에 있는 일종의 조작장치라고 말할 수 있습니다. - 아래는 Google Calender API의 일부입니다.
📝 refreshToken
accessToken
에는 일반적으로 수명이 있습니다. 수명이 끝나게 되면 더 이상 API에 접속해도 데이터를 받지 못하게 됩니다.- 그렇다면
accessToken
을 다시 발급받기 위해 사용자에게 위 과정을 다시 수행하도록 요구해야 할까요? 몰론 이를 필수로 하는 시스템도 있지만 이럴 경우 손쉽게 다시accessToken
을 발급받을 수 있도록 하는 방법이 바로refreshToken
입니다. - OAuth 2.0 표준 문서(https://www.rfc-editor.org/rfc/rfc6749#section-1.5)를 살펴보면 아래와 같은 페이지를 찾을 수 있습니다.
- 즉, 처음
accessToken
을 발급받을 때refreshToken
도 함께 발급받게 되는데,accessToken
의 수명이 다하면 이refreshToken
을Authorization Server
에게 전달함으로써accessToken
을 재발급 받을 수 있다는 것을 알 수 있습니다. 참고로accessToken
이 재발급됨에 따라refreshToken
도 갱신되는 경우도 있고 그렇지 않은 경우도 있습니다.
'🥑 Web Technoloy' 카테고리의 다른 글
Lombok이란? (1) | 2023.06.04 |
---|---|
Spring AOP(Aspect Oriented Programming) (0) | 2023.06.03 |
SpringBoot에서 SMTP를 활용한 메일 전송 구현하기 (0) | 2022.11.16 |
Spring Interceptor 개념 정리, 적용법 (0) | 2022.11.15 |
스프링 부트 Spring Security (0) | 2022.11.10 |