OAuth 2.0

2024. 2. 9. 16:12카테고리 없음

1. What is OAuth2.0?

OAuth2.0은 웹사이트나 애플리케이션같은 제3자 애플리케이션이 사용자의 리소스에 접근할 수 있도록 사용자가 권한을 위임할 수 있도록 지원하는 표준 프로토콜입니다. 대표적인 사례로 구글은 OAuth2.0 프로토콜 기반 서비스를 지원하고 있습니다. 사용자는 구글 로그인을 하고 애플리케이션에게 구글에 저장된 사용자의 정보 일부분에 접근할 수 있는 권한을 부여합니다. 권한을 부여받은 애플리케이션은 구글의 사용자 정보에 접근하여 서비스를 제공합니다. 예를 들어 사용자는 애플리케이션에게 프로필 정보에 접근할 수 있는 권한을 부여하면 애플리케이션은 사용자의 프로필 정보에 접근하여 해당 애플리케이션 사용자 계정의 프로필로 사용할 수 있도록 제공할 수 있습니다.

 

OAuth2.0을 사용하면 좋은 점은 사용자의 입장에서는 애플리케이션에 아이디와 비밀번호를 공유하지 않고도(별도의 회원가입 및 로그인 없이) 애플리케이션이 사용자를 대신해 특정한 작업을 수행할 수 있도록 하는 점이 좋습니다. 즉, OAuth2.0은 로그인 과정 자체를 담당하지 않고 이미 로그인한 사용자의 자원에 대한 접근 권한을 제 3자 애플리케이션에 부여하는 역할을 수행하는 것입니다.

 

1.1 Why use OAuth2.0

OAuth2.0 프로토콜을 사용하는 이유는 제 3자 애플리케이션을 사용자 아이디와 비밀번호 없이 인증하는 매커니즘이 포함되어 있기 때문입니다. OAuth2.0을 사용하면 사용자는 신뢰할 수 있는 서비스 제공자인 구글과 같은 곳을 통해 제 3자 애플리케이션에 리소스에 접근할 수 있는 권한을 위임할 수 있습니다. 이때 구글과 같은 서비스 제공자는 사용자의 신원정보를 인증하고 권한 위임의 결과인 authorization code라는 정보로 제 3자 애플리케이션에 전달하는 것입니다.

 

1.2 OAuth 장점

OAuth를 사용할 때의 장점을 페이스북 API를 사용하는 앱을 예시로 설명합니다.

 

  • 특정한 권한만을 가진 액세스 토큰을 생성할 수 있습니다. 예를 들어 페이스북 API를 사용할 때 읽기 권한만 가진 액세스 토큰만 만들 수 있습니다. 애플리케이션이 페이스북 인증을 지원하고 읽기 전용 토큰만 사용한다면 이 앱은 액세스 토큰으로 페이스북 글을 작성할 수 없습니다.
  • 사용자의 ID와 비밀번호가 필요하지 않습니다. 예를 들어 페이스북 인증을 사용하는 모바일 애플리케이션은 사용자의 ID와 비밀번호가 필요하지 않습니다. 사용자는 페이스북에서 로그인하면 페이스북은 모바일 애플리케이션에 사용자가 승인한 권한(ex, 읽기 권한)만 있는 액세스 토큰을 전달하기 때문입니다.
  • 필요에 따라 액세스 토큰을 즉각 폐기 처리할 수 있습니다.
  • 플랫폼(웹, 모바일, 네이티브 등)에 상관없이 API의 접근 제한을 쉽게 할 수 있습니다.

 

1.3 Differences Between OAuth 1.0 and 2.0

OAuth2.0은 OAuth1.0을 처음부터 완전히 다시 작성한 것으로, 전체 목표와 일반 사용자 경험만을 공유합니다. OAuth2.0은 OAuth 1.0 또는 1.1과 역호환(backwards compatible)되지 않으므로 완전히 새로운 프로토콜로 간주해야 합니다.

 

OAuth 1.0은 주로 Flickr의 authorization API와 구글의 AuthSub의 두가지 독점 프로토콜을 기반으로 하고 있습니다. OAuth 1.0이 되었던 작업은 당시 실제 구현 경험을 바탕으로 한 최고의 솔루션이었습니다. 몇년동안 많은 회사들이 OAuth 1.0 API를 구현하고 많은 개발자들이 API를 사용하기 위해서 코드를 구현하면서 커뮤니티는 OAuth 1.0 프로토콜이 사람들에게 구현하는데 어렵다는 것을 알게 되었습니다. 일부 특정 지역에서는 API의 기능들을 제한하거나 구현하기가 어려워 개선이 필요하였습니다.

 

