OAuth 에 대하여

김법우·2022년 12월 9일
0

security

목록 보기
2/3

들어가며…

OAuth 는 개발을 하다 보면 자주 접하는 단어이다. 내가 제일 OAuth 라는 단어를 본 것은 2년전 처음 개발 공부를 할 때 소셜 로그인을 구현하면서였다. 지금까지도 심심치 않게 듣는 단어이지만 정확히 어떤 뜻인지, 어떻게 플로우가 흘러가는지에 대해 상세하게 모를 때가 있다. 이번 포스팅에서는 OAuth 2.0 의 정의, 용어, 원칙, 동작 방식에 대해 상세히 알아보자!

OAuth 2.0 이란 뭘까?

"Open Authorization"을 의미하는 OAuth 2.0 은 웹사이트 또는 애플리케이션이 사용자를 대신하여 다른 웹 앱에서 호스팅하는 리소스에 액세스할 수 있도록 설계된 표준입니다. 

2012년에 OAuth 1.0을 대체했으며 현재 온라인 승인을 위한 사실상의 업계 표준입니다. OAuth 2.0은 동의된 액세스를 제공하고 사용자의 자격 증명을 공유하지 않고 클라이언트 앱이 사용자를 대신하여 리소스에서 수행할 수 있는 작업을 제한합니다.

“들어가며” 에서 이야기했듯이, 나도 OAuth 라는 단어를 소셜 로그인을 통해 처음 접했다. 네이버, 카카오, 구글 소셜 로그인 기능을 구현하기 위해서는 각 플랫폼에 사용자가 로그인 요청을 하고 응답으로 받아온 인증 코드를 통해 다시 엑세스 토큰을 가져와 사용자 정보를 가져와야했기 때문이다.

이 과정에서 보았듯이, 내 서버에서는 소셜 로그인을 직접적으로 수행하지 않았다. 이전 포스팅에서 인증 요소에 대해 이야기를 했었는데 사용자의 정보는 각 소셜 로그인 페이지에서 인증 요소를 통해(대부분 아이디, 비밀번호로) 인증을 수행하고 저장되는 회원 데이터베이스에 있을 것이다. 내 서버에서는 단순히 구글, 카카오, 네이버에게 엑세스 토큰을 통해 사용자의 정보를 받아왔다.

위의 정의를 다시보자. 정의에서 말하는 리소스는 예시에서 언급한 회원 정보이다. 사용자를 대신해 다른 웹 앱에서 호스팅하는 리소스에 엑세스 하는 것은, 엑세스 토큰을 통해 사용자 정보를 내 서버에서 조회하는 것이다.

이전 포스팅의 내용이라면, 사용자는 인증/인가를 통해 자신의 프로필 정보를 받아와야하는데, 전혀 무관한 내 서버에서 프로필 정보를 요청한다. 말 그대로 사용자를 대신해 프로필 정보를 요청한 것이다.

즉, OAuth 2.0 은 애플리케이션이 유저가 각 외부 서비스에서 인증 받은 결과로 얻은 엑세스 권한을 통해 해당 외부 서비스에 있는 리소스에 엑세스하는 일련의 과정을 의미한다.

이 쯤에서 용어 정리

Access Token

엑세스 토큰은 리소스에 접근하기 위해 사용되는 만료 기간이 존재하는 토큰이다. 토큰은 리소스 서버에서 특정 정보들을 암호화해서 발급하며, 발급한 리소스 서버는 토큰을 통해 들어온 요청이 리소스에 엑세스 할 수 있는 권한이 있는지를 판별 할 수 있다. 따라서 리소스 서버 → 요청자 에게 토큰을 전달하는 것은 인가를 수행한 것과 같다.

Refresh Token

엑세스 토큰과 리프레시 토큰의 차이는 만료 시간과 용도에 있다. 엑세스 토큰은 앞서 말햇듯이 인가의 목적이 있는 암호화된 문서이고, 리프레시 토큰은 해당 엑세스 토큰이 만료된 경우 재발급을 받기 위해 존재하는 암호화된 문서이다. 대부분의 보호된 리소스 접근 인가 ⇒ 엑세스 토큰, 엑세스 토큰 재발급 기능 인가 ⇒ 리프레시 토큰인 것이다.

Resource Owner

리소스 오너는 소셜 로그인 예시에서 구글, 카카오, 네이버 서비스에서 회원 가입을 통해 정보를 제공한 유저이다. 해당 서비스들은 각 플랫폼에 저장된 정보를 제공해주는 “주체” 이다. 리소스 오너는 보호 처리된 리소스에 대한 엑세스 권한을 부여해주는 주체이다.

