OAuth!

OAuth

OAuth(Open Authorization)
위키: 사용자가 자신의 자격 증명을 제공하지 않고 제3자 애플리케이션에 자신이 소유한 자원의 제한적인 접근 권한을 부여할 수 있는 표준 프로토콜

참고
https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-07
https://opentutorials.org/course/3405
https://www.youtube.com/watch?v=zEysfgIbqlg&list=PLKCk3OyNwIzuD_jxWu-JddooM2yjX5q99&index=4

대표적으로 각종 캘린더, 사진첩 등 Google Drive 를 사용하는 서드파티 앱을 예로 들 수 있다.
서드파티 앱에 Google Drive 계정을 넘기지 않고 Google Drive 에 접근을 허가시킬 수 있음.

OAuth 사용시 얻을 수 있는 장점은 아래와 같다.

  • 보안성
    사용자는 자신의 로그인 정보(자격 증명)를 서드파티 앱에 제공하지 않으므로 보안 강화.
  • 범위 제한
    엑세스 토큰별로 리소스 인가 범위를 명확하게 설정 가능.
  • 토큰 만료
    액세스 토큰의 만료를 설정하고 접근제어 가능.

용어 설명

1

  • Resoucrce
    • 사용할 데이터,
    • ex: Google Drive 내부 사용자 파일
  • Resoucrce Owner
    • 접근하려는 자원의 소유자,
    • ex: Google Drive 계정주인
  • Resource Client
    • 로그인 자원을 이용하는 Client Applicaiton,
    • 웹서버 혹은 모바일 앱
    • ex: Google Drive 를 연계해서 관련 서비스를 만드는 서드파티 앱
    • Resource Client 종류는 아래와 같이 나뉜다.
      • Confidential Client
        client key, client secret 을 보관할 수 있는, 서버와 같은 별도의 저장공간이 있는 곳에 위치하는 Resource Client
      • Public Client
        모바일 어플처럼 시크릿 정보를 보관할 수 없는 Resource Client
  • Resoucrce Server
    • 로그인 자원을 관리하는 서버
    • ex: Google Drive 서버
  • Authorization Server
    • 인증 서버
    • ex: Google OAuth 서버

Grant Type

                    1.2. Protocol Flow

    +--------+                               +---------------+
    |        |--(1)- Authorization Request ->|   Resource    |
    |Resource|                               |     Owner     |  Front Channel
    | Client |<-(2)-- Authorization Grant ---|               |
    |        |                               +---------------+
    +--------+

    +--------+                               +---------------+ 
    |        |--(3)-- Authorization Grant -->| Authorization |
    |        |                               |     Server    | 
    |        |<-(4)----- Access Token -------|               |
    |Resource|                               +---------------+
    | Client |                                                  Back Channel
    |        |                               +---------------+
    |        |--(5)----- Access Token ------>|    Resource   |
    |        |                               |     Server    |
    |        |<-(6)--- Protected Resource ---|               |
    +--------+                               +---------------+

                 Figure 1: Abstract Protocol Flow

Front Channel, Back Channel 을 어떻게 사용하는지에 따라 4가지 시나리오기 있으며 Grant Type 이라 부른다.

  • Authorization Code Grant Type
  • Client Credential Grant Type
  • Resource Owner Grant Type
  • Implict Grant Type

Grant Type 별로 인증방식은 유사하며 Front Channel, Back Channel 섞어 사용한다.

  • (1) ~ (2) 과정은 클라이언트가 직접 수행하는 Front Channel
  • (3) ~ (6) 과정은 리다이렉션을 통해 자동으로 처리되는 Back Channel

그리고 Resource Client 의 종류에 따라서 Grant Type 의 사용 가능 여부가 갈린다.

Authorization Code Grant Type

  • 3 legged flows
  • 리다이렉트를 사용함으로 웹 브라우저 환경에 적합함
  • Back Channel 이 필요하여 Confidential Client 에서만 사용 가능.
  • 대부분의 Confidential Client 기반 Resource Client 가 해당 방식을 사용함

Authorization Code Grant Type 지원 Resource Client 웹페이지에서 사용자가 OAuth 로그인 버틀을 누르면 아래와 같은 URL 로 로그인 모달창이 열린다.

https://www.facebook.com/dialog/oauth?
app_id=933793539013400&
client_id=933793539013400&
display=popup&
domain=en.airline.example.com&
response_type=token,signed_request&
scope=["email","user_birthday"]&
locale=en_US&
origin=1&
redirect_uri=https://Fstaticxx.facebook.com/connect/xd_my-demo-application/...
sdk=joey

