OAuth 흐름 이해하기
2023년 07월 15일OAuth를 개발자 입장에서 이해해보자.
내가 사용자로 쓸 때는 편했지만,, 처음 개발할 때 많은 개념들이 많아서 잘 이해가 가질 않았다. API 문서를 보면 정말 많은 것들이 나온다. client_id
, client_secret
, redirect_url
, authorization_code
, access_token
, refresh_token
, OAuth Scope
. 보통의 다른 API라면 1-2개 token, id 정도로 다 되었던 것 같은데.
OAuth를 도와주는 다른 라이브러리를 가져다 쓸 수도 있지만 개념을 이해하는 건 꼭 필요하다. 그래야 이게 어떻게 작동하는지, 개발자가 받은 token을 어디에 저장하고 보관할지, 어떤 보안상 이슈가 있을지 알 수 있다. 보통의 OAuth 플로우는 비슷하니 한번 익혀두면 어떤 서비스든지 연결할 수 있다.
OAuth의 기능
OAuth는 아래와 같은 목적을 위해 만들어졌다.
‘로그인한 서비스’ 계정의 데이터를 사용할 수 있게 해준다. 페이스북의 OAuth를 활용한다면 페이스북에 있는 사용자의 정보를 읽거나, 게시물을 대신 올릴 수 있게 된다. 구글 OAuth를 쓴다면 구글에 있는 사용자 정보를 가져오거나, Gmail의 데이터를 읽거나 Gmail로 메일을 발송할 수 있게 해준다. 개발자가 원하는 권한을 OAuth 과정에서 요청할 수 있고 유저의 승인 후 권한이 부여된다.
OAuth로 “____으로 로그인”같이 다른 서비스로 로그인하는 기능을 구현할 수도 있다. “____으로 로그인” 같은 로그인 기능만 활용하려면 OAuth 보다는 OAuth 안에 있는 개념인 OpenID를 활용한다. (요건 추후 포스팅으로)
OAuth의 흐름
한 번에 모든 구조를 이해하려고 하지 말고, 한 단계씩 살펴보면 이해가 쉽게 된다.
client_id
, client_secret
, redirect_uri
, authorization_code
, access_token
, refresh_token
등등 → 한번에 다 이해하려고 하지 말고, 한단계 씩 쪼개보자
0. 사전 준비
- 여기서는 [구글] 로그인을 예시로 사용한다.
- [구글] 로그인을 사용할 내 웹or앱 어플리케이션을 준비한다. 이하 [마이앱] 이라고 부른다
- 구글 cloud console에서 [마이앱] 을 등록하고
client_id
,client_secret
를 발급받는다.- 이때 [마이앱] 의
redirect_uri
을 입력한다.redirect_uri
: 유저가 구글이 제공한 화면에서 접근 권한을 승인한 후에 다시 돌아올 [마이앱] 의 url이다.- 로컬 환경에서 테스트 하기위해 실제 앱의 url, 로컬버전의 url을 각각 입력하기도 한다.
- 이때 [마이앱] 의
1. “구글로 로그인하기” 버튼 클릭
사용자가 “구글 연동하기” (혹은 “구글로 로그인하기”) 버튼을 클릭하면, 구글의 OAuth API로 client_id
, scope
, redirect_uri
정보를 담아 요청을 보낸다.
client_id
:client_id
를 근거로 구글이 [마이앱]에서 이 사용자의 데이터를 원하는 구나’하고 알 수 있다.scope
: 사용자의 어떤 데이터, 권한을 요청하는지.- 예를 들어) 이메일 주소, 이름, 프로필 사진에 대한 ‘읽기’ 권한을 요청할 수 있다.
redirect_uri
도 보통 이때 같이 보낸다.
2. [마이앱]의 redirect url에서 authorization_code를 받는다!
- [구글]이 사용자에게 동의 화면을 띄우고 사용자가 승인을 누르면 내가 1번 요청에서 함께 보낸 [마이앱]의
redirect_uri
로 돌아간다. - 구글이 사용자를 [마이앱]의 redirect url로 보낼 때
authorizaion_code
를 담아서 보내준다.
https://www.myapp.com/api/auth/google/redirect?authorization_code=df23sdf5twh...
- [마이앱]은 이
authorizaion_code
을 꺼내서 사용하면된다.
자! authorization_code
을 얻었다. 하지만 아직 사용자의 정보를 얻을 수 없다. authorization_code
는는 access_token
을 얻는데 사용한다. 이 access_token
을 받고서야 실제 사용자의 데이터를 요청할 수 있게 된다.
3. 진짜 필요한 키 access_token을 받자.
- [마이앱]에서
client_id
,client_secret
,authorization_code
3개로 [구글] OAuth API에 요청을 보낸다.
이 요청이 성공하면 드디어 [구글]에서 access_token
을 받을 수 있다. 이제 이 access_token
으로 드디어 사용자의 데이터를 얻을 수 있다.
4. access_token으로 사용자의 정보를 가져오자
access_token
으로 사용자의 정보를 조회하거나, 데이터를 조작할 수 있다. (허가 받은 권한 범위 안에서). 이 요청은 다른 평범한 API들처럼 요청하면 된다.
하지만 이 access_token
은 유효기간이 있다. 무한정 사용할 수 없다.
5. refresh_token 으로 access_token 갱신하기
처음 [구글]에서 access_token
을 받을 때 이 token의 expire 정보, refresh_token
을 같이 받게 된다. 유저의 다시 데이터를 읽고 쓰기위해서 4번 과정에서 처럼 access_token
을 사용하게 될 텐데, 이 access_token
이 만료되는 때가 온다. 그럼 refresh_token
을 사용해서 새로운 access_token
과 refresh_token
을 받으면 된다.
6. [마이앱] 개발자 입장에서 token 관리
기본적인 플로우는 이렇다. 그럼 [마이앱]의 개발자는 access_token
, refresh_token
을 어떻게 관리해야할까?
3번 단계에서 access_token
, refresh_token
을 DB에 안전하게 저장하자. access_token
이 만료되어 새로운 access_token
, refresh_token
을 받는다면 다시 안전하게 DB에 저장하자. 그렇지 않으면 authorization_code
단계부터 매번 다시해야한다.
주의사항
access_token
, refresh_token
은 절대 클라이언트 사이드에 노출이 되지 않게 한다. access_token
, refresh_token
은 사용자의 데이터에 접근할 수 있는 최종 키이기 때문에 안전하게 관리되어야한다. ‘안전한 방법으로’ 서버 내부에 저장한 뒤 필요할 때 꺼내 사용해야 한다.
다른 궁금증
Q. ‘____으로 회원 가입 / 로그인할 때 [마이앱]은 어떻게 회원 Authentication 처리를 해야할까?
- OAuth 플로우를 통해 받은
access_token
으로 email 같은 사용자 정보를 받을 수 있다. 이걸 회원 식별 정보로 사용하고 싶다면 따로 DB에 저장한다. - 로그인 시에는 OAuth 플로우를 통해 사용자 정보를 확인하고, 이 정보가 DB의 사용자 정보와 일치된다고 확인되면 세션 설정을 한다. (기본적인 세션 관리는 비밀번호 로그인, 이메일로 로그인과 다르지 않다.)
- OAuth 말고 OpenID를 활용할 수도 있다. 구글, 카카오는 OpenID를 기능을 제공한다. OpenID에서는 사용자 Authentication에 사용할 사용자의 프로필 정보, 이메일을 가져오는데 쓰인다. OAuth와는 다르게 사용자의 데이터를 수정할 수 있는 권한을 부여하지는 않는다.
Q. OAuth는 왜 이렇게 여러 단계를 거처야 할까? 왜 한번에 access_token을 받지 않고, authorization_code을 받고 나서야 왜 다시 access_token을 요청해야할까?
authorization_code
단계를 거치는 것이 보안에 이점이 있어서다. redirect_uri
를 통해서 바로 access_token
을 부여하면 access_token
이 브라우저에 노출된다. access_token
이 노출되면 이것만으로도 사용자 대신 데이터를 읽고 쓰고 수정할 수 있게 된다.
참고 자료
TAGS
AUTH