OAuth

김하영·2021년 4월 5일
1

OAuth 개념

- OAuth란 무엇인가?

위와 같이 별도의 회원가입 없이 로그인을 제공하는 플랫폼의 아이디만 있으면 서비스를 이용 할 수 있다.
외부 서비스에서도 인증을 가능하게 하고 그 서비스의 API를 이용하게 해주는 것을 OAuth 라고 한다.

OAuth 2.0은 다양한 플랫폼 환경에서 권한 부여를 위한 산업 표준 프로토콜이다.
간단하게 인증(Authentication)과 권한(Authorization)을 획득하는 것으로 볼 수 있다.

  • 인증은 시스템 접근을 확인하는 것 (로그인) -> 인증만 하는 것은 openID
  • 권한은 행위의 권리를 검증하는 것

OAuth는 인터넷 사용자들이 비밀번호를 제공하지 않고 다른 웹사이트 상의 자신들의 정보에 대해 웹사이트나 애플리케이션의 접근 권한을 부여할 수 있는 공통적인 수단으로서 사용되는 접근 위임을 위한 개방형 표준이다.

이 매커니즘은 여러 기업들에 의해 사용되는데, 이를테면 아마존, 구글, 페이스북, 마이크로소프트, 트위터가 있으며 사용자들이 타사 애플리케이션이나 웹사이트의 계정에 관한 정보를 공유할 수 있게 허용한다.

OAuth2 의 네 가지 역할

OAuth2에서 정의된 역할들을 앱(Client), 데이터 제공기관(Resource Server), 권한 제공기관(Authorization Server), 그리고 사용자(Resource Owner)라고 명칭한다.

1. 앱(Client)
앱은 사용자 데이터를 활용하여 서비스를 제공하려는 응용프로그램이다.
앱이 사용자 데이터에 접근할 권한을 요청하면서 OAuth2의 절차적 흐름이 시작되고 앱이 사용자 데이터를 받게 되면 끝난다.

2. 데이터 제공기관(Resource Server)
데이터 제공기관은 사용자의 데이터를 보유하고 유효한 접근 권한을 부여 받은 앱이 요청하면 사용자 데이터를 제공하기도 하는 서버를 의미한다. 경우에 따라 데이터 보유기관이라고 일컬어지는 경우도 있다.
데이터 제공기관은 앱이 접근 토큰을 사용자 데이터와 교환할 수 있는 API를 제공하는 기관이기도 하다.

3. 권한 제공기관(Authorization Server)
권한 제공기관은 사용자 데이터에 접근한 권한을 제공하는 서버이다.
앱의 접근 요청에 따라 사용자에게 앱에 대해 등록된 정보 및 앱이 요청한 데이터 항목, 활용하려는 목적 및 기간 등에 대한 정보를 제시하고 사용자의 동의 여부를 문의하는 역할을 한다.

소규모 시스템의 경우 하나의 개체가 권한 제공기관과 데이터 제공기관의 2가지 역할을 수행하는 경우도 있으나, 규모가 클수록 권한 제공기관과 데이터 제공기관을 분리해서 구현하는 경우가 많다.

4. 사용자(Resource Owner)
사용자는 OAuth2의 최고 권력자이다.
데이터 제공기관 입장에서는 데이터 보호를 부탁한 고객이고 앱의 입장에서는 가치를 창출하기 위해 필요한 데이터의 주인이다.

사용자는 임의로 자신의 데이터에 대한 접근 권한을 부여, 거부 또는 철회를 할 수 있는 데이터 주체이다.
사용자는 제공할 데이터의 범위 및 기간 등에 대한 결정도 내릴 수 있다.

인가 서버와 리소스 서버 간의 상호 작용은 이 명세의 범위를 벗어난다.
인가 서버는 리소스 서버와 같거나 별개로 구분할 수 있다.
하나의 인가 서버는 여러 리소스 서버에 의해 여러 개의 접근 토큰을 발급할 수도 있다.

프로토콜 흐름

그림 1에 설명된 OAuth 2.0의 추상적인 흐름은 네 가지 역할 간의 상호작용을 기술하며 다음 단계를 포함한다:

(A) 클라이언트는 리소스 소유자로부터의 인가를 요청한다. 인가 요청은 (그림처럼) 리소스 소유자에게 직접 요청할 수도 있지만, 중간의 인증 서버를 통해 간접적으로 하는 것이 바람직하다.