참고
app_id 는 Resource Client 를 나타내는 고유ID, 매칭되는 app_secret 이 있으며 app_secret 은 노출되면 안된다.

로그인 성공시 데이터가 전송될 리다리엑트 URI 가 적혀있다. 적혀진 URI 로 인증정보가 같이 전달되도록 한다.

 +----------+
 | Resource |
 |   Owner  |
 +----------+
       ^
       |
       |
 +-----|----+          Client Identifier      +---------------+
 | .---+---------(1)-- & Redirection URI ---->|               |
 | |   |    |                                 |               |
 | |   '---------(2)-- User authenticates --->|               |
 | | User-  |                                 | Authorization |  Front Channel
 | | Agent  |                                 |     Server    |
 | |        |                                 |               |
 | |    .--------(3)-- Authorization Code ---<|               |
 +-|----|---+                                 +---------------+
   |    |                                         ^      v
   |    |                                         |      |
   ^    v                                         |      |
 +---------+                                      |      |
 |         |>---(4)-- Authorization Code ---------'      |
 |  Client |          & Redirection URI                  |       Back Channel
 |         |                                             |
 |         |<---(5)----- Access Token -------------------'
 +---------+       (w/ Optional Refresh Token)
              
              Figure 3: Authorization Code Flow

UserAgentResource Client 에서 제공하는 Web Browser(모달창)

  1. Resource Owner 인증 후 리다이렉트될 링크가 적용되어 있는 로그인 모달창을 Authorization Server 에 등록
  2. Resource Owner 는 해당 모달창에서 로그인 진행
  3. 로그인 성공 시 Authorization Code 를 리다이렉트 URI 에 저장 후 Resource Client 로 리다이렉트
  4. Resource Client 는 전달받은 Authorization CodeAccess Token 을 요청
  5. Authorization ServerRedirection URI, Authorization Code 검증 후 Access Token 발급

Access Token 이 리다이렉트 URI 로 노출되지 않기에 안전하고 Back Channel 과정에서 추가로 Refresh Token 을 전달받을 수 있다.

Authorization Code Grant Type 을 지원하는 Authorization Server 에서 아래 3가지 데이터를 관리한다.

  • Authorization Code
    • 로그인 성공시 이동될 리다이렉트 URI 에 같이 전달되는 랜덤 문자열
    • Resource Owner 을 증명하는 임시발급 인증코드라 할 수 있다.
  • Access Token
    • Authorization Code 를 사용해서 Resource Owner 와 매핑되는 Access Token 을 발급한다.
    • 아래 2가지 종류로 나뉜다.
    • Refrence Token
      • Authorization Server 에서 관리하는 랜덤 문자열
      • Resource Server 는 매 요청마다 Access TokenAuthorization Server 에서 확인(Introspect)한다.
    • Self Contained Token
      • JWT 와 같이 서명값이 있어 자기 증명이 가능한 토큰
  • Refresh Token
    • Back Channel 사용 Grant Type 에서 Access Token 과 같이 발급되는 재발급 토큰
    • 구글 Authorization Server Access Token 유효기간은 1시간
    • 구글 Refresh Token 의 경우 별도로 만료되는 시간이 없다고 함
    • 장기간 유효기간을 가지며 로그인이 풀리지 않는 UX 구성시 사용한다

Authorization Code Grant Type - PKCE

모바일 앱과 같이 브라우저 환경이 아닌경우 위와 같이 redirect 를 사용한 Authorization Code 인증방식은 사용하기 힘들 수 있다.
그럴경우 Authorization Code, access token 요청 모두 공개 클라이언트(프론트, 모바일 앱 등)에서 수행하는데 Resource Client 의 인증으로 사용하는 client secret 을 사용하지 못한다.

이때 PKCE (Proof Key for Code Exchange) 방식으로 Resource Client 의 인증을 수행한다.

  • (1) Client Identifier & Redirection URI 단계에서 Resource Client 는 랜던값인 code_verifier 를 생성하고 해시값인 code_challenge 를 redirect URL 에 포함하여 전달
    • code_challenge 는 서명역할을 하며 중간자 공격을 방지한다.
    • Authorization Code 가 유출되어도 code_challenge, code_verifier 보안단계가 하나 더 있다.
