[OAuth] OAuth 2.0

okyungjin·2022년 4월 11일
1

📘 본 포스팅은 YouTube의 [생활코딩] WEB2-OAuth 영상을 참고하여 정리한 글입니다.

OAuth를 이해하고, OAuth를 사용하여 accessToken을 얻어오는 과정을 알아보자.

Intro: 용어 숙지

글을 효율적으로 이해하기 위해서는 용어 숙지가 필수이다.

Client, Resource Server, Resource Owner

  • 나의 서비스는 Client라고 한다.
  • Google, Facebook, Twitter 와 같은 그들의 서비스를 Resource Server라고 한다.
  • User는 Resource Owner라고 한다.

accessToken

accessToken은 일부 기능만 허용해주는 토큰이다. Client는 User의 ID / PW가 아닌 이 accessToken을 사용하여 Resource Server의 데이터를 수정, 삭제, 생성하는 등의 작업을 할 수 있게 된다.

OAuth를 왜 사용하는가?

User가 Client에서 어떤 작업을 했을 때 Resource Server에게 업데이트 등을 요청하는 경우를 생각해보자.

업데이트를 위해서는 Resource Server에서 사용하는 User의 ID / PW가 필요할 것이다.
가장 쉬운 방법 Client가 User의 Resource Server ID / PW를 받아서 가지고 있는 것일텐데, 이럴 경우 보안상 이슈가 많을 수 밖에 없다.

이러한 문제를 해결하기 위해 사용하는 것이 OAuth이며, 결론적으로 OAuth를 사용하여 accessToken을 받아 안전하게 위와 같은 작업을 처리할 수 있도록 한다.

이제 OAuth로 어떻게 accessToken을 받는지 알아보자.

OAuth로 accessToken 발급 받는 과정

1) 등록

Client는 Resource Server에 사전에 등록을 해야한다.
Resource Server 마다 등록 과정이 다르긴 하지만 아래의 항목들은 보통 공통적이다.

  • Client ID
  • Client Secret
  • Authorized redirects URIs → Resource Server는 해당 주소 외의 다른 주소가 요청할 경우 요청을 무시한다.

💡 주의
Client ID는 노출되어도 되지만, Client Secret는 절대로 노출되어서는 안 된다.

2) Resource Owner의 승인 받기

  1. Resouce Owner가 Client의 서비스를 이용하는데 Resource Server의 인증이 필요한 작업을 요청한다. 예를 들어 Facebook에 글을 쓰거나 Google Calendar에 일정을 만드는 등의 서비스를 이용할 때이다.

  2. Client는 Resource Owner에게 로그인 버튼을 제공한다. 이 로그인 버튼은 단순히 https://resource.server?client_id=1&scope=B,C&redirect_uri=https://client/callback 와 같은 주소를 연결해주는 버튼이다.

  1. Resource Owner가 해당 주소를 통해 Resource Server로 접속을 한다.

  2. Resource Server는 Resource Owner의 로그인 여부를 파악하여, 로그인이 되어있지 않다면 로그인 화면을 띄워준다.

  1. Resource Owner가 로그인에 성공했다면 Client ID를 비교하고, 현재 접속을 요청하는 URL이 redirect URL 과 일치하는지 확인한다. 다르다면 여기서 작업을 종료한다.

  2. 일치한다면 Resource Server는 Resource Owner에게 엑세스 확인 창을 전송한다. 이는 Client에게 엑세스를 허용할 것인지 물어보는 확인 창이다.

  3. 동의를 하면 Resource Server는 Resource Owner가 특정 Client에 대한 엑세스를 허용했다는 것을 알게된다.

3) Resource Server의 승인 받기

위의 과정으로 이제 Resource Owner의 승인을 받아왔으니, 이제 Resource Server의 승인을 받는 과정이 필요하다.

Resource Server가 승인을 위해 accessToken을 바로 발급하지 않고 하나의 절차를 더 거친다.

이 절차는 Authoriztion Code라는 임시 비밀번호를 받는 절차이다.

  1. 2-7 과정을 거치면 Resource Server는 Resource Owner에게 어떤 주소를 전송한다.
    Location: https://client/callback?code=3 와 같은 주소이다.
    Locaiton은 Response Header로 주는 값이며, 웹 브라우저에게 “여기 주소로 이동해라”라고 명령한다. 3 이 Authoriztion Code이다.

  2. Resource Owner의 사용자는 이 주소로 이동하게 되고, Client가 3 이라는 Authoriztion Code를 알게 된다.

  3. 이제 Client는 Resource Owner를 거치지 않고, 아래의 주소로 Resource Server에 직접 접속한다.
    이 주소에는 Authoriztion Code와 Client Secret이 담겨있다.

// 편의상 개행을 넣음
https://resource.server/token
	?grant_type=authoriztion_code
	&code=3
	&redirect_uri=https://client/callback
	&client_id=1
	&client_secret=2
  1. Resource Server는 Authoriztion Code, Client ID, Client Secret이 모두 일치하는지 확인한다.

4) accessToken 발급

OAuth의 최종 목표는 aceessToken 발급임을 까먹지 말자.

  1. 3-4 과정을 거쳐 모두 일치하는 것을 확인했다면, Client와 Resource Server는 인증을 다시 시도하는 것을 막기 위해 Authoriztion Code를 삭제한다.

  2. Resource Server는 Client에게 accessToken을 응답해준다.

  3. Client는 받은 accessToken을 내부적으로 저장한다.

이제 Resource Server는 이 accessToken을 가지고 있다면 등록 과정에서 설정한 Scope에 대한 서비스에 대한 자원을 내어준다.

발급 받은 accessToken 사용

발급 받은 accessToken을 사용하여 API를 호출해보자.

Google Calendar를 예시로 들어보면 아래와 같이 API에 대한 명세를 제공한다.
발급 받은 accessToken을 아래 주소에 넣고 호출하면 데이터를 불러올 수 있다.

refreshToken

accessToken은 일반적으로 1-2시간, 길게는 90일 까지의 수명이 정해져있다. 수명이 끝나면 API에 데이터를 요청해도 데이터를 받을 수 없다.

수명이 지났을 때마다 사용자에게 위와 같은 과정을 거치게 하는 것은 매우 불편한 일이므로 refreshToken이라는 사용한다.

다음은 OAuth에 대한 RFC 문서의 refreshToken 관련 내용이다.

🧐 RFC란?
RFC(Request for Comments)란 미국의 국제 인터넷 표준과 기구인 IETF(Internet Engineering Task Force)에서 제공, 관리하는 문서로 인터넷 개발에 있어서 필요한 기술, 연구 결과, 절차 등을 기술해 놓은 메모를 말한다.

보통 Resource Server는 accessToken과 refreshToken을 함께 발급한다.

Client가 accessToken을 사용하다가 특정 시점에 수명이 끝난 accessToken을 사용하여 Invalid Token Error라는 응답을 받게 되면, Client는 저장하고 있던 refreshToken을 전달하여 accessToken을 다시 발급 받는다.

refreshToken은 서비스에 따라 갱신될 수도 있고 갱신하지 않을 수도 있다. Resource Server 마다 refreshToken을 제공하는 법이 다르므로 문서를 참고하자.

참고) [Google identity] Access to Google APIs - Refreshing an access token

profile
배우고 기록하는 것을 좋아하는 프론트엔드 개발자입니다 ✌️

0개의 댓글