(B) 클라이언트는 리소스 소유자의 인가를 나타내는 자격 증명인 승인 인가를 받는다.
승인 인가는 이 명세에서 정의된 네 개의 승인 유형 중 하나 또는 확장된 승인 유형으로 발행된다.
인가 승인 형식은 클라이언트가 인가를 요청하는 방법과 인가 서버가 지원하는 유형에 의존한다.

(C) 클라이언트는 인가 서버에 인증하고 인가 승인을 제시함으로써 접근 토큰을 요청한다.

(D) 인가 서버는 클라이언트를 인증하고 인가 승인이 유효한지 확인하고 유효한 경우 접근 토큰을 발급한다.

(E) 클라이언트는 리소스 서버에 보호된 리소스를 요청하고 접근 토큰을 제시함으로써 인증한다.

(F) 리소스 서버는 접근 토큰이 유효한지 확인하고, 유효한 경우 요청을 받아들인다.

인가 승인

인가 승인은 클라이언트가 접근 토큰을 얻기 위해 사용되는 것으로 리소스 소유자 (보호된 리소스에 대한 접근)의 인가를 나타내는 자격 증명이다. 이 명세는 네 가지 승인 유형(인가 코드, 암시적 승인, 리소스 소유자 패스워드 자격 증명, 클라이언트 자격 증명)과 추가적인 유형 정의를 위한 확장성 메커니즘을 정의한다.

1. 인가 코드

인가 코드는 클라이언트와 리소스 소유자 사이에 중개자로서 인가 서버를 사용하여 획득된다.
리소스 소유자에게 인가를 직접 요청하는 대신 클라이언트는 리소스 소유자를 인가 서버로 안내하고 인가 서버는 자원 소유자를 인가 코드와 함께 클라이언트에게 되돌려보내면서 인가 서버는 리소스 소유자를 인증하고 클라이언트는 인가 코드를 획득한다. 리소스 소유자는 오직 인가 서버로만 인증하기 때문에, 리소스 소유자의 자격 증명은 절대 클라이언트와 공유되지 않는다. 인가 코드는 클라이언트를 인증하는 능력 뿐만 아니라 접근 토큰을 리소스 소유자의 사용자 에이전트를 거쳐서 잠재적으로 리소스 소유자를 포함한 다른 이들에게 노출하지 않는 것과 같이 소수의 중요한 보안상의 이점을 제공한다.

2. 암시적 승인
암시적 허용은 Javascript와 같은 스크립팅 언어를 사용하는 브라우저에서 구현된 클라이언트에 최적화된 단순화된 인가 코드 흐름이다. 암시적 승인 흐름에서는 (리소스 소유자 인가의 결과로) 클라이언트에게 인가 코드를 발급하는 대신, 클라이언트에게 접근 토큰이 직접 발급된다. (인가 코드와 같은) 중개 자격 증명이 발급되(고 이후에 접근 토큰을 획득하)지 않기 때문에, 이 인가 유형을 암시적 승인으로 부른다.

암시적 승인 흐름에서 접근 토큰을 발급할 때, 인가 서버는 클라이언트를 인증하지 않는다. 특정한 경우에, 클라이언트의 신원은 클라이언트에게 접근 토큰을 전달하기 위해 사용되는 리다이렉션 URI를 통해 확인될 수 있다. 접근 토큰은 리소스 소유자 혹은 리소스 소유자의 사용자 에이전트 접근을 통해 다른 애플리케이션에 노출될 수도 있다.

암시적 승인은, 접근 토큰을 얻기 위한 왕복을 줄이기 때문에 (인 브라우저 애플리케이션으로 구현된 클라이언트와 같은)일부 클라이언트의 반응성과 효율을 향상시킨다. 하지만 이러한 편의성은 암시적 승인을 사용할 때의 보안상의 영향을 고려해야 한다.

3. 리소스 소유자 패스워드 자격 증명
리소스 소유자 패스워드 자격 증명(i.e., 유저네임과 패스워드)은 접근 토큰을 얻는 인가 승인에 직접 사용될 수 있다. 자격 증명은 리소스 소유자와 클라이언트 사이에 높은 신뢰(e.g., 클라이언트가 디바이스 운영 체제 혹은 높은 권한을 가진 애플리케이션인 경우)가 있으며, (인가 코드와 같은)다른 인가 승인 유형을 사용할 수 없는 경우에만 사용되어야 한다.

