프로젝트에 구글 OAuth 2.0을 적용하며 공부한 내용을 정리한 글입니다.
해당 글은 인가와 인증에 차이를 인지하고 있는 사람들을 대상으로 작성되었습니다.
OAuth 2.0
Open Authorization 2.0으로 인증과 인가를 위한 표준 프로토콜
OAuth를 사용하는 이유
우선 OAuth 2.0을 사용하는 이유는 다음과 같습니다.
1. 보안의 수준을 알 수 없는 애플리케이션에 매번 계정을 만들어 사용하면 ID/PW 관리도 어려울뿐더러 개인정보 유출에 위험성이 있음 (보통 사용자는 비슷하거나 같은 비밀번호를 사용하기 때문)
2. 따라서 보안 수준이 어느정도 검증된 사이트의 API를 이용해 인증을 받는 방법이 보안상 👍
3. 사용자 경험 측면에서도 편리한 로그인을 제공 → (실제로 서비스를 배포하고 크루들에게 소개했을 때, 회원가입에서 귀찮음을 느낌..)
동작 방식
인증 및 인가의 과정을 타 서비스에게 위임하는 방식입니다.
OAuth2.0을 사용하는 경우, OAuth 2.0를 제공해주는 Resource Server(ex. Google)에 직접 로그인하는 방식이 아닙니다.
구글 로그인 기능을 통해 구글에 전송한 구글 계정 정보가 유효한지만 확인하고, 유효한 사용자라면 해당하는 구글 유저 정보 중 일부를 소셜 로그인을 지원하는 웹사이트에 제공해주는 '인증'의 과정만 처리합니다. 자세한 내용은 시나리오를 통해 살펴보도록 하겠습니다.
OAuth 참여자
OAuth 동작에 관여하는 참여자는 크게 세 가지
- Resource Server : Client가 제어하고자 하는 자원을 보유하고 있는 서버 (ex. Facebook, Google, Twitter)
- Resource Owner : 자원의 소유자 (ex. Client가 제공하는 서비스를 통해 로그인하는 실제 유저)
- Client : Resoure Server에 접속해서 정보를 가져오고자 하는 클라이언트(ex. 웹 어플리케이션)
Workflow
구글 소셜 로그인 시나리오
1. 사용자가 클라이언트(ex. 구글 로그인을 지원하는 특정 웹사이트)에 접근
2. 인증되지 않은 사용자인 경우 소셜 로그인 타입에 따라 구글 동의 페이지(consent screen)로 이동
3. 사용자가 동의를 누르면 구글에게 인증 요청
4. 구글에 로그인이 안되어 있다면 로그인 페이지 반환, 로그인이 되어 있다면 계정 정보 사용 허가 여부 페이지 반환
5. 사용자 동의 시, 구글은 요청된 웹사이트로 인증 코드(Authorization Code) 반환
6. 인증 코드를 받은 웹사이트는 구글에 웹사이트 등록 시 받은 [Client ID, Client Secret, 인증 코드]로 구글에 요청
7. 올바른 요청일 경우 구글은 WAS(Client)에 Access Token을 발급
8. 해당 Access Token을 통해 이제 클라이언트는 현재 로그인한 사용자 정보에 접근 가능
개인적인 궁금증 🤔: 왜 Resource Server는 Access Token을 바로 주지 않고 Authorization Code를 반환할까?
결론부터 말하자면, Front Channel(Browser), Back Channel(Backend)의 장점을 모두 흡수해 보안적으로 우수하게 만들기 위해서입니다.
위 그림을 살펴보면 실선은 query parameter로 주고받는 데이터이기 숨길 필요가 없어 때문에 프론트(브라우저)에서 일어나는 작업이고, 점선은 백엔드에서 요청하는 작업입니다.
이때 Authorization Code가 프론트단에서 탈취당한다면?
Code는 쉽게 탈취가 가능하기 때문에 해당 코드를 이용해 데이터를 요청할 가능성이 생깁니다. 다만, 항상 code와 token의 교환은 백엔드에서 일어나기 때문에 문제가 발생하지 않게 됩니다. 교환을 할 때, secret key를 이용해야 하기 때문에 탈취의 가능성이 없으며, 이러한 secret key를 잘 숨겨두기 위해 브라우저 단이 아닌 백엔드에서 교환이 일어나야 합니다.
이러한 보안 문제를 뒤로 하고 프론트 단에서 바로 access token을 요청할 수 있는 방법이 있는데, 이를 Implicit OAuth 2.0라고 합니다. 해당 방식을 이용하면 access token을 프론트에서 바로 요청할 수 있지만, 보안적으로 치명적일 수 있기 때문에 백엔드가 존재한다면 앞서 소개된 code <-> token 교환 방식을 사용하는 것이 가장 이상적입니다.
다시 본론으로 돌아와서 이렇게 OAuth 2.0를 활용해 사용자를 인증할 수 있습니다. 하지만, 이는 좋은 방식은 아니며 OAuth는 인가를 위해 사용되어야 하지 인증에 목적을 두면 안 됩니다. 이를 이해하기 위해서는 OpenID와 OAuth2의 차이를 알아야 하는데, 하단에서 알아보도록 하겠습니다.
OpenID와 OAuth2 차이
2012년도까지의 OAuth 2.0 사용 사례를 살펴보면 위와 같습니다. OAuth 2.0을 authentication(인증)의 목적으로도 자주 혼용해서 사용했는데, 사실 OAuth 2.0의 초기 디자인은 인증의 목적이 아닙니다. OAuth 2.0는 authorization(인가)을 위해 설계됐으며, 오직 permission(권한)을 위해서 사용해야 합니다.
왜 OAuth를 Authentication(인증)의 목적으로 사용하지 말아야 할까요?
- OAuth는 유저의 정보를 가져오는 데 있어서 standard way(일반적인 방법)이 존재하지 않습니다.
- 예시로 우리가 특정 사이트에 소셜 로그인을 행했을 때, 해당 사이트는 우리에 대한 기본적인 email, profile 등의 정보를 가지고 싶어 합니다.
- 이때, OAuth는 permission, scope에 대한 인가를 위해 설계됐기 때문에 유저에 대한 정보를 바로 반환해주지 않습니다.
- 그에 따라 OAuth를 이용해 로그인을 지원하는 사이트들은 모두 자신들이 직접 구글이나 페이스북에 다시 사용자 정보를 요청하는 특정 구현을 필요로 합니다.
- 이 과정에서 모든 리소스 서버마다 정보를 가져오는 방식이 다르기 때문에 프로그램이 복잡해집니다.
OpenID Connect의 등장
인가로 사용돼야 할 OAuth 2.0이 인증의 목적(자신들만의 방식으로 정보를 받아오는 방식을 사용)으로 지속적으로 사용되어, 리소스 서버들은 OAuth2.0에 부족했던 인증을 위한 OAuth2.0 위에 OpenID Connect를 만들어서 얹게 됐습니다.
OpenID Connect Workflow
- 이전과 단 하나의 차이는 scope에서 openid를 요청한다는 것
- 이를 통해 현재는 OAuth 요청이 아닌 openid 요청이라는 것이 명시되고 있다. (사실 진짜 기술적으로는 openid와 oauth request가 동시에 되고 있는 것. OAuth를 이용해 openID connect 하는 중이다.)
- OpenID를 이용해 유저의 기본적인 정보를 알아낼 수 있으며 만약 더 많은 정보를 필요로 한다면? 그때는 access token을 이용해서 더 많은 정보를 받아오는 방식
- OpenID는 JWT로 오기 때문에 decoding 하여 사용자 정보를 식별할 수 있다.
결론
OAuth 2.0 제대로 알고 쓰자!
OpenID Connect가 비교적 최근에 나왔다고 해서 더 좋거나 한 것이 아닙니다.
OAuth와 OpenID는 각자의 목적이 다른 것이기 때문에 각자 목적에 맞게 사용하시길 바랍니다. 😊
참고
https://tecoble.techcourse.co.kr/post/2021-07-10-understanding-oauth/
'Spring' 카테고리의 다른 글
Bean Validation이란 (1) | 2022.06.01 |
---|
댓글