웹 프로젝트 (IBAS)/SpringBoot api 개편

[RFC 표준] OAuth 2.0를 쉽고 정확하게 알아보자! (기초 개념 및 용어 정리)

동현 유 2022. 5. 8. 23:24

[OAuth 프로토콜이란?]

  어떤 회사가 자신의 서비스를 운영하기 위해 어떤 리소스가 필요하다고 가정하자. 근데, 해당 리소스를 처음부터 수집하고 가공하는 일은 노력이 많이들기도 하고, 서비스 사용자에게도 불편한 경험이 될 수 있다. 이 때 구글이나 네이버 같은 대기업에서는 당사에서 미리 만들어 놓은 리소스를 사용할 수 있도록 api 를 공개하는 경우가 있다. 이 때 구글, 네이버 같은 기관은  OAuth provider 라고 말한다. 이 리소스는 민감한 정보(사용자의 개인정보 등)를 포함할 수 있기 때문에 안전하게 미리 약속된 방식으로 데이터를 주고 받을 필요가 있다.

  이처럼 에서 HTTP 상으로 정보를 안전하게 주고 받을 수 있도록 통일한 규약을 OAuth 프로토콜이라고 한다.


1. 구성요소 4가지

아래는 OAuth 프로토콜 상에서 정의되는 4가지 역할에 대한 간단한 개념을 설명한다.

1.1 OAuth에서의 4가지 역할

  • resource owner : 리소스 소유자로서, 해당 리소스로의 접근을 허락할 수 있는 주체이다. 사람인 경우에는 end-user 라고 한다. (ex. 개인정보의 resource owner 는 end-user이다.)
  • resource server : 리소소를 hosting 하는 서버를 말하며, access 토큰을 이용해 리소스 요청을 받고 응답한다. (ex. end-user 의 개인정보를 저장하고 있는 naver 서버)
  • client : resource owner를 대신해서 리소스 요청하는 application (ex. 소셜로그인을 통해 사용자의 개인정보를 가져오는 온라인 게임 서비스)
  • authorization server : resource owner 임을 성공적으로 확인한 후에 client 에게 access token 을 발급하는 서버.

  개념상으로는 resource serverauthorization server 가 분리되어 있지만, 물리적으로는 하나로 합쳐져 있을수도 있고, 여러대로 나뉘어 있을수도 있다. 보통 관념상 resource serverauthorization server 를 한 기업에서 담당하는 경우가 많기 때문에 (예를 들어 네이버나 구글 등), oauth 프로토콜을 잘 따르면서 이 두가지의 서버를 갖고 관련 서비스를 제공하는 기업을 oauth provider 라고 하는 듯하다.


2. 프로토콜 흐름

1.2 프로토콜 흐름도

  

위의 프로토콜 흐름도가 잘 이해되지 않는다면, OAuth 4가지 역할 부분의 그림을 참고해도 된다.

이해를 돕기 위해 소셜로그인 상황을 떠올려보자. 그러면 아래와 같이 구체화할 수 있다.

(단 OAuth에서의 Client(모바일 어플 등)와 Resource owner(client 입장에서의 사용자)와 혼동하면 안된다!)

  • Client - 모바일 어플리케이션
  • Resource Owner - 해당 앱을 사용하는 사용자
  • Authorization server & Resource server - 구글, 네이버 등 

 

  1.  모바일 앱사용자에게 개인정보에 대한 허가를 요청한다. 직접적으로 요청하는 방법도 있지만 가장 흔히 접하는 경우는 authorization server 를 이용해서 간접적으로 요청하는 방법이다. 예로 네이버 소셜로그인 할 때, 네이버에서 제공하는 로그인 창이 나타난 걸 본 경험이 있을 것이다.
  2.  모바일 앱은 요청이 허가되었음을 확인한다. 사용자가 해당 리소스 사용에 대한 요청을 허가했다는 응답을 authorization grant 라고 하며, grant 하는 방법 여러가지이다. 표준에 명시적으로 정의된 4가지 방법(authorization code/implicit/resource owner password credentials/client credentials)과 extension grant type 으로 나뉜다.
  3.  모바일 앱authorization grant 결과를 바탕으로 authorization server 에 access token 을 요청한다. 이 때 현재 요청하는 모바일 앱이 정당한 oauth 이용자인지 인증하는 과정을 포함한다. (client id, client secret 등으로 검사)
  4.  Authorization server모바일 앱에 대한 인증을 수행하고, 모바일 앱이 제출한 authorization grant 결과가 유효한지 검사한다. 모두 다 유효하면 access 토큰을 발급한다.
  5. 모바일 앱은 access 을 제시함으로써 resource server 에 리소스 요청을 할 수 있다.
  6.  Resource server 는 해당 토큰이 유효하다면, 요청을 처리한다.