이 승인 유형이 리소스 소유자의 자격 증명에 직접 접근해야 함에도 불구하고, 리소스 소유자 자격 증명이 하나의 요청과 접근 토큰으로 교환하는 데 사용된다. 이 승인 유형은 자격 증명을 긴 수명을 가진 접근 토큰이나 갱신 토큰으로 교환함으로써, 클라이언트가 리소스 소유자의 자격 증명을 미래의 사용을 대비해 저장할 필요가 없도록 할 수 있다.

4. 클라이언트 자격 증명
인가 범위가 클라이언트의 통제 아래에 있는 보호된 리소스이거나 미리 인가 서버와 조정된 보호된 리소스로 제한된 경우, 클라이언트 자격 증명(혹은 클라이언트 인증의 다른 방식)이 인가 승인으로 사용될 수 있다.
클라이언트 자격 증명은 보통 클라이언트가 자기 자신을 대신하여(클라이언트가 리소스 소유자이기도 하여) 행동하고 있는 경우 혹은 미리 인가 서버와 조정된 보호된 리소스에 대한 접근 요청인 경우 사용될 수 있다.

OAuth2 에 사용되는 데이터

1. 앱의 등록정보
OAuth2가 작동하기 위해서 앱은 사전에 권한 제공기관에 등록해야 한다.
새로운 앱이 등록할 때 일반적으로 앱이 제공할 서비스의 명칭, 웹사이트, 로고 등의 기본정보를 제출한다.
웹서버 앱, 브라우저 기반 앱 또는 모바일 앱의 경우에는 반드시 Redirect URI에 대한 정보를 추가적으로 등록해야 한다.

2. Redirect URI
권한 제공기관은 사용자가 앱에게 권한 부여하는 것에 사용자가 동의하면 사용자를 앱의 등록된 Redirect URI로 이동(redirection)시킨다. 만일 등록되지 않은 Redirect URI를 담은 요청을 받게 되면 그 요청은 무효 처리된다.
기존에 등록된 Redirect URI의 범위에 한해서 사용자를 연결시킴으로써 방지할 수 있는 공격들이 있기 때문이다.

모든 HTTP 기반 Redirect URI는 반드시TLS 로 보안이 되어있어야 하므로 “https”로 시작하는 URI만 등록이 가능하다.
이 제약조건이 존재하는 이유는 승인 과정에서 토큰 노출에 대한 방어를 하기 위해서이다.

3. Client ID와 Client Secret
새로 등록하는 앱은 권한 제공기관으로부터Client ID와 Client Secret을 발급받는다.
Client ID는 공개하는 정보로서 로그인 웹 페이지 또는 JavaScript에 포함될 수 있는 정보이다.
반면에 Client Secret은 노출되면 안되는 정보이다.

Client Secret의 노출을 방지할 수 없는 Single-Page JavaScript 앱 또는 Native 앱의 경우 Client Secret을 사용하지 않는다. 이럴 경우 애초부터 Client Secret을 발급하지 않는게 바람직하다.

OAuth 매커니즘

- OAuth2의 토큰(Token)

OAuth2가 지원하는 여러가지 권한 부여 방식들의 공통점은 토큰을 사용한다는 점이다.
토큰의 종류로 접근 토큰(Access Token)과 재생 토큰(Refresh Token)이 있다.
하지만 OAuth2에서는 접근 토큰 및 재생 토큰이 가져야 할 특정한 형식을 지정하고 있지 않다.
다시 말해, 개발자가 임의로 토큰을 구현할 수 있도록 설계된 것이다.

실제로 현실에서는 대부분의 경우 토큰을 JWT 형식으로 구현하고 있다.

  1. 접근 토큰(Access Token)
    접근 토큰은 사용자의 데이터에 접근하기 위해 필요한 자격증명으로서 사용자가 특정 앱에게 부여한 권한에 대한 정보가 담긴 문자열이다.
    접근 토큰에는 접근할 수 있는 특정 scope들과 접근 가능한 기간 등 사용자가 동의한 사항들에 대한 정보가 담겨 있다.
    이 정보에 기반하여 권한 제공기관 및 데이터 제공기관은 앱의 요청에 응하게 된다.

  2. 재생 토큰(Refresh Token)
    누구든지 유효한 접근 토큰을 보유하면 통제된 데이터에 접근할 수 있게 된다.
    따라서 접근 토큰이 노출될 리스크를 감안해서 피해를 최소화하기 위해 일반적으로 접근 토큰의 유효기간을 짧게 설정한다.
    접근 토큰의 유효기간이 만료되었을 경우를 대비하여 앱 개발자는 재생 토큰을 사용할 수 있다.
    재생 토큰을 활용하면 사용자에게 인증을 반복하게 하지 않고도 접근 토큰을 새로 발급 받을 수 있게 된다.

