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
사용시 얻을 수 있는 장점은 아래와 같다.
- 보안성
사용자는 자신의 로그인 정보(자격 증명)를 서드파티 앱에 제공하지 않으므로 보안 강화. - 범위 제한
엑세스 토큰별로 리소스 인가 범위를 명확하게 설정 가능. - 토큰 만료
액세스 토큰의 만료를 설정하고 접근제어 가능.
용어 설명
- 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
- Confidential 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
UserAgent
는Resource Client
에서 제공하는Web Browser
(모달창)
Resource Owner
인증 후 리다이렉트될 링크가 적용되어 있는 로그인 모달창을Authorization Server
에 등록Resource Owner
는 해당 모달창에서 로그인 진행- 로그인 성공 시
Authorization Code
를 리다이렉트 URI 에 저장 후Resource Client
로 리다이렉트 Resource Client
는 전달받은Authorization Code
로Access Token
을 요청Authorization Server
는Redirection 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 Token
을Authorization 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 Client
는access token
요청시code_verifier
를 포함하여 전달.Resource Client
는[grant_type, code, redirect_uri, client_id, code_verifier]
을 Form data 에 설정해서Authorization Server
로 전달한다.
Authorization Server
는 가지고 있던code_challenge
와code_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 Client
는Resource 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 Owner
가Resource Client
를 믿고ID/PWD
를 넘겨주는 방식Resource Client
는Authorization 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 Client
와 Authorization 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)
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"
}
JWT
는 Authorization 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.0
의 Authroization Server
와 OP
의 차이점은 Grant Type
과정에서 Access Token
을 반환하는 과정에 OpenID
에 필요한 데이터를 같이 삽입하여 반환하거나,
그림 (4) ~ (5)
과정에서 Access Token
을 사용해 UserInfo
를 요청할 수 있는 기능을 추가로 제공한다.
UserInfo
가ID 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 Channel
이Flow
에 개입하기에Confidential Client
에서만 사용 가능하다.
- Implict Flow
- 리다이렉트 URI 에
Access Token
,ID Token
을 포함시켜 반환한다.
- 리다이렉트 URI 에
- Hybrid Flow
Authorization Code
,Implict
2가지Flow
를 섞어 사용하는 방식Back Channel
이Flow
에 개입하기에Confidential Client
에서만 사용 가능하다- 보안적으로 노출되어도 상관 없는
Authorization Code, ID Token
은 리다이렉트 URI 에 포함시켜 반환 - 노출되면 위험한
Access Token
은Back 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
IoT, Smart TV 와 같이 입력환경이 제한된 상태에서 기기에 대한 인증을 수행하고 싶을 때 사용하는 flow
- 사용자가 Netflix TV App 을 킴
- Netflix TV App 에서 인증을 위해
Authorization Server
에 요청 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는 짧고 기억하기 쉬워야 하며, 사용자가 쉽게 입력할 수 있어야 합니다.
- device_code
- 사용자는
user_code
를 확인하고 해당verification_url
에 접속- 사용자 로그인 (Browser Flow) 수행
- Netflix TV App 은 사용자가 휴대폰으로 로그인할 때 까지
interval pooling
을 수행 - 사용자가
user_code
를 입력하여device
승인 했는지 determine(확인) device
승인이 되었다면interval pooling
응답으로Access Token
발급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초 간격으로 폴링해야 합니다.