OAuth 2.0은Yahoo!, Facebook, Salesforce, Microsoft, Twitter, Deutsche Telekom, Intuit, Mozilla 그리고 Google을 포함한 광범위한 기업과 개인 간의 수년간의 논의한 것을 나타냅니다.

 

이 장에서는 OAuth 1.0과 OAuth 2.0 사이에 주요 차이점과 배경 동기에 대해서 다룹니다.만약 여러분들이 OAuth 1.0에 익숙하다면, OAuth 2.0에서의 주요 변경점들을 빠르게 이해하는 좋은 포인트일 것입니다.

 

1.3.1 Terminology and Roles

OAuth 2.0이 4가지 역할들을 정의할 때(client, authorization server, resource server, resource owner), OAuth 1.0은 이러한 역할들에 대해서 다른 용어들을 사용합니다. OAuth 2.0의 "client"는 "consumer"로 알려져 있고, "resource owner"는 간단하게 "user", "resource server"는 "service provider"로 알려져 있습니다. OAuth 1.0은 또한 resource server와 authorization server의 역할을 명확하게 구분짓지 않습니다.

 

"two-legged"과 "three-legged" 용어는 Client Credentials Grant Type과 Authorization Code Grant Type과 같은 Grant Type이라는 용어로 대체되었습니다.

1.3.2 Summary

OAuth 2.0은 OAuth 1.0과는 호환되지 않는 완전히 다른 프로토콜입니다. OAuth 1.0 프로토콜은 개발자들이 구현하는데 어렵고 일부 특정 지역에서는 API 기능을 제한하거나 구현하기가 어려워 개선이 필요하였습니다. OAuth 1.0의 consumer는 OAuth 2.0의 client, user는 "resource owner"로, "service provider"는 "resource server"로 역할이 알려져 있습니다. OAuth 1.0은 resource server와 authorization server의 역할을 명확하게 구분짓지 않지만 OAuth 2.0은 명확하게 구분짓습니다. 마지막으로 OAuth 1.0의 "two-legged"과 "three-legged"라는 용어는 OAuth 2.0에서는 Client Credentials Grant Type과 Authorization Code Grant Type라는 용어로 대체되었습니다.

 

1.4 OAuth2.0 Terms

 

  • Resource Owner : 보호된 리소스에 접근하는 승인해주는 사용자, 일반적으로 이 리소스는 최종 사용자의 정보가 됩니다.
  • Client : 사용자를 대신하여 사용자 리소스에 접근을 요청하는 애플리케이션
  • Resource Server : 보호된 리소스들을 호스팅하는 서버
  • Authorization Server : Resource Owner를 인증하고 적절한 권한을 부여받은 후 Access Token을 발급하는 서버
  • User Agent : Client와 같이 상호작용하기 위해서 Resource Owner에 의해 사용되는 에이전트, 예를 들어 브라우저나 네이티브 애플리케이션이 해당됩니다.
  • Authentication : 리소스 소유자가 자신임을 증명하는 과정입니다. 사용자가 아이디와 비밀번호를 통해 이루어집니다. 인증 과정을 통과한 사용자는 사용자에 대한 정보 접근 권한을 가지게 됩니다.
  • Authorization : 인증된 사용자에게 특정 리소스에 접근하는 권한을 부여하는 과정입니다. 사용자가 특정 애플리케이션을 통해 자신의 정보에 접근하도록 허용하면, 애플리케이션이 사용자의 정보를 읽거나 쓸 수 있는 권한을 얻게 됩니다. 이 권한은 AccessToken을 통해 애플리케이션에 부여됩니다.
  • AccessToken : AccessToken은 OAuth2.0 프로토콜에서 사용되는 보안 토큰입니다. AccessToken은 인가된 클라이언트가 리소스 서버에 접근할 수 있는 권한을 제공합니다. 토큰에는 리소스 소유자의 신원, 인간된 권한, 토큰의 유효 기간 등의 정보가 포함됩니다. AccessToken은 일정 기간 후에 만료되므로, 기간이 만료되면 Refresh Token을 사용하여 새로운 토큰을 발급받아야 합니다.
  • RefereshToken : AccessToken이 만료되었을 때 새로운 AccessToken을 받기 위해 사용되는 토큰입니다. AccessToken은 보안상의 이유로 짧은 만료기간을 가져서 일정 시간 후에 만료되지만, RefreshToken을 사용하면 사용자가 다시 로그인 하지 않아도 새로운 AccessToken을 발급받을 수 있습니다. 이는 사용자가 계속 로그인 하지 않아도 되며, AccessToken 탈취 등에 대한 보안을 유지합니다.

 