3. Authorization Grant Type

  authorization grant 는 resource owner가 client로 하여금 해당 리소스를 사용해도 된다고 허락한 것을 의미하며, 4가지의 방식이 존재한다.

(1) Authorization Code

  resource owner 가 사용허가를  application(oauth client)에 직접하지 않고, authorization server 에게 간접적으로 하는 방식이다. resource owner 가 authorization server 에 직접 허가를 한 뒤에 허가의 증거로 auth server 는 임시 코드를 발급해준다. client 는 이 임시 코드를 application 에 제출하게 되고, 최종적으로 application이 임시코드(resource owner의 허락 증거물)를 authorization server 에 제출함으로써 허락이 완료된다. (이 때 oauth client 자체에 대한 인증까지 완료되면 access 토큰이 발급된다.) 임시토큰을 authorization code 라고 한다. 

  이 방식은 oauth client 대한 인증 뿐만 아니라, access token 을 외부 노출 없이 안전하게 전달할 수 있다는 장점이 있다.

(2) Implicit

  authorization code 의 간소화된 방식으로, 스크립트 언어를 사용하는 in-browser application 형태의 client 에서 주로 사용한다. authorization code 대신에 access token 을 바로 발급받는다. application(client) 자체에 대한 인증도 이루어지지 않는다.(경우에 따라서 redirection uri 방식으로 지원하는 경우도 있음)

  절차가 간단하기 때문에 더 효율적이라는 장점이 있지만, access token 이 노출될 수 있다는 보안상 취약점이 존재한다.

(3) resource owner password credentials

  username and password 등의 방식이다. 자원 소유자의 비밀번호가 직접적으로 access token 을 얻는데 사용된다. authorization code 대신 owner 의 password를 전달한다고 생각하면 된다. 모바일 os 등 접근이 제한된 client 에게 적용가능한다. 즉 resource owner 와 client 사이의 신뢰가 높아야한다. resource owner의 정보를 client가 직접 다루기 때문에 다른 인증 방법이 불가할 때만 사용하도록 권장된다.

(4) client credentials

  client가 소유하고 있는 어떤 정보가 그 자체로 authorization grant 로 사용된다. client가 스스로 resource server 의 역할을 할 때나, 기존에 authorization server에 의해 허가된 인증(access token 등)을 재사용하는 경우 등에서 사용된다.


4. Access & Refresh token

(1) access 토큰, refresh 토큰 의미

  • protected resource를 요청할 때는 꼭 액세스 토큰을 제시해야한다. 토큰은 client에게 발행된 인증에 관한 내용을 담는 암호화된 문자열이다. 인증 범위나 인증 기간 등의 정보를 포함하는데, resource owner 에 의해 grant 되어야하는 부분이다. 액세스 토큰 자체에 대한 권장사항은 RFC6750 을 참고해야함.
  • 리프레시 토큰은 액세스 토큰과 비슷한 형태를 띄고 있는데, 보통 액세스 토큰보다 만료기간 길다는 차이가 있다. 이는 보안상의 문제로 인한 절충안인데, 만약 만료기간인 긴 토큰이 갈취당했을 경우를 생각해보자. 그러면 공격자는 해당 토큰이 만료되기 전까지는 protected resource 를 마음껏 요청해서 받아올 수 있다. 이런 위험성을 줄이고자 access token 의 만료기간을 상대적으로 짧게하고, refresh token 를 길게 한다. 그래서 액세스 토큰이 만료되었을 때, refresh token 을 이용하여 새로운 access token 발급을 요청하게 된다.

(2) access 토큰 재발급 시나리오

만료된 access token 갱신하기

  1. 4가지 방법 중 하나의 authorization grant 방법으로 access token 을 요청한다.
  2. client 인증 + authorization grant 유효성 검사 => access 토큰과 refresh 토큰 발행
  3. access token으로 protected resource 요청
  4. access token이 유효하면, 해당 리소스 제공
  5. 토큰이 만료될 때까지 (C)와 (D)를 반복한다. 이후에 만료된 access token으로 protected resource 요청
  6. 만료된 토큰이라고 응답
  7. refresh token으로 새로운 access token 발급해달라고 요청한다. 이 때 client에 대한 인증도 함께 이루어진다.
  8. client 인증 + refresh token 유효성 검사 => access token 을 재발급(경우에 따라 refresh token 도 재발급 가능)