http://authorization-server:9090/oauth2/authorize?
  response_type=code&
  client_id=oauth-demo-client-id&
  scope=openid%20profile%20email&
  redirect_uri=http://resource-client:8080/login/oauth2/code/oauth-client-redirect&
  state=znoqBBJcIPiMhva-Ze527g2sYhyFg3u_g7GpYF3-0WQ%3D&
  nonce=C317bREycoVNZm3kUcswIBh_eVu8jXnL7hu95mQurNo&
  code_challenge=bu_IDU5aUm1igD7jbfca8-8KwOC7Ot342d_hnYcmn0k& # code_verifier 를 해시한 값
  code_challenge_method=S256
  • 사용자가 로그인 한 뒤 (4) Authorization Code & Redirection URI 단계에서 Resource Clientaccess token 요청시 code_verifier 를 포함하여 전달.
    • Resource Client[grant_type, code, redirect_uri, client_id, code_verifier] 을 Form data 에 설정해서 Authorization Server 로 전달한다.
  • Authorization Server 는 가지고 있던 code_challengecode_verifier 가 매칭되는지 확인 후 access token 를 발급한다.

client_secret 을 사용하지 못하는 공개 클라이언트에서 사용하기 때문에 위조된 로그인 요청을 막을 수 없다.
발급된 access token 으로 백엔드 서비스에서 로그인여부를 파악하려면 해당 access token 이 예상한 client id 에서 생성된 것인지 검증 과정을 수행해야 한다.

별도 백엔드 서비스를 사용하지 않고 모바일 앱만 사용하는 경우에 PKCE 를 사용한다, 대부분 서비스에 백엔드가 존재하다 보니 client secret 을 사용하는 방식을 사용함.

Client Credential Grant Type

  • 2 legged flows
  • Confidential Client 만 사용.
  • Back Channel 만 사용하며 사전에 Resource Owner 인증정보 가 필요함.
  • Resource ClientResource Owner 의 인증정보 사용하여 Authorization Server 에게 직접 Access Token 을 요청함.
  • Authorization Server 와 연동가능한 인증정보를 Confidential Client 가 가지고 있어야 해서 거의 지원하지 않음.
+---------+                                  +---------------+
|         |                                  |               |
|         |>--(1)- Client Authentication --->| Authorization |
| Client  |                                  |     Server    |  Back Channel
|         |<--(2)---- Access Token ---------<|               |
|         |                                  |               |
+---------+                                  +---------------+
            Figure 4: Client Credentials Grant

Resource Owner Credentials Grant Type

  • 2 legged flows
  • User Password Authentication Flow 라 부르기도 함.
  • Resource OwnerResource Client 를 믿고 ID/PWD 를 넘겨주는 방식
  • Resource ClientAuthorization Server 에 전달받은 ID/PWD 를 사용해 Access Token 을 요청.
  • Public Client 가 사용하지만 보안상 취약하여 Authorization Server 에서 지원하지 않는 경우가 많음.
  • OAuth 1.0 에서 사용하던 방식
+----------+
| Resource |
|   Owner  |
+----------+
    |
    |
    | Authenticate with client(Username, Password)
    |
    v
+---------+                                  +---------------+
|         |                                  |               |
|         |>--(1)- Client Authentication --->| Authorization |
| Client  |                                  |     Server    | Back Channel
|         |<--(2)---- Access Token ---------<|               |
|         |                                  |               |
+---------+                                  +---------------+

Implicit Grant Type

  • 2 legged flows
  • OAuth 2.1 에서 deprecated 됨
  • Authorization Code 방식과 동일하게 리다이렉트 방식이지만 Authorization Code 대신 Access Token 을 바로 전달받음
  • 리다이렉트 URL 에 Access Token 이 노출되어 보안에 취약함(Refresh Token 은 전달하지 않음)
  • 브라우저 기반 리다이렉트를 지원하는 SPA 형태 Public Client 에서 사용가능
  • Confidential Client 에서도 사용 가능하지만 Authorization Code 방식을 선호함
 +----------+
 | Resource |
 |   Owner  |
 +----------+
       ^
       |
       |
 +-----|----+          Client Identifier      +---------------+
 | .---+---------(1)-- & Redirection URI ---->|               |
 | |   |    |                                 |               |
 | |   '---------(2)-- User authenticates --->|               |
 | | User-  |                                 | Authorization | Front Channel
 | | Agent  |                                 |     Server    |
 | |        |                                 |               |
 | |    .--------(3)-- Redirect URI With  ---<|               |
 +-|----|---+             Access Token        +---------------+
   |    | 
   |    | 
   ^    v 
 +---------+
 |         |
 |  Client |
 |         |
 +---------+

Grant Type 중 유일하게 Resource ClientAuthorization Server 가 직접 통신하는 Back Channel 과정이 없다.

Refresh Token Grant Type

Back Channel 이 있는 Grant Type 에서 추가적으로 지원하는 Grant Type.
Access Token 을 전달받으면서 같이 발급된 Refresh Token 을 사용해 새로운 Access Token 을 발급받을 수 있다.

