관리 메뉴

솔트펀 티스토리

OAuth 2.0 본문

WEB DEVELOPMENT/Web Dev

OAuth 2.0

SALTFUN 2020. 2. 5. 10:58

https://opentutorials.org/course/3405

0. INTRO

사용자가 가입된 서비스의 API에 접근하기 위해서는 사용자로부터 권한을 위임 받아야 한다. 이 때 사용자의 패스워드 없이도 권한을 위임 받을 수 있는 방법이 필요하다. 이를 위해서 고안된 기술이 OAuth입니다. 오늘날 많은 API들이 OAuth를 통해서 상호 연동을 지원하고 있다.

구글, 페이스북과 같은 서비스의 API에 사용자 대신에 접근하기 위해 반드시 필요한 기술이다. 또 아래 그림과 같이 다른 서비스로 로그인 하기 기능을 구현하는데도 필수적으로 필요한 기능이다.

Fig 1

OAuth 2.0 Youtube 재생목록

https://www.youtube.com/playlist?list=PLuHgQVnccGMA4guyznDlykFJh28_R08Q-

참고

또 OAuth는 애플리케이션 기술(PHP, Python, Ruby, JavaScript, Node.js, Java..)을 이용하기 때문에 이런 기술에 대한 이해가 필요하다. 

https://cg-developer.tistory.com/361

 

OAuth는 Open Authorization, Open Authentication 뜻으로 오픈 스탠다드 프로토콜을 말하는데, OAuth 2.0은 다양한 플랫폼 환경에서 권한 부여를 위한 산업 표준 프로토콜이다. 플리케이션(페이스북,구글,트위터등- Service Provider)의 유저의 비밀번호를 나의 서비스에 제공 없이 사용자 인증,인가를 할 수 있는 기술 이다.  또는 제 3의 앱이 자원의 소유자인 서비스 이용자를 대신하여 서비스를 요청할 수 있도록 자원 접근 권한을 위임하는 방법이다.

OAuth 2.0은 페이스북이나 구글의 아이디로 제 3의 서비스에 로그인해서 등록되어 있는 정보(친구목록)나 기능(담벼락 글쓰기)에 접근할 수 있는 권한을 제어하기 위한 표준 프로토콜이다.

OAuth라는 기술과 관련 3명의 참여자

- Mine  = 나의 서비스
- User  = 사용자(나의 서비스를 사용하는자 )
- Their (나의 서비스가 연동하려고 하는 그들의 서비스) 구글, 페이스북, 트위터

 

Fig 2

OAuth라는 기술이 나오게 된 배경

나의 서비스가 사용자를 대신해서 사용자가 가입한 구글과 같은 서비스의 API에 접근하여 CRUD를 하고싶다면 사용자로부터 구글의 서비스에 접근할수 있도록 허가를 받아야 한다. 가장 쉬운 방법은 사용자로부터 아이디와 비밀번호를 받아서 우리가 기억하고있다가 그들의 서비스에 접속할때 아이디와 비밀번호를 이용하는것이다. 하지만 보안상 여러가지로 상당히 위험하다.

사용자의 아이디, 패스워드 없이도 권한을 위임 받을 수 있는 방법이 필요하다. 그래서 이러한 문제점에서 OAuth라는 기술이 고안 되었다. OAuth기술을 사용해 훨씬 더 안전한 방법으로 그들의 서비스와, 나의 서비스가 상호작용 할수 있는것이다. 

OAuth기술의 핵심 요약

OAuth 를 통해서 나의 서비스가 accessToken을 얻어낼수있다는게 가장 핵심이다.

 

Fig 3

 

 

1) 유저의 요청에 의해서 그들의 서비스가 accessToken을 나의 서비스에 발급해준다. accessToken은 그들의 서비스의 비밀번호와 아이디가 아닌 장점을 가지면서도 역할을 대신해주는것으로 볼 수 있다.
accessToken은 그들의 서비스가 가지고 있는 모든 기능이 아니라 그중에 나의 서비스가 로 하는 기능만 부분적으로 허용하는 것이다.

