본문 바로가기
Code/개발지식

OAuth 이해하기

by 코드포휴먼 2020. 7. 22.

최근 대부분의 서비스에서 소셜 로그인을 지원하는 것을 볼 수 있다.

소셜 로그인 덕분에 인증 절차가 간략해지고 인증 정보를 잊어서 발생하는 불편함이 해소되었다.

소셜 로그인을 구현하기 위해선 기본 원리인 OAuth 개념과 절차를 이해할 필요가 있다.

OAuth를 통해 회원들의 아이디와 비밀번호를 처음부터 보관하지 않고 회원을 식별하는 기능을 구현할 수 있다. 

 

rfc 6749에서 OAuth 개념을 확인할 수 있다. https://www.ietf.org/rfc/rfc6749.txt

OAuth에 대해 정말 잘 정리된 글도 있다. https://d2.naver.com/helloworld/24942

원리를 깊은 곳까지 자세히 설명한 글이지만, 그 전에 보다 쉽게 내용을 정리하겠다.

본 포스팅은 생활코딩의 OAuth 강의를 정리한 글이다. https://opentutorials.org/course/3405

 

 

OAuth의 세 가지 참여자

OAuth와 관련해선 크게 세 가지 참여자가 존재한다.

  • Resource Server : 제어하고자 하는 자원을 갖고 있는 서버 (ex. Facebook, Twitter)
     + Authorization Server : 인증과 관련된 처리를 전담하는 서버
  • Resource Owner : 자원의 소유자 (User)
  • Client : Resoure Server에 접속해서 정보를 가져가는 클라이언트 (개인의 서비스)

 

OAuth의 공식 매뉴얼을 본다면 Authorization Server라는 것이 추가적으로 있을 것이다.

Resource Server는 데이터를 갖고 있는 서버이며, Authorization Server는 그쪽에서 인증 처리만 전담하는 서버다. 

본 포스팅에서는 편의상 Resourse Server로만 지칭하겠다.

원본 리소스 - 생활코딩 <WEB2 - OAuth 2.0> 강의

 

 

OAuth의 accessToken 역할

회원이 내 서비스에 글을 썼다고 가정하면 내 서비스가 사용자를 대신해서 Resource Server(ex.구글)의 캘린더에 기록하거나 내용을 공유해준다.

이것이 가능하기 위해선 구글에 접근할 수 있도록 허가를 받아야 한다. 

가장 쉬운 방법은 Resource Server로부터 Resource Owner의 아이디와 비밀번호를 그대로 전달받아서 이용하는 것이다. 

그러나 구글의 모든 기능을 다 사용할 수 있기 때문에 강력하고 위험하다.

회원과 구글 측에서도 꺼려할 방법이다.  

개인 서비스 개발자 입장에서는 강력한 개인정보를 유실하지 않도록 엄청난 부담을 떠안게 된다.

 

OAuth를 이용하면 훨씬 안전하게 상호작용할 수 있게 된다. 

회원의 요청에 의해 구글이 아이디와 비밀번호 대신 accessToken이라고 하는 일종의 암호를 발급한다.

accessToken은 구글의 모든 기능이 아닌 그 중 나의 서비스가 꼭 필요한 필수기능만 부분적으로 허용하는 비밀번호다.

나의 서비스는 OAuth를 통해 accessToken을 획득한 다음 그 accessToken으로 구글에 접근해서 데이터의 CRUD 작업을 할 수 있게 된다. 

 

 

 

OAuth의 첫 번째 절차 - ① Client의 등록

Client가 Resource Server를 이용하기 위해서는 사전승인을 받아야 한다. 

사전승인을 register라고 부르며, Resource Server마다 register 방법은 상이하다.

 

공통적으로 register에서 받는 것은 세 가지다.

  1. Client ID : 내가 만들고 있는 어플리케이션을 구분하는 식별자  (노출 무방)
  2. Client Secret : Client ID에 대한 비밀번호  (절대 노출 금지)
  3. Authorized redirect URIs : Authorization Code를 전달받을 주소

생활코딩 <WEB2 - OAuth 2.0> 강의 캡처 화면

 

Resource Server로부터 권한을 부여받는 과정에서 Authorization Code라는 값을 전달받는다.

Authorization Code를 전달받을 주소가 Authorized redirect URIs다.

