OAuth는 어떻게 동작하는가?

하루히즘·2021년 11월 20일
1

Web Basics

목록 보기
4/4
post-thumbnail

서론

인증, 인가가 필요한 애플리케이션에서 자신을 인증하는 가장 기본적인 방법은 해당 서비스에 가입하는 것이다. 그래서 아이디, 비밀번호, 이름, 생년월일 등을 입력하기도 하고 좀 더 인증이 중요한 서비스의 경우 주민번호, 휴대전화 인증 등을 요구하기도 한다.

그러나 개인정보보호 관리 측면이나 인증의 간편화를 위해서 영향력 있는 기업에 인증을 위임하고 애플리케이션에서는 인증된 사용자를 인가 처리만 하는 방식이 등장하게 되었다. 이것이 OAuth, Open Authorization이다.

현대 애플리케이션에서는 거의 빼놓지 않고 지원하는 인증 방식이며 GitHub, Google, Kakao 등 국내외 다양한 기업에서 해당 서비스를 제공하고 있기 때문에 거의 모든 사용자에 대해서 인증할 수 있다. 그래서 개인 프로젝트에도 이를 적용하려다가 원리를 먼저 이해하고 진행해야 할 것 같아서 이 포스트를 작성하였다.

본론

무엇을 인가하는가?

이름에서 볼 수 있듯이 OAuth는 인가(Authorization)를 위한 프로토콜인데 무엇을 인가한다는 것일까? 보통 OAuth는 로그인할 때 자주 보기 때문에 사용자가 자신을 인증해서 서버 애플리케이션이 사용자에게 리소스를 인가하는 것으로 생각할 수 있지만 OAuth의 Auth는 서비스 제공자가 리소스 오너, 즉 사용자의 데이터(이메일, 식별자 등)를 클라이언트(서버 애플리케이션)에게 인가하는 것을 의미한다.

OAuth로 인증하다보면 어떤 사이트에서는 이메일만, 어떤 사이트에서는 이메일, 이름, 생년월일 등 각 사이트마다 다양한 정보를 요구한다. 이 경우 Google 같은 서비스 제공자가 사이트에게 사용자의 개인 정보를 인가해주기 위해서 사용하는 프로토콜이 OAuth인 것이다.

이렇게 외부 서비스를 이용하여 사용자는 애플리케이션에 직접적으로 민감한 정보(계정 아이디, 비밀번호 등)를 제공하지 않으면서도 자신의 리소스를 제공할 수 있다. 그리고 애플리케이션에서는 이 리소스를 활용하고 사용자를 식별할 수 있다.

프로토콜의 흐름

OAuth 프로토콜에는 3가지 주체가 참여한다.

  • 클라이언트: 리소스에 접근하는 애플리케이션.
  • 엔드 유저, 리소스 오너: 리소스 제공에 동의하는 실제 사용자.
  • 리소스/서비스 프로바이더: 실제 사용자의 리소스를 보관하고 있고 제공하는 서비스(Google, GitHub 등).

oauth flow

위의 도표에서 클라이언트는 서버 애플리케이션(내 경우는 SimpleTodoList)이 될 것이다. 그리고 리소스 오너가 개인 정보를 제공할 실제 사용자가 된다.

먼저 인증되지 않은 사용자가 OAuth로 로그인하려면 자신의 개인 정보를 클라이언트에게 제공하겠다는 것에 동의해야 한다. 이를 위해서 Google이나 GitHub 같은 인증 서버에서는 다음과 같은 화면을 제공(1)한다.
access request

이 화면에서는 어떤 애플리케이션에서 어떤 목적으로 어떤 정보에 접근하는지 사용자에게 명시하고 있다. 즉 자신의 개인 정보를 어떻게 제공하는지 확인하고 이에 동의(2)하는 경우에만 실제로 인증 과정을 진행하게 된다.

동의했다면 OAuth 서비스 업체는 임시 토큰을 발급하여 클라이언트로 전달한다. 그러면 클라이언트는 해당 토큰으로 OAuth 서비스의 인증 서버에 사용자가 자신에게 정보를 제공하도록 동의했다는 것을 인증(3)한다. 그러면 인증 서버에서는 이후 사용자의 리소스에 접근할 수 있는 액세스 토큰을 발급(4)하여 전달한다. 이후 클라이언트는 이 토큰을 이용하여 리소스에 접근(5, 6)할 수 있다.

그리고 일련의 비연속적인(stateless) 과정에서 주체를 인증하기 가장 좋은 수단이 토큰이기 때문에 access token, authorization token 등 다양한 토큰을 목적에 따라 활용하게 된다.

인증 수단으로서의 OAuth

어쨌든 OAuth를 사용하여 서비스 제공자에게서 리소스 오너의 정보를 받을 수 있었다는 것은 사용자가 Google 로그인같은 어떤 인증 수단으로 한 차례 인증되었다는 것을 의미한다. 이를 통해 사용자가 자신의 개인 정보에 대한 접근 권한을 클라이언트에게 위임(delegation)하여 사용자 인증 프로세스의 일부로 사용할 수 있다.

그러나 OAuth는 본래 authorization이지 authentication을 목적으로 만들어진 프로토콜이 아니기 때문에 인증 수단 그 자체로 이를 사용하는 것은 부적합하다. 사용자를 인증하려면 CAPTCHA나 아이디, 비밀번호를 입력하는 것처럼 현재 인증을 요구하는 자가 누구인지, 인증 주체의 본인이 인증을 요구하는 것인지 확인해야 할 필요가 있다.