2) accessToken을 통해서 그들의 서비스에 접근해서 데이터를 CRUD할수 있는것이다.  

이러한 기술을 Federated Identity라고 하는데 그 가장 기반에 있는  것이 OAuth이다.

TOP

1. 역할

OAuth라는 기술과 관련한 3자 관계 재정의

 

 

Fig 4

 

- Resource server : 나의 서비스가 제어하고자 하는 자원, 데이터를 가지고 있는 서버라는뜻
(이름, 나이 등 아이디 관련 정보를 제공하는 서버, 구글,페이스북등)

- Authorization Server :  인증과 관련된 처리를 전담하는 서버이고
(로그인을 통해 인증 후 권한을 부여하는 서버. 구글, 페이스북 등). 공식 매뉴얼에서는 Resource Server와 Authorization Server를 구분하는데 여기서는 그냥 모두 Resource Server 로 본다. 

- Resource Owner : 자원의 소유자를 뜻 한다. 즉 나의 서비스를 이용하려고 하는 일반사용자

Client : Resource server에 접속해서 정보를 가져가는자. 서비슬 제공하려고 하는 "나"다. 내가 사용자에게 서비스를 제공하며 이때 인증서비스를 받으려고 하기 때문에 Client 가 된다. 

TOP

2. 등록

OAuth를 이용해서 Resource Server에 접속하기 위해서는 우선 Resource Server에 등록하는 과정이 필요하다.

Fig 5

Client가 Resource Server를 이용하기 위해서는 Resource Server의 승인을 사전에 받아 놓아야 하는데 그것이 등록 register이다.

  서비스 마다 등록하는 방법이 다 다르지만, Client ID, Client Secret, Authorized redirect URIs 의 세가지 요소는 공통적으로 가진다.

.Client ID: 우리가 만들고 있는 애플리케이션을 식별하는 ID, 식별자.  외부에 노출됨
Client Secret: Client ID 에 대한 비밀 번호. 절대로 노출되면 안된다. 엄청난 보안사고가 일어날 수 있다.
Authorized redirect URIs: Resource Server가 권한을 부여하는 과정에서 우리에게 Authorized Code 값을 전달해주는데 어느 주소로 전달 받을지를 지정하는 값. 리소스 서버는   지정된 주소가 아닌 곳으로부터의 요청을 무시할 것이다. 

Tistory에서도 이 서비스를 제공한다. Facebook 개발자페이지를 통해 실천의 예시를 살펴보자.

Fig 6

https://developers.facebook.com :facebook 개발자 페이지

Fig 7
Fig 8
Fig 9

이제 Facebook Login을 Set Up 하면 다음 화면이 뜬다.

Fig 10

그리고 Web을 하려고 한다면 Web을 클릭한다.

Fig 11
Fig 12

Facebook Login/Settings 에서 Redirect URI to Check 에 URI를 입력하고 확인 후 저장한다.

Fig 13

Settings를 보면 App ID 와 App Secret 가 있다.

구글도 한 번 훑어보자.

Google Cloud Platform 에서 앱을 만드는데,  Select a Project/New Project에서 Project Name을  설정한다.

Fig 14

그러면 Project가 생성되고 이제 다시 project를 선택한다. 

Fig 15

여기서 우리가 원하는 것은 API를 제어하는 것이다. 그러기 위해서는 제어할 수 있는 자격을 얻어야 하는데 구글에서는 Credentials에서 진행한다.

Fig 16

Consent Screen 설정

Fig 17

이제 우리가 서비스할 애플리케이션 타입을 설정한다.

Fig 18
Fig 19
Fig 20

TOP

3. Resouce Owner의 승인

등록을 마치면 Resource Server와 Client는 Client ID, Client Secret, Redirect URI 라는 3가지 핵심적인 정보를 동시에 갖게 된다. Client는 Redirect URI에 해당하는 페이지를 구현해놓고 준비해두고 있어야 한다. 

