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
- 로그인 자원을 이용하는 클라이언트 앱,
- 웹서버 혹은 모바일 앱
- ex: Google Drive 를 연계해서 관련 서비스를 만드는 서드파티 앱
Resource Client종류는 아래와 같이 나뉜다.- Confidential Client
client_id,client_secret을 보관할 수 있는, 서버와 같은 별도의 저장공간이 있는 곳에 위치하는Resource Client - Public Client
모바일 어플처럼 시크릿 정보를 보관할 수 없는Resource Client
- Confidential Client
- Resoucrce Server
- 로그인 자원을 관리하는 서버
- ex: Google Drive 서버
- Authorization Server
- 인증 서버
- ex: Google OAuth 서버
Grant Type
1 | 1.2. 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 로 로그인 모달창이 열린다.
1 | https://www.facebook.com/dialog/oauth? |
참고
app_id 는Resource Client를 나타내는 고유ID,
매칭되는 app_secret 이 있으며 app_secret 은 노출되면 안된다.
로그인 성공시 데이터가 전송될 redirect_uri 이 적혀있다. 적혀진 URI 로 인증정보가 같이 전달되도록 한다.
1 | +----------+ |
UserAgent는Resource Client에서 제공하는Web Browser(모달창)이다.
Resource Client인증 후 리다이렉트될 링크가 적용되어 있는 로그인 모달창을Authorization Server에 등록Resource Owner는 해당 모달창에서 로그인 진행- 로그인 성공 시
Authorization Code를 리다이렉트 URI 에 저장 후Resource Client로 리다이렉트 Resource Client는 전달받은Redirection URI, Authorization Code, Client ID, Client Secret로Access Token을 요청Authorization Server는Redirection URI, Authorization Code, Client ID, Client Secret검증 후Access Token발급
Back Channel과정에서 추가로Refresh Token을 전달받을 수 있음.Access Token이 리다이렉트 URI 로 노출되지 않기에 안전하게 사용자(Resource Owner) 대신Resource를 요청할 수 있음.
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에서 확인해야하는 번거로움이 있음. - Self Contained Token : JWT 와 같이 서명값이 있어 자기 증명이 가능한 토큰
- Refresh Token
Back Channel사용Grant Type에서Access Token과 같이 발급되는 재발급 토큰- 구글
Authorization ServerAccess Token유효기간은 1시간 - 구글
Refresh Token의 경우 별도로 만료되는 시간이 없다고 함 - 장기간 유효기간을 가지며 로그인이 풀리지 않는 UX 구성시 사용한다
Authorization Code Grant Type - PKCE
모바일 앱과 같이 브라우저 환경이 아닌경우 위와 같이 리다이렉트를 사용하는 Authorization Code 인증방식은 사용하기 힘들 수 있다.
그럴경우 Authorization Code, access token 요청 모두 공개 클라이언트(프론트, 모바일 앱 등)에서 수행해야 한다.
하지만 공개 클라이언트에선 Resource Client 의 인증으로 사용하는 client_secret 을 사용하지 못하기 때문에 다른 방식을 사용하는데, PKCE (Proof Key for Code Exchange) 방식으로 Resource Client 의 인증을 수행한다.
별도 백엔드 서비스를 사용하지 않고 모바일 앱만 사용하는 경우에 PKCE 를 사용한다,
대부분 서비스에 백엔드가 존재하다 보니client_secret을 사용하는 첫번째 방식을 사용.
(1) Client Identifier & Redirection URI단계에서Resource Client(모바일앱)는 랜던값인code_verifier를 생성하고 해시값인code_challenge를 redirect URL 에 포함하여 전달code_challenge는 서명역할을 하며 중간자 공격을 방지한다.Authorization Code가 유출되어도code_challenge,code_verifier보안단계가 하나 더 있다.- 추가로 랜덤 난수인
state, nonce를 생성하여 전달한다. state는 CSRF 방지를 위한 값으로 사용자가 아래 링크로 로그인 성공시 동일한state값이redirectURL 파라미터로 전달된다.nonce는OpenID Connect에서 JWT 토큰에 삽입되는 값으로 토큰재생공격을 방지한다.
1 | http://authorization-server:9090/oauth2/authorize? |
위 2개 추가 파라미터를 통해 client_secret 을 사용하지 않아도 정상앱인척 하는 Authorization Server 로의 공격요청을 방지한다.
- 사용자가 로그인 한 뒤 성공하면 위 redirect URL 과 파라미터가 전송된다.
state는code_verifier를 찾기 위한 매핑값으로 캐시에 저장된다.
1 | com.myapp:/oauth2redirect? |
(4) Authorization Code & Redirection URI단계에서Resource Client(모바일앱)는access token요청시[grant_type, code, redirect_uri, client_id, code_verifier]을 Form data 에 설정해서Authorization Server로 전달한다.Authorization Server는 가지고 있던code_challenge와code_verifier가 매칭되는지 확인 후access token을 발급한다.
발급된 access token 으로 백엔드 서비스에서 로그인여부를 파악하려면 해당 access token 이 예상한 client id 에서 생성된 것인지 검증 과정을 수행해야 한다.
Client Credential Grant Type
인증정보를 Resource Client(앱) 에게 직접 전달하는 방식이라 거의 사용하지 않음.
- 2 legged flows
Confidential Client만 사용.Back Channel만 사용하며 사전에Resource Owner인증정보 가 필요함.Resource Client는Resource Owner의 인증정보 사용하여Authorization Server에게 직접Access Token을 요청함.Authorization Server와 연동가능한 인증정보를Confidential Client가 가지고 있어야 해서 거의 지원하지 않음.
1 | +---------+ +---------------+ |
Resource Owner Credentials Grant Type
인증정보를 Resource Client(앱) 에게 직접 전달하는 방식이라 거의 사용하지 않음.
- 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에서 사용하던 방식
1 | +----------+ |
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방식을 선호함
1 | +----------+ |
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 | +--------+ +---------------+ |
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 이내로 저장가능하다.
1 | { |
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 | +--------+ +--------+ |
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,Implict2가지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 값을 반환받는다.
1 | { |
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초 간격으로 폴링해야 합니다.