지정된 주소 이외의 다른 주소에서 요청하면 Resource Server 그 요청을 무시해버린다. 

설정해둔 Authorized redirect URIs에 Authoization Code와 Access Token이 표시되기 때문이다.

 

 

 

OAuth의 두 번째 절차 - ② Resource Owner의 승인

Resource Owner가 Resource Server에게 Client의 접근을 승인한다는 것을 알려줘야 한다.

과정을 세세하게 보겠다. 

 

Client가 Resource Owner에 등록하면 양쪽 모두 세 가지 핵심정보를 알게 된다. 

Client는 redirect URI에 대한 페이지를 구현하고 준비해놓고 있어야 한다.

만약 Resource Server가 갖고 있는 기능이 A, B, C, D 네 가지라고 가정해본다.

그 중 Client는 B와 C 기능만 필요하다면 모든 기능에 대해 인증을 받지 않고 최소한의 기능에만 인증을 받는다.
그것이 서로에게 유리하기 때문이다.

이제 시나리오를 순차적으로 밟아보겠다.

 

1. Resource Owner는 나의 서비스에 접속한다. 

 

2. 서비스 이용 과정에서 내 서비스가 페이스북 게시글을 조작하는 등의 Resource Server을 사용하는 작업을 해야한다면 Resource Owner에게 소셜 로그인 버튼을 보여준다.

혹은 아래와 같은 메세지를 보여준다. 

"귀하께서 하시는 일은 페이스북의 ~한 기능을 필요로 합니다. 그 기능을 사용하기 위해서는 인증을 거쳐야합니다."

 

버튼을 클릭하거나 메세지를 읽고 다음 행위를 한다는 것은 Resource Owner의 동의를 거친다는 것을 의미한다.
버튼에는 링크를 걸어주면 된다.
링크에는 리소스 서버에 client id값, 사용할 기능(Resource Server가 정해놓은 형식), 인증코드를 전달받을 redirect URI를 쿼리 파라미터로 넘긴다. 

원본 리소스 - 생활코딩 <WEB2 - OAuth 2.0> 강의

 

 

3. Resource Owner가 버튼을 눌러서 Resource Server로 접속을 한다.

 

4. Resource Server는 Resource Owner의 현재 로그인 여부를 파악한다. 

로그인 되어있지 않으면 로그인 화면을 띄운다.

 

5. Resource Owner는 로그인을 수행한다.

 

6. 로그인이 완료되면 Resource Server는 비교 검증을 수행한다.

서버주소 뒤에 파라미터로 넘어온 client id값과 동일한 client id 값이 존재하는지 확인한다.

그리고 서버가 갖고 있는 client id=1에 해당하는 redirect URI
접속을 시도하는 요청에 함께 넘어온 redirect URI와 같은지 비교한다.

원본 리소스 - 생활코딩 <WEB2 - OAuth 2.0> 강의

 

 

7. 비교 검증을 마치면 Resource Owner에게 scope에 해당하는 권한을 Client에게 부여할 것인지 확인 메세지를 전송하게 된다. 

"어떤 Client가 특정 항목들을 요청하고 있는데 허용할 것인가?"

 

8. 허용 버튼을 누르면 허용했다는 정보가 Resoure Server로 전송된다. 

 

9.  Resource Server는 회원의 허용 정보수집한다.

Resource Owner의 user_id가 1이라고 가정할 때 user_id 1인 객체는 Scope b,c에 해당하는 작업에 허용하는 것에 동의했다고 서버(디비/파일)에 저장한다.

 

원본 리소스 - 생활코딩 <WEB2 - OAuth 2.0> 강의

 

 

 

OAuth의 세 번째 절차 - ③ Resource Server의 승인

이전 단계까지 마치면 Resource Server에는 user_id가 1인 회원은 b, c기능 접근에 허용했다는 정보가 저장된다.

Resource Owner에 대한 허락을 구했으니 이제 Resource Server의 허락을 구해야한다.

Resource Server는 accessToken발급하기 전에 임시 암호인 Authorization Code를 발급한다.

(삼자 간의 인증 절차를 위해서)

accessToken을 발급하기 전 단계를 순차적으로 보겠다.

 

1. Resource Server는 Authorization Code를 회원에게 전송한다.