먼저 한가지 내용을 짚고 가자. Resource Server 가 가지고 있는 기능이 A, B, C, D 4개 라면 Client가 Resource Server의 모든 기능이 다 필요한 것이 아니라 그 중 B, C에 해당되는 2개의 기능만 필요한 경우, 모든 기능에 대해 인증을 받는 것이 아니라 최소한의 기능에 대해서만 훨씬 용이하고 안전하다. 

Resource Owner 즉 user가 우리의 서버에 접속을 하면 우리가 Resource Server를 사용해야 하는 상황이 생길 수 있다. 예를 들어 Facebook에 글을 게시한다든지, Google Calendar에 날짜를 기록한다든지 등의 작업을 해야 한다면 우리는 Resource Owner에게 이런 화면을 보여주게 된다. 

Fig 22. user 즉 Client 에게 다른 사이트 계정을 이용하여 로그인하도록 하는 화면

"지금 귀하께서 하시려고 하는 일은 페이스북의 ... 기능이 필요한데 그 기능을 쓰기 위해서는 하기 때문에 인증을 거쳐야 합니다"라는 메세지와 함께.

Fig 23

어찌됐든 사용자의 동의를 해야만 다음 과정으로 넘어가게 될 것이다. 위 그림의 버튼을 클릭했다는 것은 사용자가 동의를 했다는 의미인데 저 버튼은 이런 링크를 가지고 있다.

버튼이 가지고 있는 링크

인자로서 Client ID, 사용하려는 서비스 B와 C,  redirect uri 값이다. 실제로 저런 버튼의 링크를 보면 이렇다.

Resource Owner는 버튼을 클릭하여 저 주소, 즉 Resource Server로 가게 되며, 이때 Resource Server 는 로그인 하도록 한다. 로그인이 되면 Resource Server는 Resource Owner가 보낸 URI에 있는 Client ID 가 있는 지를 확인하고, 계속해서 자신에게 등록되어 있는 redirect uri 와 저 주소의 redirect uri가 같은지를 또 확인하고 다르면 그냥 끝내버린다. 확인 되면 Resource Owner에게 scope에 해당되는 권한을 Client에게 부여할 것인지를 확인하는 메세지를 보낸다.

Fig 24

사용자가 동의하면 Resource Server는 user id가 scope 에 해당하는 작업을 허용하는 것에 동의하였다는 정보를 가지게 된다. 

url을 보기 쉽게 decoding 도구: https://urldecode.org

TOP

4. Resouce Server의 승인

OAuth 2.0의 총 6 가지 인증 방식(grant type)

인증 Grant Type이란 Client가 액세스토큰을 발급받기 위한 플로우라고 보면 된다

1) Authorization Code Grant (인가 코드 그랜트 타입)

OAuth2.0 Grant Type에서 가장 잘 알려진 인가 코드 그랜트 타입은 중요한 보안 이점을 제공하는 방법이다. 일반적인 웹사이트에서 소셜로그인과 같은 인증을 받을 때 가장 많이 쓰는 방식으로 기본적으로 지원하고 있는 방식이다. 클라이언트는 토큰을 발급 받기 전에 인증 코드라는 것을 사전에 리소스 소유자에 의해서 받게 되고 그 인증코드(권한 부여코드)를 가지고 인증서버에 요청을 보내야 토큰을 발급받을 수 있다. 

2) Implicit Grant (암시적 그랜트 타입)

암시적 그랜트 타입은 서버가 없는 단순 웹 브라우저에서 직접 실행되는 자바스크립트 웹 애플리케이션 클라이언트에게 적당한 권한 부여 방법이다. 별다른 인증방법없이 클라이언트가 요청을 보내면 리소스 소유자의 Authentication(+사용자 동의 과정) 과정만 거치고 바로 토큰을 발급해준다. 이 그랜트 타입은 클라이언트가 토큰을 안전하게 보관할 방법이 없기때문에 리프레시 토큰을 발급해주지 않는다.