그러나 OAuth는 위의 프로세스를 통해서 토큰을 얻으면 이제 사용자가 어떤 상태인지, 어떤 식으로 본인을 인증했는지는 신경쓰지 않는다. 그래서 리소스 오너의 리소스에 접근(인가)하는 경우에 적합하지만 리소스 오너 자체를 인증하는데에는 적합하지 않다는 것이다.
process difference

OpenID 라는 인증을 위한 프로토콜과 비교한 도표는 위와 같다. OpenID는 리소스 오너에게 자신을 식별하라는 요청을 보내면 외부 서비스 업체에 자신을 입증할 수 있는 개체를 받아서 클라이언트에게 전달하여 자신을 인증한다. 그러나 OAuth에서는 클라이언트가 리소스 오너에게 리소스에 접근할 수 있는 권한을 요청한다. 리소스 오너가 이에 동의하면 클라이언트는 해당 리소스로 사용자를 식별하여 로그인이나 회원가입같은 로직을 실행할 수 있는 것이다.

그렇지만 거시적인 시각으로 볼 때 사용자는 자신을 인증했으며 클라이언트는 사용자가 누구인지에 대한 정보를 식별할 수 있기 때문에 많은 클라이언트에서 로그인 시 이를 인증 수단으로 활용하고 있다. 어떤 사이트는 OAuth가 끝나면 바로 로그인이 되지만 다른 사이트는 추가적인 정보를 입력하는 경우가 있는데 이는 해당 클라이언트에 OAuth가 인가된 범위의 차이 때문일 것이다.

OAuth 서비스 등록

당연하지만 리소스 오너의 정보를 아무한테나 제공할 순 없기 때문에 OAuth를 사용하려면 인증 서비스 업체에 클라이언트를 등록해야 한다. 그래서 구글같은 업체에서는 이런 가입 과정을 문서로 제공하고 있다. 단순히 가입만 하면 되는게 아니고 클라이언트 애플리케이션에서도 OAuth를 지원하도록 API를 열어두어야 하는데 위의 흐름에서 리소스 오너가 정보 제공에 동의했다면 이를 클라이언트에게 알리고 임시 토큰을 전달하기 위해 리다이렉트를 활용하기 때문이다. 이를 콜백 URL이라 한다.

클라이언트가 서비스 업체에 등록되면 클라이언트 ID와 클라이언트 시크릿(비밀 값)이 발급된다. 클라이언트는 ID를 활용하여 서비스 업체와 리소스 오너에게 어떤 애플리케이션과 상호작용하고 있는지 명시할 수 있다. 리소스 오너는 자신이 정보를 제공하려는 애플리케이션이 맞는지 확인한 후에 접근을 허용한다.

이후 콜백으로 받은 토큰과 클라이언트 시크릿을 활용하여 인증 서비스 업체에게 방금 리소스 오너의 리소스를 요청하던 클라이언트가 자신이 맞다고 인증한다. 이 과정에서 클라이언트 시크릿을 사용하기 때문에 이 값은 프론트엔드나 모바일 애플리케이션에서 노출되지 않도록 신경써야 한다.

이후 리소스 오너가 허용한 애플리케이션이 맞다고 인증되면 그제서야 리소스에 접근할 수 있는 액세스 토큰이 발급된다. 이후 클라이언트는 사용자의 이메일이나 이름, 주소 등 기타 리소스에 접근할 때 이 액세스 토큰을 활용하여 접근할 수 있다.

다른 OAuth 인증 방식

대부분 OAuth는 리소스 오너가 민감한 정보를 제공하지 않고 클라이언트의 접근을 허가하기 위해 사용한다. 그러나 클라이언트가 서비스 업체에게 자신의 정보(콜백 URL 등)를 갱신하기 위해 클라이언트 아이디, 시크릿을 보내서 자신에 대한 액세스 토큰을 얻어오는 방식도 있다. 이 경우 리소스 오너에 대한 인가보다는 클라이언트 측 정보 갱신을 위한 것이라 할 수 있다.

사용자가 상호작용할 수 있는 웹 브라우저가 없는 장치(TV 셋톱박스 등)일 경우 해당 장치(인증 서비스에 등록된 디바이스)의 식별자를 활용하여 인가하는 방법도 있다. 이 경우 인증 서버에 디바이스의 식별자를 요청하면 사용자가 다른 곳(스마트폰, PC 등)에서 인증 과정을 진행할 수 있도록 해당 장치의 식별자와 인증 URL이 응답된다. 사용자는 해당 URL에 직접 접속하여 장치를 확인하고 인가를 허용하는 방식으로 OAuth를 적용할 수 있다.

자세한 내용은 해당 문서의 Grant Type 부분에서 확인할 수 있다.

결론

굉장히 자주 사용되는 서비스지만 그 원리를 제대로 알고 있지 못했다. 이번 기회에 그 흐름을 정리할 수 있었고 추후 개인 프로젝트에 적용할 때도 좀 더 이해를 쉽게 할 수 있을 것 같다.

토큰을 활용하는 점 때문에 JWT가 거의 필수적으로 사용되는 것 같은데 스프링 시큐리티에 내장된 JWT 라이브러리가 있는지 조사해봐야겠다. 이전에는 io.jsonwebtoken 라이브러리를 사용했으나 불필요한 의존성일 경우 제거할 계획이다.

참고

Is there any drawback of using OAuth "pseudoauthentication" as opposed to OpenID?
OAuth
User Authentication with OAuth 2.0
OpenID
An Introduction to OAuth 2

profile
YUKI.N > READY?

0개의 댓글