이 말이 조금 어려울 수 있는데, 위의 소셜 로그인 흐름에서 내 서버 → 카카오 (카카오 로그인 페이지) → 사용자 (카카오 로그인 수행) → 내 서버로 오는 흐름을 이해한다면 중간에 사용자가 자신의 리소스에 대해 인증을 수행하는 것을 알 수 있다.

Client

보호된 자원을 요청하는 애플리케이션이다. 위의 예시라면, 소셜 로그인 페이지를 제공하는 내 리액트 앱이 될 수 있겟다.

Resource Server

사용자의 보호된 자원을 호스팅하는 서버이다. 위의 예시로 보면 구글, 네이버의 프로필 조회 API 를 제공하는 서버가 되겠다.

Authorization Server

말 그대로 권한 서버로, 클라이언트의 인증/인가를 수행하는 서버이다. 위의 예시에서 인증 코드 발급, 엑세스 토큰 발급을 네이버에서는 네아로 API 서비스가 해주는데 해당 서버를 권한 서버라고 할 수 있겠다.

2가지 유형에 대하여

OAuth 2.0 에서 권한 부여는 클라이언트(내 서버)가 리소스에 대한 엑세스 권한을 얻기 위해 수행해야하는 일련의 과정(프로토콜)이다. 여러 시나리오를 처리하기 위해 여러 권한 부여 유형을 제공한다. 그중에서도 이번엔 인증 코드 방식, 암시적 허가 방식에 대해 알아보자.

**Authorization Code Grant**

3) Resource Owner 는 Authorization 서버에 로그인을 통해 인증을 수행한다.

4) Authorization 서버는 일회용 인증 코드를 Client 에게 반환한다.

5) Client 는 인증 코드를 사용해 Authorization 서버에게 엑세스 토큰을 요청한다.

3 ~ 5 번이 Client 가 리소스에 접근할 권한을 얻는 핵심 플로우이다. 4) 를 유의깊게 보면 인증은 유저(Resource Owner)가 진행했는데 승인 코드는 내 서버(Client)로 반환하는 것을 알 수 있다.

그렇다면 어떻게 승인 코드를 전달하는지가 궁금할 수 있는데, OAuth 2.0 에서는 https://{MY_APP}/callback 으로 각각의 권한 서버에서 내 서버로 인증 코드를 URL 에 포함해 리다이렉션 시키는 방식을 사용한다. 예시로 카카오 권한 서버는 아래와 같은 반환을 해준다.

// Request
GET /oauth/authorize?
client_id=${REST_API_KEY}
&redirect_uri=${REDIRECT_URI}
&response_type=code HTTP/1.1
Host: kauth.kakao.com

// Response
HTTP/1.1 302 Found
Content-Length: 0
Location: https://{MY_APP}/callback?code=${AUTHORIZE_CODE}

Implicit Grant

Authorization Code Grant 와 가장 큰 차이점은 일회용 승인 코드를 받아오는 과정이 사라졌다는 점이다. Client 에서 Authorization Server 로 엑세스 토큰을 바로 요청한다.

해당 방식은 승인 코드를 사용하지 않으므로 리프레시 토큰을 통해 엑세스 토큰을 재발급하는 것이 불가능하다. 반면에 승인 코드를 발급 받기 위해 필요한 Client 측 비밀키가 필요하지 않으므로 절차와 관리면에서는 효율성이 좋아진다.

애초에 이 방식이 필요했던 이유는 Authorization Code Grant 에서 승인 코드를 받기 위해 client 측 비밀키가 필요한데, 위와 같이 별도의 백엔드 서버가 없는 경우에는 User → Authorization Server → User https://{MY_APP}/callback?ㅁaccess_token=${ACCESS_TOKEN} 오게 되므로 보안 이슈가 발생한다.

마치며

이번에 OAuth 2.0 이 무엇인지 그리고 2가지 유형의 프로토콜에 대해 알아보았다. 다음 포스팅에서는 간단하게 인증/인가를 수행하는 Authorization 서버와 리소스 서버에 사용자 정보를 요청하는 Client 를 Nest.js 로 구현해보고자 한다!

profile
개발을 사랑하는 개발자. 끝없이 꼬리를 물며 답하고 찾는 과정에서 공부하는 개발자 입니다. 잘못된 내용 혹은 더해주시고 싶은 이야기가 있다면 부디 가르침을 주세요!

0개의 댓글