3) Resource Owner Password Credentials Grant 

Client에 아이디/패스워드를 받아 아이디/패스워드로 직접 access token을 받아오는 방식이다. Client가 신용이 없을 때에는 사용하기에 위험하다는 단점이 있다. 클라이언트가 확실한 신용이 보장될 때 사용할 수 있는 방식이다.

4) Client Credentials Grant 

5) Device Code Grant 

6) Refresh Token Grant

Resource Server 는 Access token을 발급하기 전에 한 가지 절차를 더 진행한다. 이때 사용하는 임시비밀번호가 Authorization Code이다. Resource Server 는 Resource Owner에게 아래 그림의 ①과 같은 식으로  Authorization Code를 전송한다.

Fig 25

응답할때 Header 값으로 location을 줘서 저 주소로 이동하도록 명령하는 것이다. Resouce Server가 Resouce owner의 웹브라우저에게 https://client/callback?code=3  로 이동하도록 한 것. 이 주소를 살펴보면 인자값으로 code=3 을 주고 있는데 여기서 이 3이 바로 Authorization code이다.

이에 따라 Resource owner의 웹브라우저는  사용자[즉 Resource owner]가 인식하지 못하도록 은밀하게 location 헤더 값 주소로 이동하게 된다. 그리하여 Client는 Authorization code 의 값 3을 얻게 된다. 이것이 Client가 Resouce Server로부트 Access token을 발급받기 전 단계이다.

이제 클라이언트는 리로스오너를 통하지않고 리소스 서버에 직접 접속한다. 아래 그림과 같이 https://resouce.server/token?grant_type=authorization_code&code=3&redirect_uri=https:client/callback&client_secret=2 이라는 주소를 사용하여 접속하는데 여기서 grant_type 은 이 authorization code 방식을 지정하고 있는데 이 방식 외에도 4가지 방식이 더 있다. 

Fig 26

authorization code와 함께 client_secret 값도 전송하게 되는데, Resource Server는 이 두 개의 비밀정보와 redirection uri를 결합하여  확인과정을 거친다. 

TOP

5. Access token

드이어 Access Token을 발급받게 되었다. 이제는 authorization code의 역할이 끝났기 때문에 Client 와 Resource Server 모두 authorization code 값을 지워버린다.  

 

 

Fig 27

 

리소스 서버는 Access Token을 발급하고 클라이언트에게 응답하면,  클라이언트는 access token을 db나 파일 등에 내부적으로 저장하게 된다. access token을 가지고 리소스 서버에 접근하면 리소스 서버는 access token을 보고서 userid 1번에 해당하는 사용자의 기능 b,c에 대해 허용해주는것다.

TOP

6. API 호출

이제 Access Token을 활용하여 Resource Server를 handling 조작하기 위해서는, Resouce Server가 Client에게 알려 주는 방식을 지켜야 하는데, 이 방식이 API Application Programming Interface 라는 것이다.

Fig 28

실제 API의 모습을 한 번 살펴보자. 예를 들어 구글 캘린더를 Resource Server로 하여 그것을 제어하고 싶다면 이때 검색어는 마땅히 google calendar api 가 되어야 할 것이다.

Fig 29

저 링크로 접속하여 Reference 참조 를 보면 Acl, CalendarList, Calendars, Channels, Colors, Events, Freebusy, Settings 등 여러 개의 Resource types 이 있는데 여기서 CalendarList가 필요하다고 한다면

Fig 30

그림에 표시된 저 부분의 주소를 베이스로 하여, list를 GET 하고 싶다면

Fig 31

저 주소를 결합하여 전체 주소를 완성한다. 이제 이 주소를 주소창에 입력해보자.

Fig 32

이 주소가 바로 구글 캘린더의 리스트를 보여주는 API가 되는 것이다. 접속해보면 이런 결과를 볼 수 있다.

Fig 33

