본문 바로가기

TIL

OAuth란? 그리고 적용시 고려해야 하는 점

백엔드 프로젝트를 진행하다보면, 다들 기능을 하나하나 추가하고 싶어하는 마음이 생기게 된다. 아마 프로젝트를 진행할 때, 기본적으로 로그인 환경을 구현할 것이다. MySQL과 같은 RDBMS를 사용하여, 테이블에 ID와 password가, 클라이언트가 보낸 데이터와 일치하는지 확인한 다음, 성공시 해당 유저를 특정할 수 있는 토큰/세션을 발급해 주는 방식이 가장 흔할 것이다. (여기서 좀 더 업그레이드를 한다면, 비밀번호를 암호하 하여 저장)

사실, 여기까지는 강의를 통해서든, 부트캠프를 통해서든 과정이 마련되어 있어 구현을 대부분 할 수 있을 것이다. 그러나, 요즘 서비스에서 번거롭게 직접 아이디와 비밀번호를 생성하는 과정보단, 이미 가입한 소셜 계정(카카오/구글/네이버 등)을 통해 회원가입과 로그인을 진행하는 것이 보편화 되어있다. 이러한 로그인을 편하게 말하면 소셜 로그인이 되고, 전문적인 용어로 말하면 OAuth가 된다.

 

OAuth란?

먼저 OAuth는 Open Authorization의 약자이다. Open이라고 하면 개방/공개라는 뜻을 뜻하는 경우가 많은데, 이번에도 그러한 케이스이다. 윗 문단에서 자기네 DB에 유저 정보를 저장하고, 자기네 DB로 유저를 인증/인가하는 방식을 설명을 하였다. 이는 어디까지나 자기 자신 서버에서만 이루어지는 과정이다. 하지만 OAuth는 Google이나 Kakao같은 회사의 서버측에서  본인이 구축한 서버(3rd Party)에서 접근을 허용하는 개방된 방식이다.

그러니까, Google/KaKao에는 회원가입한 유저의 정보를 담고 있을 것이고, 이를 내가 구축한 서버에서 사용할 수 있도록 권한을 허용(개방)하는 프로토콜로 이해하면 되겠다.

 

 

OAuth 과정이 생각보다 복잡한 이유

OAuth를 처음 구현하려는 사람이라면, OAuth가 사용자 입장에서 간편한 로그인인 만큼, 구현도 쉬울 거라고 생각하기 쉽다. 하지만 이는 오산이다! 본래 편리한 서비스는 뒤에서 개발자들이 뼈를 깎는 노력을 통해 탄생하는 법. 실제로 사용자 입장에는 간단히 구글 로그인 허용 버튼만 클릭하면 되지만, 그 안에서는 복잡한 로직들이 처리가 된다.

 

OAuth 과정에서 역할을 하는 주체는 다음과 같이 도식화가 가능하다.

먼저 사람 모양을 한 사용자가 있다. 이 사람이 내가 만든 서비스 서버에 OAuth 로그인을 요청하면(일반 로그인 처럼 내 서버에서만 처리가 불가능 하니), Authorization 서버에 로그인 요청을 하는 방식이다.

아마, 여기서 OAuth 처음 구현자(당시의 나)는 이렇게 생각했다. "어, 내 MySQL(RDBMS)에서 직접 식별을 하지 않네. 그럼 Authrization 서버에서 무언가를 내 서버에 전달해 주겠지. 그럼 그거가지고 내 RDBMS에서 식별하게 하면 될려나?" 이렇게...

 

무언가를 그냥 전달하면 매우 위험하다

실제로, Authorization 서버에서 무언가를 전달해 주는 것은 맞다. 그런데 그 무언가가 탈취가 가능하다면? 예를 들어 우리가 브라우저로 로그인을 하였을 때, 서버 측에서 클라이언트 PC에 JWT 등을 마치 표처럼 준다. 만약 Authorization 서버, 예를 들어 Google Authorization 서버에서 사용자의 google email과 ID를 바로 제공하면 어떻게 될까? 손쉽게 탈취가 가능해진다. 그렇게 때문에, OAuth는 여러 단계를 걸쳐서 인증이 이루어지도록 고안되었다.

 

 

OAuth 과정 순서를 정리하자면?

먼저 사용자가 소셜 로그인을 요청하였다고 해보자. 이것을 위의 그림에서는 Authorization Request로 표현을 하였다. 이후 Authorization 서버에서 승인(Authorization Grant)를 하고, 일종의 code를 보낸다. code는 여러분이 백엔드 어플리케이션 설정에 적어놓은 redirection url, 즉 프론트 서버(브라우저)로 전달이 된다.

프론트 서버에서 받은 code는 다시 백엔드 서버로 전달된다(이건 본인 서비스 서버 내에서 전달). 그리고 백엔드 서버에서는, code를 다시 Authorization 서버에 전달을 하여 access token을 요청한다. 

왜 이미 Authorization 서버에 접근이 가능한데 왜 또 access token을 요청하는지 이해가 처음에는 이해가 되지 않았다. 하지만, access token은  Authroization 서버가 아닌, Resource 서버에 접속을 해야 할 때 사용되는 토큰이다. Resource 서버는 말 그대로 사용자의 정보를 담고있는 서버이다. 개인정보 탈취를 방지하기 위해 이렇게 몇 단개를 걸쳐 요청하는 것으로 이해하면 되겠다.

Access Token은 백엔드 서버에서 직접 구글로부터 받아오며, 클라이언트에는 전달되지 않기 때문에 브라우저 상에서 노출될 일이 없다. 이는 OAuth 구현에서 보안을 강화하는 중요한 요소다. 그리고 백엔드 서버는 access token을 사용자 정보를 담고 있는 resource 서버에 전달과 동시에 유저의 정보를 요청한다. 예를 들어, google의 서버라면, 소셜 로그인을 하는 해당 유저의 email 주소나 닉네임 등이 있겠다.

이렇게 전송받은 사용자 정보는 본인 서버의 RDBMS에 테이블에 저장한 유저 정보를 통해 식별을 한다. 그리고 본인 서버에서 jwt토큰을 발급하면서 사용자는 로그인 유저 대상 서비스를 이용 가능한 상태가 된다.

 

처음에는 난해하고, 소셜 로그인 구현 강의를 보면서 바쁘게 타이핑 하느라 이해가 안 갈 수도 있다. 하지만, 시간을 가지고, 천천히 하나하나 이해를 하면, 추후에는 여기서 더 추가적인 보안도 구현할 단계로 나아갈 수 있으리가 생각한다.