정리정리

OAuth2.0이란? 본문

cs

OAuth2.0이란?

wlsh 2023. 3. 27. 23:41

혼자 프로젝트를 하다가 점점 인증 과정을 만드는게 프로젝트의 목적에 벗어나기도 하고 배보다 배꼽이 더 큰 경우가 많았습니다. 그래서 소셜 로그인을 도입하자는 생각을 했고, Spring Security의 도움 없이 실제로 구현을 해보고 싶어 자세한 동작 과정을 공부하던 중 생각보다 몰랐던 내용들이 많고, OIDC에 관한 내용을 포스팅 하기 전에 한 번쯤 정리를 해야 할 것 같아서 글을 작성하게 되었습니다.

OAuth 2.0

OAuth 2.0의 정의에 대해 알아보겠습니다.

The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service, either on behalf of a resource owner by orchestrating an approval interaction between the resource owner and the HTTP service, or by allowing the third-party application to obtain access on its own behalf. (출처 RFC6749)

해석을 해보면, '타사 애플리케이션이 리소스 소유자를 대신해 HTTP Service에 제한된 접근을 가능하는 인가 프레임워크' 라고 되어 있습니다.

좀 더 직관적으로 풀이를 하면

'사용자가 사용하는 애플리케이션이 사용자를 대신해 구글, 페이스북에 있는 API와 같은 기능에 접근할 수 있게 하는 프레임워크 또는 프로토콜'

이라고 할 수 있습니다.

여기서 사용자, 애플리케이션, 구글 페이스북 같은 API 제공 서비스는 아래의 역할에 따라 각각 Resource Owner, Client, Resource Server(Authorization Server)이 됩니다.

OAuth 역할 (Roles)

OAuth에는 서로 상호작용하는 4개의 역할이 있습니다.

  • Resource Owner
    • 말 그대로 리소스 소유자이며, 애플리케이션을 사용하는 사용자 입니다.
  • Resource Server
    • 사용자의 리소스를 가지고 있으며, 클라이언트에 제공해주는 서버로, 구글이나 페이스북과 같은 플랫폼을 생각하시면 됩니다.
  • Client
    • 리소스 서버에 저장된 리소스를 접근하려는 애플리케이션으로, 사용자 입장에서는 사용하는 애플리케이션이고, 개발자 입장에서는 서버(서버와 클라이언트가 분리되어 있는 경우)라고 할 수 있습니다.
  • Authorzation Server
    • 클라이언트가 리소스 서버에 있는 리소스에 접근할 때 필요한 Access Token을 제공하는 서버입니다.
      사실 개발자 입장에서는 Resource Server와 Authorzation Server를 구분지을 필요가 크게 없기 때문에 둘을 하나로 합쳐 Resource Server라고 하는 경우도 많은 것 같습니다.

대략적인 흐름

플로우 차트를 통해 OAuth의 흐름을 파악해보겠습다.
사용자가 소셜 로그인 버튼을 클릭하면 클릭을 하면, 클라이언트는 인증 서버에 인증 코드 발급을 요청합니다.

만약 사용자가 권한 요청을 승인하지 않은 상태라면 승인 요청 페이지로 리다이렉트 됩니다.

리소스 접근에 승인을 했다면, 인증 서버는 사용자에게 클라이언트가 접근하려는 리소스와 이에 대한 승인을 허락하는지 확인하고 클라이언트에게 인증 코드를 발급합니다. 이때 인증 서버에서 곧바로 클라이언트에 인증 코드를 발급하기보다, 리소스 오너에게 인증 코드와 클라이언트 리다이렉트 주소를 넘겨 리소스 오너가 인증 코드를 들고 클라이언트에게 리퀘스트를 보내도록 합니다.

클라이언트는 인증 서버에 사용자가 접근 권한을 승인했다는 증거인 인증 코드를 들고 인증 서버에 access token을 요청합니다.

인증 서버는 인증 코드 외에도 필요한 여러 조건들을 확인한 후 클라이언트에게 access token을 제공합니다.

클라이언트는 그제서야 리소스 서버에 access token을 들고 접근이 허가된 리소스에 대해 접근을 할 수 있게 됩니다.

구체적인 흐름

대략적인 흐름에 대해 알아봤지만 애플리케이션을 개발하는 클라이언트 입장에서는 실제로 저 과정이 어떻게 동작하는지를 좀 더 살펴볼 필요가 있습니다. OAuth는 어떤 식으로 OAuth는 3자간의 통신을 원활하게 할 수 있을까요? 또한 정의에서 볼 수 있다시피 '제한된' 접근을 가능하게 하는데, 어떻게 리소스의 접근을 제한시키는지에 대해서도 파악해보겠습니다.

OAuth 인증을 하기 위해 우선 클라이언트는 미리 리소스 서버에 OAuth 사용 등록을 해야 합니다. 리소스 서버에 클라이언트를 등록하다보면 중요한 부분이 크게 4가지가 있는데, 바로 Client ID, Client Secret, Redirect URI, Scope입니다. 하나씩 살펴보겠습니다. (지금부터는 인증서버를 간단하게 리소스 서버라고 하겠습니다)

  • Client ID, Client Secret
    • 리소스 서버에 등록할 클라이언트 아이디와 비밀 키 입니다. 이를 통해 리소스 서버에서 클라이언트를 식별합니다. 클라이언트 아이디는 노출이 되어도 되지만(권환 획득 과정에서 URI를 통해 노출됩니다.) 비밀 키는 절대 노출 되어서는 안됩니다.
  • Redirect URI
    • 클라이언트가 리소스 서버에게 인증 코드를 받을 URI입니다.
  • Scope
    • 클라이언트가 접근 허용을 요청하는 리소스 범위입니다. 소셜 로그인을 할 때 프로필, 사진 등의 권한을 요청한다는 부분이 이에 해당합니다.

구글의 OAuth 등록 과정에서도 이 내용을 볼 수 있습니다.

1. 소셜 로그인 클릭

사용자가 소셜 로그인을 클릭하면 실제로 저런 형태의 URI로 이동하게 됩니다. 그러면 리소스 서버에서는 사용자가 해당 플랫폼에 로그인이 되어있는지를 확인하고 로그인이 되어있지 않다면 로그인 페이지로 리다이렉트 시킵니다. 로그인을 성공하면 리소스 서버는 쿼리 파라미터로 넘어온 데이터들(Client ID, Redirect URI)을 확인하여 리소스 서버에 등록되어 있는 클라이언트인지 체크를 하는 과정을 거칩니다. 만약 등록이 되어있는 클라이언트라면 다시 사용자에게 권한 접근 승인 요청 페이지를 띄우고 클라이언트의 접근 승인을 수락할지 선택하게 합니다.

2. 인증 코드 전달

사용자가 접근 승인을 허락하면, 리소스 서버는 인증 코드와 함께 사용자에게 Redirect URI + 인증 코드가 담긴 URI를 location 헤더에 담아 302 리다이렉트 응답을 보냅니다. 그러면 사용자는 클라이언트에게 인증 코드를 보내고, 클라이언트는 Redirect URI를 통해 인증 코드를 받습니다.

3. access token 발급

클라이언트는 access token을 얻기 위해 리소스 서버에 인증 코드, Redirect URI, Client ID/Secret, Grant Type 등을 넣어 POST 메서드, form 형식으로 보냅니다(구글의 경우입니다). 이 때 Grant Type은 토큰을 발행하는 방법을 말합니다. 사실 위에서 작성했던 흐름 외에도 OAuth 인증에는 다양한 방식이 존재합니다. 하지만 가장 대중적으로 쓰이는 방식이 authorization_code 이고, 지금까지 설명했던 방식도 해당 방법입니다. 다른 방법들에 대해서는 추후에 기회가 되면 포스팅해보도록 하겠습니다.
아무튼 리소스 서버는 다시 한 번 해당 데이터들을 가지고 클라이언트에게 access token을 발급할지에 대해 판단하고 access token, 만료 시간, 토큰 타입 등의 데이터를 전달하게 됩니다. (구글의 경우 JSON으로 응답합니다)

4. 리소스 접근

드디어 인증이 끝나고 클라이언트는 리소스에 접근할 수 있는 권한을 얻었습니다. 이를 통해 허용된 범위 내의 리소스에 접근을 하면 됩니다.


이런 식으로 리소스에 접근할 수 있습니다. 예시 링크

OAuth와 소셜 로그인

지금까지 OAuth에 대해 알아봤습니다. 그런데 OAuth에 대해 알아보니, 단순히 소셜 로그인 용도로 사용되고 리소스 접근은 부가 기능이라고 생각했었지만 실제로 OAuth의 목적은 리소스 접근이었습니다. 사실 이전에 OAuth의 정의에서 authentication framework가 아닌 authorization framework 라고 설명이 되어있었던 것을 기억하시나요? 즉, OAuth는 로그인 인증 프로토콜이 아니라 리소스 접근을 하게 해주는 인가 프로토콜이고, 인가를 하는 과정에서 인증 과정을 거치기 때문에 OAuth를 소셜 로그인 인증 방식으로 사용할 수 있었던 것입니다. (적어도 저는 이렇게 이해했습니다)

그래서 OAuth 인증을 했다 하더라도, 최종 응답에 유저에 대한 데이터가 전혀 없는 것을 알 수 있습니다. 만약 클라이언트가 유저의 가장 간단한 정보인 profile이나 email과 같은 리소스에 접근을 할 때도 항상 access token을 들고 API 통신을 해야 하는 번거로움이 있습니다.

여기서 OpenID Connect(OIDC)라는 새로운 프로토콜과 내용이 연결됩니다. 실제로 구글 OAuth는 OIDC를 사용하고 있습니다. 이에 대한 내용은 다음 포스트에서 작성해보겠습니다.

참고

https://www.youtube.com/watch?v=hm2r6LtUbk8&list=PLuHgQVnccGMA4guyznDlykFJh28_R08Q-&index=1&ab_channel=%EC%83%9D%ED%99%9C%EC%BD%94%EB%94%A9

https://developers.google.com/identity/protocols/oauth2?hl=ko

https://www.rfc-editor.org/rfc/rfc6749

https://6991httam.medium.com/oauth%EB%9E%80-%EA%B7%B8%EB%A6%AC%EA%B3%A0-openid-8c46a65616e6

https://hudi.blog/open-id/

'cs' 카테고리의 다른 글

OpenID Connect와 OAuth2.0  (0) 2023.03.27
Comments