OAuth2의 프로토콜 흐름(Protocol Flow)

(A) (앱→사용자)
사용자 데이터에 접근하기 위한 권한을 요청한다.
개념상 앱이 사용자에게 요청하지만, 실제 구현은 앱과 사용자 사이에 권한 제공기관이 중개 역할을 하는 경우가 일반적이다.

(B) (사용자→앱)
접근에 동의함을 증명하는 권한 부여 동의서(Authorization Grant)를 발급한다.
RFC 6749에서는 4가지 유형의 권한 부여 동의서를 정의하고 있다.
앱의 유형 및 권한 제공기관의 지원 여부에 따라 사용할 권한 부여 동의서의 유형이 결정된다.

(C) (앱→권한 제공기관)
권한 부여 동의서를 제출하여 접근 토큰을 요청한다.
접근 토큰은 사용자 데이터를 잠근 자물쇠를 여는 열쇠이다.

(D) (권한 제공기관→앱)
권한 부여 동의서를 확인하여 사용자가 동의한 데이터 항목, 범위 및 기간 등에 대한 정보가 담긴 접근 토큰을 제공한다.
즉, 사용자 데이터에 접근할 때 사용할 열쇠를 제공하는 셈이다.

(E) (앱→데이터 제공기관)
접근 토큰을 제출하여 사용자 데이터를 요청한다.

(F) (데이터 제공기관→앱)
사용자 데이터를 제공한다.
이때 앱이 제출한 접근 토큰이 유효함을 확인하고, 접근 토큰의 정보를 확인하여 제공할 데이터 항목, 범위 및 유효기간이 정해진다.

OAuth2의 권한 부여 동의서(Authorization Grant)

접근 토큰을 요청하기 전에 앱은 사용자로부터 권한 부여에 대한 동의를 받아야 한다.
사용자의 동의는 권한 부여 동의서(Authorization Grant)의 형태로 제공된다.
권한 부여 동의서는 사용자가 데이터 접근을 허가했음을 나타내는 증명서로서 사용자가 앱에게 발급한다.
권한 부여 동의서를 근거로 앱은 권한 제공기관에게 사용자 데이터에 접근할 권한을 요청할 수 있다.

OAuth2는 4가지 유형의 권한 부여 동의서를 정의하고 있다.
승인 코드, 암묵적 동의, 사용자 비밀번호 유형, 그리고 앱 인증 유형이 있다.

새로운 유형을 추가할 수 있는 확장 메커니즘도 지원한다.

1. 승인 코드(Authorization Code) 유형
사용자가 권한 제공기관에 연결하여 인증받고 권한 부여에 동의하면 승인 코드를 발급하는 유형이다.

승인 코드 유형은 신뢰성 높은 앱이 사용하기에 최적화 되어 있다.
승인 코드를 사용할 경우 접근 토큰 뿐만아니라 재생 토큰도 요청할 수 있다.
승인 코드는 리디렉션 기반 절차를 활용하기 때문에 앱은 사용자의 에이전트(user-agent)를 통해 사용자와 상호작용할 수 있어야 하며 또한 권한 제공기관으로부터 Redirection URI에서 요청을 수신할 수 있어야 한다.

승인 코드 유형 권한 부여의 절차적 흐름은 다음과 같다.

제3자 앱 및 서비스들에게 데이터를 자주 제공하는 플랫폼을 구축하고자 한다면 승인 코드를 활용하는 것이 가장 안전하다. 승인 코드를 활용한 권한 부여 방식의 절차적 흐름은 다음과 같다.

(A) 앱은 user-agent 상으로 사용자를 권한 제공기관의 Authorization endpoint로 안내한다.
이때 앱은 앱의 식별자, 요청하는 scope, 로컬 상태 및 Redirection URI에 대한 정보도 함께 전송한다. 사용자가 접근 권한 부여에 동의하면 권한 제공기관은 사용자를 Redirection URI로 이동시키게 된다.