로그인이 되어 있지 않기 때문에 Login Required 가 있는 것을 보고 이 API는 인증이 필요하다고 판단할 수 있는데, 바로 OAuth를 통해, 즉 Access Token을 통해야만 저기의 데이터를 제대로 가져올 수 있는 것이다.

실제 Access Token을 가져오는 방법은 각각의 애플리케이션에서 해야 하는데 여기서 그 부분을 다루지는 않는다.

google api access token oauth  라고 구글링 해보자.

Fig 34

https://developers.google.com/identity/protocols/OAuth2WebServer 의 웹페이지를 열어보면,

Fig 35

많은 내용들이 들어 있는데 Client libraries를 쓸 수 있는 언어 별로 정리된 내용들도 있고,

Fig 36

기타 여러 가지 내용들이 있는데, 이 중에서 Calling Google APIs 부분을 보면

Fig 37

두 가지 방법이 있는데, 하나는 access_token을 query parameter로 보내는 방법과, Authorizaiotn: Bearer를 HTTP header로 전송하는 방법인데 이 중에서 HTTP header 가 더 선호된다[안전하다] 고 설명하고 있다. access_token을 사용하는 방법은 파랑색으로 표시하였다. 앞에서 CalendarList의 캘린더 list를 GET하는 API를 완성하려면 Fig 32의 주소뒤에 access_token을 붙여줘야 하는데 실제 access_token은 이런 모양이다.

Fig 38

그리고 이걸 이용하여 접속했을 때에는 제대로 데이터를 받게 된다.

Fig 39. 앞의 그림처럼 완성한 URI로 접속한 결과

이것은 Client가 가지고 있는 캘린더들의 목록이다. 예제용으로 만든 것이기 때문에 내용이 많지는 않다. 

이것이 첫 번째 방법인데 이 방법은 제공하지 않는 경우도 많다. 

좀 더 선호되는 방법인 헤더값으로 Authorization: Bearer <access_token>을 전송하는 방법의 경우는 curl 이라는 프로그램을 이용하면 쉽게 볼 수 있다.

Fig 40
Fig 41

curl 은 해당 주소에서 받은 코드를 살펴보는 프로그램이라고 할 수 있다. 

콘솔에서 실행시키면 좀 더 안전하게 결과를 가져올 수 있는 것을 확인할 수 있다. 

Fig 42

앞에서 본 query parameter 방식은 제공하지 않을 수도 있기 때문에 매뉴얼을 확인하여야 하며, 이 Authorization Bearer 에 의한 방법은 어디서나 제공하는 표준화된 방식이고 좀 더 안전하고 선호되는 방식이다.

TOP

7. Refresh token

Access token은 수명이 있습니다. Access token의 수명이 다했을 때 새로운 access token을 발급 받는 방법이 refresh token이다. access token은 일반적으로 1~2시간 정도의 수명이 있고, 수명이 긴 경우에는 60일, 90일 이나 되는 경우도 있다.

Access token의 수명이 다했을 때 api로 접근하면 더 이상 데이터를 주지 않는다. 그러면 access token을 다시 발급받아야 하고 이때 또다시 사용자와 확인•동의 과정을 거치는 것은 번거로운 일이고, 이것을 필수로 하게 하는 시스템도 있긴 하지만, 이러한 경우에 새로 access token을 쉽게 발급받을 수 있는 방법이 바로 refresh token이다.

검색어: oauth 2.0 rfc          * RFC: 인터넷과 관련된 여러 가지 표준들. Request For Comments 컴퓨터 네트워크 공학 등에서 인터넷 기술에 적용 가능한 새로운 연구, 혁신, 기법 등을 아우르는 메모

Fig 43. 검색하면 RFC 6749 문서가 보인다

이 RFC 6749는 OAuth 2.0 Authorization Framework 를 설명하는 문서이다. 여기서 목차 Table of Contents/1.5 Refresh Token 을 보자.

Fig 44. Resource Server와 Authorization Server가 서로 다르다