+--------+                                           +---------------+
|        |--(1)------- Authorization Grant --------->|               |
|        |                                           |               |
|        |<-(2)----------- Access Token -------------|               |
|        |               & Refresh Token             |               |
|        |                                           |               |
|        |                            +----------+   |               |
|        |--(3)---- Access Token ---->|          |   |               |
|        |                            |          |   |               |
|        |<-(4)- Protected Resource --| Resource |   | Authorization |
| Client |                            |  Server  |   |     Server    |
|        |--(5)---- Access Token ---->|          |   |               |
|        |                            |          |   |               |
|        |<-(6)- Invalid Token Error -|          |   |               |
|        |                            +----------+   |               |
|        |                                           |               |
|        |--(7)----------- Refresh Token ----------->|               |
|        |                                           |               |
|        |<-(8)----------- Access Token -------------|               |
+--------+           & Optional Refresh Token        +---------------+
        
            Figure 2: Refreshing an Expired Access Token

OAuth 의 허점

Access Token, Refresh Token 을 통해 사용자 접근 허용을 관리함으로 토큰을 탈취할 수 있는 해킹공격에 취약하다.

Access Token 은 보통 해당 브라우저의 local storage, HTTP Cookie 등에서 관리되기 때문에 악성코드를 대신 실행시키는 CSRF, XSS 의 공격대상이 되기 쉽고,
GET HTTP URL 에 인증코드가 그대로 유출되기 때문에 중간자 공격에 취약하다. HTTPS 를 사용한다 하더라도 DNS 스푸핑과 같은 공격으로 인해 무력화될 수 있다.

  • CSRF
  • 토큰 도용(XSS 등으로 토큰을 도용)
  • 토큰 하이재킹(중간자 공격)

이를 막기 위해 Private Resource Client 는 자신만 아는 secret 을 함께 사용하여 Access Token 을 요청하고
Public Resource Client 또한 code challenge 와 같은 서명기능을 사용해 Access Token 을 요청한다.

OpenID Connect(OIDC)

https://openid.net/specs/openid-connect-core-1_0.html

OpenID Connect(OIDC)OAuth 프로토콜을 기반으로 권한과 더불어 사용자의 신원을 검증하는 인증 기능을 추가지원한다.
OAuth 2.0 프로토콜에 JWT 를 추가한 신원 확인 프로토콜 이다.

OIDC 에선 Access Token 의 형태가 Opaque Token(랜덤 문자열) 타입 대신 JWT 를 사용한다.
그리고 사용자의 추가적인 신원데이터를 포함한 JWT 형태의 ID Token 을 추가하여 반환한다.

OAuth 에서 사용하는 Access Token, Refreth Token 외에 ID Token 이 추가되었다.

ID Token 내부에는 아래와 같이 JWT Claims 형태로 OIDC 가 지원하는 신원데이터 형식, HTTP 헤더의 최대 사이즈인 4KB 이내로 저장가능하다.

{
  "iss": "https://server.example.com",
  "sub": "24400320",
  "aud": "s6BhdRkqt3",
  "nonce": "n-0S6_WzA2Mj",
  "exp": 1311281970,
  "iat": 1311280970,
  "auth_time": 1311280969,
  "acr": "urn:mace:incommon:iap:silver"
}

JWTAuthorization Server 의 비공개키로 서명되어 있어 출처 인증이 가능하다.

OIDC Flow

문서에선 OAuth 와 비슷한 역할을 수행하지만 새로운 이름을 가진 리소스들로 설명한다.

  • Relying Party(RP)
    • Resource Client 의 연장선
    • ID Token 을 사용하는 어플리케이션
  • OpenID Provider(OP)
    • Authorization Server 의 연장선
    • Authorization Code, Access Token, Refresh Token, ID Token 을 발급
  • Identity Provider(IDP)
    • 인증서비스에서 사용하는 일반적인 통칭, IDP 안에 Authorization Server, OP 개념이 포함된다.
+--------+                                   +--------+
|        |                                   |        |
|        |---------(1) AuthN Request-------->|        |
|        |                                   |        |
|        |  +--------+                       |        |
|        |  |        |                       |        |
|        |  |  End-  |<--(2) AuthN & AuthZ-->|        |
|        |  |  User  |                       |        |
|   RP   |  |        |                       |   OP   |
|        |  +--------+                       |        |
|        |                                   |        |
|        |<--------(3) AuthN Response--------|        |
|        |                                   |        |
|        |---------(4) UserInfo Request----->|        |
|        |                                   |        |
|        |<--------(5) UserInfo Response-----|        |
|        |                                   |        |
+--------+                                   +--------+