전송할 때 Header 값에 Location를 주는데, 이는 리다이렉션 명령에 해당한다.

즉, Resource Server가 회원의 웹브라우저에게 https://client/callback?code=3이라는 주소로 이동하라고 명령한 것이다.

?code=3 부분이 Authorization Code에 해당한다. 

생활코딩 <WEB2 - OAuth 2.0> 강의 캡처 화면

 

 

2. Resource Owner의 웹브라우저는 회원이 인식하지도 못할 만큼 은밀하게 주어진 주소로 이동한다. 
Client는 이 주소를 바탕으로 Authorization Code를 알게 된다.

생활코딩 <WEB2 - OAuth 2.0> 강의 캡처 화면

 

 

3. 이제 Client는 Resource Owner을 통하지 않고 Resource Server에 직접 접속한다.

지금까지 알아낸 정보와 client_secret을 함께 보낸다. 

 

4. Resource Server는 클라이언트가 넘긴 codeclient_id, client_secretredirect_uri 4가지가 모두 일치하는지 확인하고 다음 단계로 넘어간다.

저장하고 있는 code와 전달받은 code가 일치하는지 비교하는데, code=3은 client_id=1인 클라이언트에게 발급한 인증코드였다.

생활코딩 <WEB2 - OAuth 2.0> 강의 캡처 화면

 

 

 

OAuth의 네 번째 절차 - ④ Access Token 발급

앞서 Client는 Resource Server에 외부에 노출해선 안되는 client_secret값을 authorization code와 함께 직접적으로 보냈다.

이제 OAuth의 핵심인 accessToken을 발급하는 과정을 보겠다.

 

1. authorization code을 통해 인증을 마쳤으므로 Resource Server는 code값을 지워야한다.

그래야 다시 인증하지 않는다.

 

 

2. 그 후 Resource Server는 AccessToken을 발급하고 Client에게 응답해준다. 

 

3.  Client는 AccessToken을 내부적으로 서버에 저장한다.

앞으로 Client가 accessToken=4로 접근하면 Resource Server는 갖고 있던 accessToken가 user_id=1에 해당하는 회원에게 발급한 것을 확인하고, 유효한 기능(b, c)에 대해 접근을 허용한다. 

 

 

 

OAuth의 다섯 번째 절차 - ⑤ API 호출

accessToken을 활용해서 Resource Server을 핸들링해야 한다.
Client는 Resource Server가 알려주는 방식대로 조작해야 하며, 그 방식을 API(Application Programming Interface)라고 부른다. 

Resource Server 앞에는 API가 존재한다고 이해하면 된다.

 

API를 사용하는 방법은 Header에 "Authorization: Bearer [Access Token]"을 넣어서 API URI에 요청하는 것이 일반적이다. 

Resource Server의 API를 호출하는 방법은 여러가지이니 참고용으로만 영상을 살펴봤다.

 

 

 

OAuth의 연장 - ⑥ Refresh Token 발급

Access token수명이 있다. 

수명이 끝난 token으로 API에 접속해도 API는 요청을 받지 않는다. 

토큰을 다시 발급받을 때마다 사용자에게 인증과정을 처음부터 밟도록 하는 것은 적합하지 않다.

Access token의 수명이 다했을 때 새로운 access token을 발급 받는 방법이 refresh token이다. 

 

보통 Access Token을 발급할 때 Refresh Token을 발급하는 경우가 많다. 

이 두 개를 모두 저장하고 있다가 API 호출할 때엔 Access Token을 이용한다.

그리고 일정기간이 지나서 유효하지 않는다는 에러가 발생한다면 보관하던 Refresh Token을 Authorization Server에 전달해서 Access Token을 다시 발급받는다. 

방법은 Resourch Server마다 다르며 Refresh Token도 주기적으로 새로 발급하는 경우도 있다.

rfc 6749 문서 

 

 

 

OAuth 개념도 중요하되 실제로 소셜 로그인을 구현해보거나 인증이 필요한 API를 사용하면 더 감이 올 것이다.

그리고 구현하면서 사용하는 Resource Server의 지침을 더 자세히 보는 것이 필요할 것 같다. 


출처

https://opentutorials.org/course/3405

https://www.ietf.org/rfc/rfc6749.txt

 

댓글