[Client Registration]

  프로토콜을 이용하기 전에, client는 authorization server 에 등록되어 있어야한다. 각 provider에 client를 등록하는 방법에 대해서는 정확한 규정이 없다. client가 authorization server 사이에 직접적으로 등록될 필요도 없다. redirect URI, client type 등의 필요한 client 정보를 얻을 수 있는 신뢰할 만한 어떤 채널을 통해 간접적으로 등록될 수 있다.


1. Client Types

(1) 기밀성에 따른 분류

authorization server 와 얼마나 안전하게 인증할 수 있는지에 따라 confidential과 public 으로 나눌 수 있다. 이렇게 나누는 목적은 authorization server 입장에서 client의 안전성에 따라 resource의 공개 범위를 결정하게 하기 위함이다. 

  • confidential : 기밀성을 유지할 수 있는 client를 의미. 안전한 server에 접근 권한이 철저하게 제한된 서버등을 예로 들 수 있다.
  • public : 기밀성을 유지할 수 없는 client 를 의미, resource 나 토큰이 그대로 노출된다. resource owner가 소유하고 있는 device 등을 예로 들 수 있는데, native application이나 web brower-based application 등이 있다.

(2) type에 따른 client 예시

한 클라이언트는 여러 components로 구성될 수 있는데, 각각의 component가 각자 다른 client type과 security context를 갖는다면 (ex, 웹앱과 모바일 네이티브 앱), 각각의 구성요소를 authorization server 에 등록해야한다. 대표적인 client 의 예시는 다음과 같다.

  • web app
      : 웹앱은 웹서버에서 운영되는 confidential client 이다. 클라이언트 자체 정보나 resource owner의 토큰 등은 모두 웹서버에 저장되고, resource owner 가 접근 불가능하다.
  • user-agent-based app
      : public client 이다. client 의 코드를 웹 서버로부터 다운받을 수 있고, 인증 정보에 접근가능하다. 
  • native app
      : public client 이다. resource owner 의 device에 의해 설치 및 실행되고, resource owner 가 쉽게 추출할 수 있다. 뿐만 아니라 같은 장치 내의 다른 어플리케이션이 쉽게 접근할 수도 있다.

2. Client Authentication

  client identification을 확인하고 싶다면, authorization server 와 client 간의 인증절차를 거쳐야한다. Confidential clients는 인증에 필요한 정보를 authorization server 와 나눠 가질 수 있다. (ex, password, public/private key pair, etc.) 하지만 public clients 에 대해서는 identify 를 목적으로 인증을 할 수 없다. public client 임을 증명할 수 있는 어떤 데이터가 있다고 하더라고, 충분히 갈취당할 수 있기 때문이다. confidential clients 인증 방법에는 아래와 같은 방법이 존재한다.

  • Client Password
      : Http basic 인증 방식(RFC2617)을 사용한다. Authorization 헤더에 "Basic $(password)" 형태로 담아서 전송해도 되고, 또는 request-body에 client_id와 client_secret을 담아서 보내도 된다. 하지만 직접적으로 request-body에 클라이언트 정보를 담는 것을 권장되지 않고, 직접적으로 HTTP Basic 인증 방식을 사용할 수 없는 경우에만 이용하도록 제한한다. request-body에 포함될 정보를 request-uri에 절대로 담아서는 안된다. 액세스 토큰 재발급 요청을 예로 들면 다음과 같다. 

액세스 토큰 재발급 요청 예시

  • Other Authentication Methods
      : 다른 적당한 HTTP 인증 방식을 사용할 수 있다.

[Protocal Endpoints]

 인증과정에서 필요한 서로 다른 두 인증 객체 사이의 endpoint를 다음과 같이 정의할 수 있다.

  • Authorization endpoint
      : resource owner 로 부터 authorization grant를 받기 위해 사용됨. (user-agent redirection 방식) authorization server가 client에게 authorization grant를 전달하기 위해서는 Redirection endpoint를 이용함.
  • Token endpoint
      : client 가 access token을 위해 authorization grant를 제출할 때 사용됨

[출처]

https://datatracker.ietf.org/doc/html/rfc6749

https://oauth.net/2/