소셜 로그인을 진행하기 앞서, 기본이 되는 OAuth 프로토콜을 알아보고 정리하는 시간을 갖기 위해 포스트를 작성하였습니다.
개념을 한 줄 요약하자면 "OAuth는 서비스에서 '인증'을 분리하는 방식입니다."
1. OAuth 란?
우선 OAuth는 Open Authorization의 약자로, 이를 직역해보면 "권한 열기" 라는 의미를 가집니다. 실제 개발을 하며 사용되는 의미로는 다음과 같이 이해할 수 있습니다. 구글, 애플, 카카오톡과 같은 여러 플랫폼의 사용자 데이터에 접근하기 위해, 제 3자 클라이언트(우리의 서비스)가 사용자의 접근 권한을 위임받을 수 있는 표준 프로토콜이다.
plus. 지금 글을 작성하고 있는 tistory도 카카오 OAuth를 사용하고 있다.
등장배경
OAuth 이전에는, 사용자의 아이디/비밀번호를 직접 제 3자 서비스에 제공해야 했습니다.
(예를 들어 Github에서 Google 계정과 연동을 하려면, Google 계정 정보를 Github에 직접 등록했어야 했다..)
이 방식은 사용자의 모든 권한을 제 3자 서비스가 통제하게 하며, 계정 정보가 해킹 위험에 노출될 수 있는 문제가 있었습니다. 물론 이런 문제를 해결하기 위해 각 회사는 AuthSub(구글)나 BBAuth(야후)와 같은 프로토콜을 개발했지만, 이들은 표준화된 방법이 아니었습니다.
이러한 배경 속에서 2007년에 OAuth 1.0 버전으로 처음 등장했습니다.
하지만 클라이언트의 구현이 매우 복잡했고 CSRF 공격에 대해 취약했으며, 모바일 환경에서 구현하기 어려운 문제가 있었습니다.
이후 OAuth 2.0이 개발되어 더 간단하고 안전한 인증 구조가 제공되었고, 현재까지 많은 서비스에서 표준으로 채택되어 사용되고 있습니다.
2. OAuth 구성 역할
유저 | 서비스 | 플랫폼(구글, 애플, 카카오..) | |
Resource Owner | Client | Authorization Server | Resource Server |
인증을 수행하는 주체 | 권한을 위임받는 주체 | 인증을 수행하고 권한을 부여하는 주체 |
인가를 수행하고 리소스를 제공하는 주체 |
3. OAuth 주요 용어
"인증/인가"는 보안을 공부할 때, 가장 먼저 마주하는 개념입니다.
중요한 개념으로, 이름이 비슷해 헷갈릴 수 있어 간략히 개념을 정리하였습니다.
Authentication | 인증. 올바른 유저인지 확인하는 과정이다. |
Authorization | 인가. 인증된 유저에게 접근 권한을 부여하는 과정이다. |
[OAuth Setting]
Client_ID / Client_Secret | 클라이언트 자격증명 클라이언트가 권한 서버에 등록하면 발급받을 수 있으며, 권한 서버에서 클라이언트의 검증에 사용된다. |
Redirect URI | 클라이언트의 인증을 마치고, 권한 서버가 응답을 보낼 url |
[OAuth Request/Response]
Authorization Code | 인가 서버에서 인증 이후에 발급되는 코드 access token과 refresh token을 얻는 데 사용된다. |
Scope | 클라이언트가 유저 리소스에 대해서 특점 범위의 엑세스 권한을 요청하는데 사용된다. (예를 들어, 유저의 이름과 이메일 정보에 대한 권한 요청할 수 있다.) |
State | CSRF 공격에 대비하기 위해 클라이언트가 권한 서버에 요청 시 포함하는 임의의 문자열 권한 서버는 응답 시 동일한 값을 클라이언트에게 보내야 한다. |
Access Token | 클라이언트가 유저 리소스에 접근하기 위한 권한을 부여받은 토큰 |
Refresh Token | access token이 만료된 후 새로운 access token을 발급받기 위한 토큰 |
4. OAuth 동작 과정
OAuth 동작 과정은 위에 작성한 플로우로 충분히 이해할 수 있을 것 같습니다.
하지만 보다 명확하게 개념 정리를 하기 위해서, 플로우를 직접 그리면서 한 번 짚고 넘어가면 좋을 것 같은 주제들을 정리해보았습니다.
1) 인증 참여 주체
OAuth 인증 과정에서 Resource Owner와 Authorization Server만이 참여합니다.
Client는 사용자 인증 정보에 대해서 알 필요가 없으며, 알아서도 안 됩니다.
2) OAuth와 서비스의 연결 시점
운영 환경에서 OAuth가 정상적으로 동작하고 있다면, OAuth와 서비스의 연결 시점은 크게 중요하지 않을 수 있습니다.
그러나 OAuth 로그인 개발 단계에서는 예외적인 상황을 고려해야 합니다.
ex. OAuth 인증 및 인가 과정은 정상적으로 완료되었으나, Client 서버에 문제가 발생하여 회원가입 과정에서 오류가 생긴 경우 (회원가입 시 이름 정보 필수)
이러한 상황을 이해하기 위해 "OAuth와 Client가 연결되는 시점"을 살펴볼 필요가 있습니다.
총 두 가지 단계가 생각될 수 있습니다.
- OAuth 서비스 → 클라이언트 서버 (인가 코드 전달)
- 위 플로우에서 9번 과정에 해당됩니다. - 클라이언트 서버 → OAuth 서비스 (인가 코드로 토큰 요청)
- 위 플로우에서 5~6번 과정에 해당됩니다.
이 연결 시점은 OAuth 플랫폼마다 다를 수 있으며, 애플 로그인의 경우는 5~6번 과정에서 OAuth와 Client가 연결됩니다.
따라서 Access token 요청 단계에서 에러가 발생했을 시, 테스트 계정의 연동을 해제해야만 회원가입 환경을 유지할 수 있습니다. 특히, 애플 로그인은 회원가입 시점에서만 '사용자 이름' 정보를 주기 때문에, 이름이 반드시 필수적인 서비스라면 OAuth 연동을 해제하고 다시 진행해야 합니다.
3) 로그인 세션 응답
Client 서버가 회원가입/로그인을 성공적으로 마치고, 반환하는 세션 응답은 서비스 보안 방식에 따라 달라질 수 있습니다.
- 세션 DB를 사용하는 경우 → 세션 ID(Session ID) 반환
- 서비스 자체 JWT를 사용하는 경우 → JWT(Json Web Token) 반환
- OAuth의 Access/Refresh Token을 사용하는 경우 → OAuth Token (JWT 아님) 반환
4) 로그인 완료 이후, 리소스 요청
로그인을 마치고 사용자가 서비스를 이용하는 과정에서, 어떻게 리소스를 요청해야 하는지 생각해봅시다.
이는 '로그인 세션 응답'에 따라서 달라지게 됩니다.
OAuth token을 사용한다면, OAuth Resource Server에서 리소스를 요청 및 제공받을 수 있습니다.
그렇지만 세션 ID나 자체 Jwt을 사용한다면 그럴 수 없습니다.
여기서 한 가지 고민해야 할 점이 있는데..
'사용자가 리소스를 요청할 때마다 Resource Server에 요청을 보내서 받아오는 것이 좋은 방법일까?'
이를 고려했을 때, 회원가입 때 서비스에서 필요한 사용자의 Resource를 모두 받아와 서비스 DB에 저장하고, 리소스 요청 때마다 서비스 DB에서 조회하는 방식이 더 좋은 설계이지 않을까 생각합니다.
5. OpenID Connect
OAuth 2.0에서는 OIDC(Open ID Connect) 의 개념이 도입되었습니다.
OIDC는 기존의 Authorization Server를 그대로 사용하면서, AccessToken뿐만 아니라 ID Token을 함께 발급받을 수 있는 방식입니다. ID Token은 JWT 형식으로 제공되어, 사용자의 인증 정보를 포함하고 있어 Client가 별도로 Resource Server에 사용자 정보를 요청하지 않아도 인증을 수행할 수 있다는 장점이 있습니다.
애플 소셜 로그인 역시, OIDC 방식으로 동작합니다..
(추가 정리 예정..)
참고
테코톡 (인증/인가, OAuth 2.0)
https://www.youtube.com/watch?v=y0xMXlOAfss&t=884s
https://www.youtube.com/watch?v=Mh3LaHmA21I
NHN (OAuth: 과거, 현재 그리고 미래)
'TIL' 카테고리의 다른 글
애플 소셜 로그인 (with. Spring) (1) | 2024.11.05 |
---|---|
Sysbench 벤치마크 & 테스트 데이터 (for. Mac) (0) | 2024.07.27 |
템플릿 메소드 패턴 vs. 전략 패턴 (0) | 2024.07.14 |