OAuth 2.0Authroization ServerOP 의 차이점은 Grant Type 과정에서 Access Token 을 반환하는 과정에 OpenID 에 필요한 데이터를 같이 삽입하여 반환하거나,
그림 (4) ~ (5) 과정에서 Access Token 을 사용해 UserInfo 를 요청할 수 있는 기능을 추가로 제공한다.

UserInfoID Token보다 훨씬 상세한 데이터를 가지고 있다.
UserInfo 를 제공하는 서버는 RP 가 아닌 Resource Server 로 따로 구축하는 경우도 있다.

OIDC 에서는 Access Token, ID Token 을 발급하기 위한 3가지 Flow 를 사용한다.

대부분 Authorization Code Flow 를 사용한다.

  • Authorization Code Flow
    • Back Channel 에서 수행하는 Access Token, Refresh Token 발급과정에 ID Token 을 같이 껴서 반환하게 된다.
    • Back ChannelFlow 에 개입하기에 Confidential Client 에서만 사용 가능하다.
  • Implict Flow
    • 리다이렉트 URI 에 Access Token, ID Token 을 포함시켜 반환한다.
  • Hybrid Flow
    • Authorization Code, Implict 2가지 Flow 를 섞어 사용하는 방식
    • Back ChannelFlow 에 개입하기에 Confidential Client 에서만 사용 가능하다
    • 보안적으로 노출되어도 상관 없는 Authorization Code, ID Token 은 리다이렉트 URI 에 포함시켜 반환
    • 노출되면 위험한 Access TokenBack Channel 에서 Authorization Code 를 사용해 요청한다.
    • Access Token 을 요청하면서 ID Token 을 다시한번 수신받는데, 이전에 받은 ID Token 과 교차 검증한다.

OAuth Device Flow

https://auth0.com/docs/get-started/authentication-and-authorization-flow/device-authorization-flow

1

IoT, Smart TV 와 같이 입력환경이 제한된 상태에서 기기에 대한 인증을 수행하고 싶을 때 사용하는 flow

1

  1. 사용자가 Netflix TV App 을 킴
  2. Netflix TV App 에서 인증을 위해 Authorization Server 에 요청
  3. Authorization Server 에서 device_code, user_code, verficiation_url 반환
    • device_code
      device_client 가 인증 서버에게서 받는 장치식별코드.
      인증 수행, 토큰 저장소의 index 용도로 사용.
    • user_code
      device_client 가 인증 서버에게서 받는 사용자 식별 코드(보통 8자리).
      device_client 의 승인을 위해 사용된다.
    • verification_uri
      사용자 검증 URI, 사용자가 에이전트(브라우저 등)에 입력하여 연결.(보통 QR코드로 접속)
      URI는 짧고 기억하기 쉬워야 하며, 사용자가 쉽게 입력할 수 있어야 합니다.
  4. 사용자는 user_code 를 확인하고 해당 verification_url 에 접속
    • 사용자 로그인 (Browser Flow) 수행
  5. Netflix TV App 은 사용자가 휴대폰으로 로그인할 때 까지 interval pooling 을 수행
  6. 사용자가 user_code 를 입력하여 device 승인 했는지 determine(확인)
  7. device 승인이 되었다면 interval pooling 응답으로 Access Token 발급
  8. Access Token 으로 Resource Server 에 API 요청

3번 과정에서 아래와 같은 json 값을 반환받는다.

{
  "device_code": "4/0AY0e-g7YZ4xQ...",
  "user_code": "G3Q4",
  "verification_uri": "https://example.com/device",
  "verification_uri_complete": "https://example.com/device?user_code=G3Q4",
  "expires_in": 1800,
  "interval": 5
}
// 1800초동안 5초마다 pooling

verification_uri_complete “user_code” 를 포함하는 검증 URI 입니다. URI 에 user_code 를 포함하고 있으므로 사용자가 직접 user_code 를 입력하지 않고 인증 과정을 진행할 수 있습니다. 주로 QR, NFC 와 같은 non-textual verification 방식에서 사용되며 애플리케이션의 사용성 향상을 위해 활용됩니다. expires_in 필수 “device_code”와 “user_code”의 수명을 초 단위로 나타내며, 이 시간이 지나면 코드는 만료됩니다. interval 선택 Device Client 가 토큰 엔드포인트에 폴링 요청을 보내는 사이에 기다려야 하는 최소 시간(초)을 나타냅니다. 값이 제공되지 않을 경우, Device Client 는 기본적으로 5초 간격으로 폴링해야 합니다.

카테고리:

업데이트: