OAuth 인증의 이해 2


이 시리즈의 모든 글 보기 : oauth


OAuth의 등장 배경

User Account

우리가 개발한 서비스는 사용자를 관리합니다.

public class User(string email, string password)
{
    public int Id { get; set; }
    public string Email { get; set; } = email;
    public string Password { get; set; } = password;
    public PersonalInfo? PersonalInfo { get; set; }
}

public class PersonalInfo(User user)
{
    public User User { get; private set; } = user;
    public int? Age { get; set; }
    public string? PhoneNo { get; set; }
}

이 글은 시리얼 키로 소프트웨어 접근을 관리하는 시나리오에는 해당되지 않습니다.

이 경우, 보통 아래와 같이 시스템을 구성하는 것이 일반적입니다.

위 그림에서 Display 다이어그램으로 표시되는 앱들은 우리 시스템이 제공하는 UI 앱(클라이언트)이고, Cloud 다이어그램으로 표신되는 앱들은 웹 서비스(서버) 앱입니다.

보안 위협

사용자의 데이터를 보호하기 위해, 올바른 증명(credentiails)을 제출한 방문자만 접근을 허용하는데, Api 와 Was 모두 로그인을 통해 증명을 제출하도록 합니다.

API

API가 아래의 로그인 요청을 받도록 설계되어 있다면, 우리 시스템은 보안에 안전할까요?

POST /account/login
Host : https://api.myservice.com
Content-type : multipart/form-data

email=abc@abc.com&password=12345

전혀 안전하지 않습니다.

왜냐하면, 누구나 저런 형식의 요청을 우리 API 에 보낼 수 있기 때문입니다.

악의의 공격자가 우리 UI를 흉내내서, 사용자에게 이메일과 비밀번호를 입력하도록 하면 로그인 정보를 쉽게 탈취할 수 있습니다.

WAS

WAS의 경우는 좀 더 안전합니다.
왜냐하면, UI(의 폼)에 Anti-forgery token을 강제로 넣을 수 있기 때문입니다.

POST /account/login
Host : https://was.myservice.com
Content-type : multipart/form-data

email=abc@abc.com&password=12345&asp-anti-forgery-token=…

다양한 공격 패턴이 있겠지만, 가장 기본적인 보안 수단만 고려합니다.

그러나, WAS는 외부 시스템(클라이언트)과 협업하는 것이 곤란한 형태입니다.

제3자 클라이언트

우리 서비스는 성공적이었고, 이제는 외부 시스템이 우리 서비스를 이용하고 싶어 합니다. 우리 시스템 입장에서 이들은 악의적인 공격자가 아니라 할 수 있습니다.

이제, 우리 시스템은 사용자 뿐만 아니라, 외부 시스템도 관리해야 합니다.
아래 도표에서 “Client” 및 "외부 클라이언트"는 외부 시스템을 가리킵니다.

이들을 위한 로그인 규칙도 추가했습니다.

POST /client/account/login
Host : https://api.myservice.com
Content-type : multipart/form-data

email=abc@abc.com&
password=12345&
clientid=132654&
clientpassword=…

그럼, 위와 같은 방식은 보안에 안전할까요?

문맥 상 전혀 그렇지 않겠죠?

첫째로, 사용자의 로그인 정보가 외부 클라이언트에게 모두 노출되고 있습니다.
외부 클라이언트는 무한정 신뢰할 수 있는 존재가 아닙니다. 그들 중에 악의적 목적이 없다고 누가 확신할 수 있겠습니까?

그리고, 더 중요한 둘째는, 외부 클라이언트의 비밀 번호가 "사용자 환경"에서 노출된다는 점입니다.

이는 선한 외부 클라이언트의 로그인 정보를 사용자에게 노출하는데, 모든 사용자가 악의의 목적이 없다고 할 수 없기에, 이 또한 보안 구멍입니다.

용의자는 클라이언트

살펴 봤다 시피, 우리가 일반적으로 생각할 수 있는 시스템 구성은 잠재적 보안 위협을 내포하는데, 그 원인은 비밀 정보가 사용자 환경에 노출되는 구조에서 비롯됩니다.

image

클라이언트가 우리 시스템의 일부든, 외부 시스템이든 말이죠.

OAuth 는 그런 구조적 보안 위협을 해결하기 위해 탄생했습니다.
아래 링크는 OAuth 1.0 의 서문(소개)입니다.

물론 이 스펙은 OAuth 2.0 에 의해 폐기되었습니다만, 그 출발점이 무엇인지를 보다 명확히 알려줍니다.


OAuth provides a method for clients to access server resources on
behalf of a resource owner (such as a different client or an end-
user). It also provides a process for end-users to authorize third-
party access to their server resources without sharing their
credentials (typically, a username and password pair), using user-
agent redirections.

For example, a web user (resource owner) can grant a printing service
(client) access to her private photos stored at a photo sharing
service (server), without sharing her username and password with the
printing service. Instead, she authenticates directly with the photo
sharing service which issues the printing service delegation-specific
credentials.

OAuth 2.0 은 외부 시스템에 사용자의 데이터를 안전하게 제공하는 것에 집중합니다. 즉,

  • 외부 시스템(클라이언트)에게,
  • 우리가 보호하는 사용자의 데이터를,
  • 사용자의 로그인 정보를 노출하지 않고,
  • 사용자가 허락한 범위 내에서,

제공하는 것이 목표입니다.

말로만 떠드는 내용이 생각보다 길어지고 있어 여기에서 일단 끊겠습니다.

6개의 좋아요