(B) 권한 제공기관은 사용자에 대한 인증을 수행하고 앱의 접근 요청에 대한 사용자의 동의 여부를 확인한다.

(C) 사용자가 앱의 접근에 동의하면 권한 제공기관은 승인 코드를 발급하고 앱이 요청한 Redirection URI로 user-agent를 안내한다. 이때 사용되는 Redirection URI에 승인 코드와 앱이 요청 시 제출한 로컬 상태에 대한 정보가 포함된다.

(D) 앱은 발급받은 승인 코드를 권한 제공기관의 Token endpoint에 제출하고 접근 토큰을 요청한다. 이 때 앱에 대한 인증 정보와 함께 앱이 승인 코드를 제공받은 Redirection URI를 제출함으로써 권한 제공기관은 앱의 요청이 유효함을 검증할 수 있도록 한다.

(E) 권한 제공기관은 앱을 인증하고 승인 코드가 유효함을 확인하며, 접근 토큰 요청에 제출된 Redirection URI가 승인 코드를 발급한 Redirection URI와 일치함을 확인한다. 모든 사항에 문제 없음이 확인되면, 권한 제공기관은 접근 토큰을 발급한다. 이때 요청되었을 경우 재생 토큰도 함께 제공한다.

2. 암묵적(Implicit) 유형

승인 코드 방식과 유사하나 사용자가 권한 제공기관에 인증받은 후 승인 코드 대신에 접근 토큰을 바로 발급하는 유형이다.

암묵적 유형의 권한 부여 방식은 단일 페이지(Single Page) JavaScript 앱을 위해 만들어진 방식이다. 암묵적 유형의 권한 부여 방식의 절차적 흐름은 승인 코드 방식의 절차적 흐름과 매우 흡사하다.
차이점은 권한 제공기관로부터 승인 코드를 발급받지 않고 대신 바로 접근 토큰을 발급 받는다는 점이다.
보안을 유지하기 위해 Implicit 방식에서 재생 토큰은 금지되어 있다.

암묵적 유형 권한 부여의 절차적 흐름은 다음과 같다.

3. 사용자 비밀번호 인증(Resource Owner Password Credentials) 유형
사용자가 앱 상으로 ID/비밀번호로 로그인하여 인증하고 권한 부여에 동의하면 접근 토큰을 발급하는 유형이다.

사용자 비밀번호 인증 유형의 권한 부여 방식은 앱이 운영체제일 경우와 같이 사용자와 앱 사이에 높은 신뢰가 형성된 경우에 적합하다. 권한 제공기관은 다른 유형의 권한 부여 방식이 불가한 특수한 경우에만 사용자 비밀번호 인증 방식이 사용되도록 주의를 기울여야 한다.

사용자 비밀번호 인증 유형 권한 부여의 절차적 흐름은 다음과 같다.

4. 앱 인증(Client Credentials) 유형

권한 소유자가 앱인 경우 앱이 발급 받은 Client ID와 Client Secret을 확인하여 앱에 대한 인증을 수행하고 권한을 부여 받는 유형이다.

앱 인증 방식은 사용자가 앱인 경우에 활용된다.
앱 인증(Client Credentials) 유형을 사용하는 방법은 사용자 비밀번호 인증 유형을 사용하는 방법과 유사하다.
사용자 비밀번호 인증 방식에서 사용자 ID와 비밀번호가 사용되듯이 앱 인증 방식에서는 Client ID와 Client Secret을 통해 앱을 인증한다.

인증에 성공하면 권한 제공기관은 앱에게 접근 토큰을 발급하게 된다. 앱 인증 방식은 재생 토큰 사용을 금지한다.

앱 인증 유형 권한 부여의 절차적 흐름은 다음과 같다.

OAuth 구현 예제

- 스프링 시큐리티와 OAuth 2.0으로 로그인 기능 구현

OAuth 구현 예제 포스팅

OAuth 적용 사례

https://imweb.me/faq?mode=view&category=30&category2=42&idx=4647

네이버, 카카오, 페이스북 중 하나의 도메인에 로그인을 하면 해당 사이트 로그인이 가능하다.

  • 참고

https://kimdoky.github.io/oauth/2019/05/01/oauth-serverside-flow/

https://developers.facebook.com/docs/permissions/reference (페이스북)

https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api (카카오)

profile
Back-end Developer

0개의 댓글