A : 권한을 획득한다. access token을 발급받는것
B: access token과 함께 Refresh token도 발급하고 저장해둠. Refresh token을 동시에 발급해주는 경우가 많지만 아닌 경우도 있다. 
C,D: API를 호출할때 access token을 제출해 보호된 자원들을 가져옴
E,F: 계속해서 자원을 가져오다가 access token의 수명이 끝나 유효하지 않게 된다.
G: 이때 인증 서버에게 Refresh token을 전달하면서 
H: 다시 access token을 발급 받는다. 이때 refresh token을 새로 발급받는 경우도 있고 그냥 access token만 계속해서 발급받기도 한다.

Fig 35의 페이지에서 refresh token에 대한 매뉴얼을 확인할 수 있다. 

Fig 45

사용하는 Resource Server마다 refreshing하는 방법이 모두 다르기 때문에 매뉴얼을 확인하는 과정이 필요한 것이다. 이 매뉴얼을 조금 더 자세히 들여다보면,

Fig 46

[Host] oauth2.googleapis.com[POST] /token 이라는 path로, [Content-Type: application/x-form-urlencoded는 Form에서 POST 방식으로 전송한다는 뜻], client_id와 client_secret, 보관하고 있었던 refresh_token 값과 grant_type은 refresh_token으로 하여 전송하면 구글에서는 C 부분과 같은 JSON포맷으로 데이터를 리턴해주는데, 새롭게 발급된 access_token, 유효시간 expires_in 과 같은 정보들을 보내주게 되는 것이다. 그리고 B 부분의 항목들을 보면 OAuth의 스펙을 보면 표준화된 항목들이다. 많은 시스템들에서 이와 비슷하게 동작한다고 볼 수 있다.

전체 인증 과정 요약도

https://meetup.toast.com/posts/105

https://stackoverflow.com/questions/32964774/oauth-or-jwt-which-one-to-use-and-why

TOP

8. 마무리

단체 메신저가 없던 시절에는 문자메세지를 주고받을 때 단 둘이서만 메신저를 사용할 수 있었다. 이때 3자가 서로 약속을 정하려고 하면 소통의 어려움이 엄청 컸다. 단체 채팅이 가능한 메신저가 등장하면서 약속에 대한 혁명이 시작되었다.

OAuth 가 복잡한 것도 비슷하다. OAuth는 인증과정에 참여하고 있는 3자, 즉 Client, Resource Owver, Resource Server가 한자리에 모일 수 없는 상황에서 어떻게 하면 서로를 신뢰할 수 있을 까라는 고민에서 출발한 기술이다. 

OAuth를 몰라도 이를 대신해줄 라이브러리들도 많이 있다. 관심가져 볼 만한 주제 몇 가지에 대해 얘기해보자.

OAuth의 가장 매력적인 부분은 Client 입장에서 제3자인 Resource 서버를 통해 Resource Owner의 신원을 인증할 수 있다는 점이다. 누군가가 구글이나 페이스북처럼 신뢰할 수 있는 Resource Server를 통해 우리에게 access token을 전달한다면 이를 통해 우리는 Resource Server 상에서 Resource Owner의 고유한 식별자를 획득할 수 있을 것이다. 바로 이 식별자가 일반적인 서비스에서 id와 비밀번호가 하는 역할을 할 수 있게 되는 것이다. 이렇게 다른 서비스와의 연합을 통해 사용자를 식별하는 인증체계를 federated identity라고 부른다. Login with Facebook, Login with Google과 같은 기능들이 바로 이러한 기술을 이용한 것이다. 주요한 서비스들은 이를 쉽게 구현할 수 있는 방법을 제공하고 있다. 

한편 OAuth를 이용하는 궁극의 목적은 API를 제어하는 것이다.  오늘날 많은 API가 Restful 스타일로 설계되고 있다. 또 API를 통해 주고 받는 데이터는 JSON, XML 과 같은 정보형태, 데이터 포맷을 이용하는 경우가 많다. 이런 키워드들을 활용하기 바란다. 

TOP

Comments