(RFC 6749) OAuth2.0과 token 개념정리, 사용 시 보안 고려점
서론
JWT 리프레쉬 토큰 구현을 하기 위해 찾아보던 중, RFC 6749 문서를 발견하게 되었고 여기에 그간 궁금했던 access token
, refresh token
, bearer token
등의 용어정의와 해당 내용들을 구현할 때 보안적으로 고려해야 할 부분들에 대해 상세히 정리가 되어 있어서 자세히 읽어보게 되었다. 보는 김에, 잘 몰랐던 OAuth 2.0
에 대한 내용도 정리해봤다.
OAuth 2.0 Authorization Framework
개요
- OAuth2.0 프레임워크는 서드파티 어플리케이션이, Http 서비스에 대해 제한된 접근을 가질 수 있도록 도와줌
- resource owner와 Http Service 사이의 인증 과정을 resource owner를 대신하여 진행해 줌으로써 도와줌
- 혹은 써드 파티 어플리케이션을 대신하여 인증과정을 진행해줌
OAuth에 나오는 Roles
resource owner
: 보호받는 리소스에 대해 접근 권한을 허용해 줄 수 있는 entityresource server
: 보호받는 리소스를 호스팅하는 서버. 리소스 요청(access token 포함하여)을 받고 응답함client
:resource owner
에게 권한을 받고resource owner
를 대신하여 해당 인가 정보와 함께 보호받는 리소스에 대한 요청을 하는 어플리케이션authorization server
: resource owner의 인증(authentication)을 거치고 권한(authorization)을 받은 다음 access token을 클라이언트에게 발급하는 서버
OAuth Abstract Flow
(A) 클라이언트가 resource owner
에게 인가 요청을 진행. 보통 클라이언트가 직접 resource owner
에게 요청하기 보다는 authorization server
를 거쳐서 진행하게 됨
(B) 클라이언트가 Authorization Grant
(resource owner
의 권한을 갖고있다는 자격증명)를 받음
Authorization Grant
의 타입은 클라이언트가 authorization 요청을 하는 방법에 따라 다름
- Authorization Code
- Implicit
- Resource Owner Password Credentials
- Client Credentials
(C) 클라이언트는 authorization server
에게 인증을 받으며 access token을 요청하고 Authorization grant
를 제출
(D) authorization server
가 클라이언트를 인증하고 Authorization Grant
유효성 검증 후, 유효하다면 access token 발급
(E) 클라이언트는 보호된 리소스에 대해 resource server
에게 요청하고 access token을 제출함으로 인증을 진행함
(F) resource server
는 access token을 검증하고, 유효하다면 리소스를 보내줌
카카오톡 OAuth 인증에 적용해보기
resource owner
: 카카오 (접근 권한을 허용해 줄 수 있는 역할. 카카오 계정으로 로그인하니까)authorization server
: 우리가 구현하는 어플리케이션에 포함. 여기서Authorization Request
도 날리고,Authorization Grant
를 받은 다음 유효하다면 access token 까지 내려주는 역할을 담당- 그 후, access token으로 우리의 어플리케이션의 기능들을 활용할 수 있는 것
Access Token, Refresh Token, Bearer Token
- access token : 보호받고 있는 리소스에 대한 접근을 위해 사용되는 자격 증명
- access token은 추상화 레이어를 제공
- 다른 방식의 인증 방식(username & password)을 하나의 토큰으로 대체
resource server
에서 다양한 방식의 인증 과정을 알고 있어야 할 필요가 없어짐(어떠한 방식으로 인증을 받았건 간에 access token만 제출하면 인증되었다고 생각하면 되니까)
- 리소스 서버의 보안 요구사항에 따라 다른 포맷, 구조, 이용 방식을 가질 수 있음
- access token은 추상화 레이어를 제공
- refresh token : access token을 얻기 위한 자격 증명
authorization server
에 의해 클라이언트에게 발급- access token이 유효하지 않거나 만료되었을 때, 혹은 동일하거나 더 적은 scope(짧은 만료기간, 더 적은 권한)의 추가적인 토큰 발급을 위해서 사용됨
- 사용한다면 access token 발급 시 같이 발급함
- Bearer Token : 토큰을 갖고 있는 어떠한 사용자든 간에 그 토큰만 갖고 있으면 동일하게 이용할 수 있는 특징을 가진 보안 토큰을 말함
- 좀 더 풀어서 내 식대로 이해하면, 해당 토큰에 리소스에 접근하기 위해 필요한 정보가 포함되어 있어 그 토큰만 갖고 있으면 누구든지 리소스에 접근이 가능하다고 이해하면 될 듯함
- Bearer, 즉 나르는 사람, 운반인, 전달자 라는 뜻을 갖고 있으므로 자격 증명을 담고 있다 포함하고 있다로 이해
토큰 이용시, 보안 고려점
클라이언트 인증
authorization server
는 인증되지 않은 클라이언트와의 상호작용으로 인해 보안에 미치는 영향을 고려해야 하고, 다른 자격증명(eg. refresh token)의 노출을 방지할 수 있는 조치를 취해야 함- 이전에 했던 프로젝트에서 살펴보면 API 호출을 할 때, access token과 더불어 api version이라는 헤더를 클라이언트(Unity)에서 추가해서 보내어 해당 version이 맞지 않으면 응답을 내려주지 않는 식으로 access token이 노출되었다 하더라도 이중 보안을 적용한 사례가 있었음
Refresh Token
authorization server
에서 refresh token이 어느 클라이언트(web application client, native application client ..)에게 발급되었는지의 정보를 관리하여 매칭을 시켜야 함- 그렇게 하여, refresh token을 통해 access token을 발급 받을 때, 그 특정 클라이언트가 보낸 요청이 맞는지를 확인하는 것 => refresh token의 오용, 남용을 막을 수 있음
- 예를 들어, 로그인 할 때 id, password와 클라이언트 identity 정보(mac주소, ip 또는,, 어플리케이션의 고유값.
무슨 값이 있을까..)을 같이 보냄으로 access token, refresh token을 발급해주면서 identity 정보와 refresh token 정보를 저장하는 방식으로..
- 예를 들어, 로그인 할 때 id, password와 클라이언트 identity 정보(mac주소, ip 또는,, 어플리케이션의 고유값.
- 그렇게 하여, refresh token을 통해 access token을 발급 받을 때, 그 특정 클라이언트가 보낸 요청이 맞는지를 확인하는 것 => refresh token의 오용, 남용을 막을 수 있음
- 오용, 남용을 막기 위한 방법으로 refresh token이 한번 사용되면 또 다시 사용될 수 없도록 해야 함
- 두 명이 동시에 동일한 refresh token을 제출 한다면 한명은 무효화된 토큰을 제출할 것이고 보안이 뚫렸다는 것을 탐지가 가능하게 됨
- token(access token, refresh token)은 꼭 TLS를 통해서 전송되어야 함
시니어 분의 충고
- access token은 공개된 거라고 생각을 해야 하고 만료시간을 짧게 가져가는 것이 좋다
- 라이브 때는 하루, 개발 동안 1주일 기간으로 사용하셨다고 함
- 너무 짧으면(예를 들어 1시간?) 인증하는 네트워크 통신 비용만으로도 꽤 과다할 것임(1시간 마다 리프레시 토큰 날려야 할테니 or 재인증)
- 이런 고민도 좋은데 DDos 공격을 막는 것이 더 중요함
- [클라이언트 측면] 로그인 시, 구글 인증(로봇이 아닙니다) 같은 것을 도입하여 API 요청을 빠른 시간안에 반복 못하도록 해야 함
- [서버 측면] API Rate limit 같은 것 적용
- 둘 중 하나만 하는 것이 아니라, 둘 다 해야 함