1.5 OAuth2.0 Grant Flow Type

OAuth2.0 Authorization Framework는 여러개의 Grant Flow Type들을 지원합니다. 즉, Access Token을 발급받는 여러개의 플로우가 존재하는 것입니다. Grant Flow Type중 하나를 선택하는 것은 애플리케이션의 타입이나 클라이언트에 대한 신뢰 수준, 사용자가 원하는 경험과 같은 변수에 따라 달라집니다.

 

OAuth2.0 Authorization Framework가 가지는 Grant Flow Type들은 다음과 같습니다.

 

  • Client Credentials Flow
  • Authorization Code Flow
  • Resource Owner Password Flow (Legacy)
  • Implicit Flow with Form Post (Legacy)
  • Authorization Code Flow with Proof Key for Code Exchange (PKCE)

 

이 글에서는 일반적인 웹 및 모바일 애플리케이션에서 많이 사용하는 Authorization Code Flow에 대한 것만 소개합니다.

 

2. OAuth2.0 Authorization Code Flow

이번장에서는 OAuth2.0 Grant Flow Type중에서 웹 및 모바일 애플리케이션에서 가장 많이 사용하는 Grant Flow 종류 중 하나인 Authorization Code Flow의 수행과정을 소개합니다.

 

2.1 The Authorization Code Flow

Authorization Code Grant Type은 웹과 모바일 애플리케이션에서 사용됩니다. 먼저 애플리케이션이 Flow를 시작하기 위해서 브라우저를 실행해야 한다는 점에서 대부분의 다른 Grant Flow와 다릅니다. 상위 레벨에서 Flow는 다음 단계를 수행합니다.

 

  • 애플리케이션은 브라우저를 열어서 사용자를 OAuth 서버로 보냅니다.
  • 사용자는 Authorization 프롬프트를 보고 애플리케이션의 권한 위임 요청을 승인합니다.
  • 사용자는 쿼리 스트링에 authorization code를 가지고 애플리케이션으로 다시 리다이렉션합니다.
  • 애플리케이션은 액세스 토큰을 얻기 위해서 authorization code를 가지고 액세스 토큰과 교환합니다.

 

2.2 Get the User’s Permission

OAuth는 사용자가 애플리케이션에게 특정 리소스에 접근할 수 있는 권한을 부여할 수 있도록 하는 프로토콜입니다. 애플리케이션은 우선 리소스에 접근할 수 있는 권한을 결정한 다음에 사용자를 브라우저를 통하여 권한 선택 창으로 이동시키고 사용자로부터 권한을 받아야 합니다.

 

인가 플로우를 진행하기 위해서는 애플리케이션은 다음과 같은 URL을 구성하고 URL을 브라우저로 엽니다.

 

https://authorization-server.com/auth
 ?response_type=code
 &client_id=29352915982374239857
 &redirect_uri=https%3A%2F%2Fexample-app.com%2Fcallback
 &scope=create+delete
 &state=xcoiv98y2kd22vusuye3kch

 

위 URL의 쿼리 파라미터의 설명은 다음과 같습니다.

 

  • response_type=code : 이것은 authorization server(ex, 구글 인가 서버)에게 애플리케이션이 authorization code flow를 시작하고 있음을 알려줍니다.
  • client_id : client_id는 애플리케이션의 공개 식별자입니다. client_id는 개발자가 애플리케이션을 등록할때 얻습니다.
  • redirect_uri : authorization server에게 사용자가 권한 위임 요청을 승인한 다음에 사용자가 다시 돌아갈때 리다이렉션 주소입니다.
  • scope : 한개이상의 공백으로 구성된 애플리케이션이 요청하는 권한들을 의미합니다.
  • state : 애플리케이션이 생성한 랜덤한 문자열이고 생성한 문자열은 요청의 쿼리 파라미터에 포함됩니다. state는 그런 다음에 사용자가 애플리케이션을 인가한 다음에 반환되는 값과 같은 값인지 검사합니다. state는 CSRF 공격을 예방하는데 사용됩니다.

 

사용자가 위 URL에 방문한 다음에 authorization server는 이 애플리케이션의 요청을 인가하는 것과 같은 프롬프트 요청을 보여줄 것입니다.

 

 

2.3 Redirect Back to the Application

만약 사용자가 요청을 승인하면 authorization server는 애플리케이션에 의해서 명세된 redirect_uri 주소로 리다이렉트합니다. 이때 redirect_uri에는 쿼리 파라미터에 code와 state가 같이 포함되어 전송됩니다.

 

예를 들어 사용자가 다음 URL과 같이 리다이렉트 된다고 가정합니다.

 

https://example-app.com/redirect
 ?code=g0ZGZmNjVmOWIjNTk2NTk4ZTYyZGI3
 &state=xcoiv98y2kd22vusuye3kch

 

state 값은 애플리케이션이 초기에 설정한 값(리퀘스트 쿼리 파라미터에 같이 첨부하여 전송한)과 같은 값일 것입니다. 애플리케이션은 초기에 요청에서 전달한 state값과 리다이렉트로 전달된 state값이 같은 값인지 검사할 것입니다. 이 검사는 CSRF 공격을 막을 것입니다.

code 값은 authorization server에 의해서 생성된 인가 코드(authorization code) 입니다. 이 인가 코드는 상대적으로 짧게 살아있고 OAuth 서비스에 따라서 1~10분정도입니다.

 

2.4 Exchange the Authorization Code for an Access Token

애플리케이션은 authorization code를 가지고 있고 이제 authorization code를 이용하여 액세스 토큰(Access Token)으로 교환할 할 수 있습니다.

 

애플리케이션은 다음 파라미터를 포함하는 서비스의 액세스 토큰 엔드포인트로 전송할 POST 요청을 만듭니다.

 

  • grant_type=authorization_code : token 엔드포인트에게 애플리케이션이 Authorization Code Grant Type을 사용하고 있음을 알려줍니다.
  • code : 애플리케이션이 리다이렉트시 받은 authorization code를 의미합니다.
  • redirect_uri : authorization code를 요청할 때 사용되었던 같은 redirect URI를 의미합니다. 몇몇 API들은 이 파라미터를 요구하지 않지만, 여러분들은 여러분들이 접근하는 특정 API의 문서를 다시 확인해서 redirect_uri 파라미터가 필수적인지 선택적인지, 아니면 없어도 되는지 확인해야합니다.
  • client_id : 애플리케이션의 client ID.
  • client_secret : 애플리케이션의 client secret입니다. 이 정보는 액세스 토큰을 얻고자 하는 요청이 애플리케이션으로부터 만들어진 것인지 보장하도록 합니다. 그리고 이 정보는 authorization code를 가로챈 해커가 아님을 보장합니다.

 

token 엔드포인트는 code(authorization code)가 만료되지 않았는지, client ID와 client secret이 매치되는지 요청의 모든 파라미터를 검증할 것입니다. 만약 모든것이 일치하면, authorization server는 액세스 토큰을 생성하고 response에 담아서 반환합니다.

 

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache

{
  "access_token":"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3",
  "token_type":"bearer",
  "expires_in":3600,
  "refresh_token":"IwOGYzYTlmM2YxOTQ5MGE3YmNmMDFkNTVk",
  "scope":"create delete"
}

 

위와 같은 http response를 받는하면 Authorization Code Flow는 완료입니다.

 

2.5 When to use the Authorization Code Flow

 

Authorization Code Flow는 웹과 모바일 애플리케이션에서 가장 잘 사용됩니다. Authorization Code Grant는 액세스 토큰을 위해 authorization code를 교환하는 추가적인 단계를 가지기 때문에Implicit Grant Type에서 나오지 않는 추가적인 보안 레이어(security layer)가 제공됩니다.

 

만약 여러분들이 모바일 애플리케이션이나 client secret를 저장할 수 없는 다른 애플리케이션 종류에서 Authorization Code Flow를 사용한다면, 여러분들은 PKCE extension을 사용할 수 있습니다. PKCE extension은 authorization code가 가로챌 때와 같은 다른 공격을 방어하기 위해서 제공됩니다.

 

authorization code를 액세스 토큰으로 교환하는 단계에서 해커는 액세스 토큰을 가로챌 수없도록 보장합니다. 액세스 토큰은 항상 애플리케이션과 OAuth server 간에 보안 백채널(secure backchannel)을 통해 전송되기 때문입니다.

 

2.6 Authorization Code Flow Sequence Diagram

이 장에서 설명한 Authorization Code Flow의 수행과정을 시퀀스 다이어그램으로 표현하면 다음과 같습니다.

 

 

References