OAuth란 구글과 같은 플랫폼의 특정한 사용자 데이터에 접근하기 위해 제3자 클라이언트(우리의 서비스)가 사용자의 접근 권한을 위임(Delegated Authorization)받을 수 있는 표준 인가 프로토콜을 말한다. 우리 서비스의 사용자의 구글 플랫폼 데이터에 접근하기 위해 사용자의 구글 id, pw를 받아 가져오는 것은 간단하지만 보안 측면에서 좋지 않다. 물론 구글 역시 우리 서비스가 사용자의 id, pw를 가지고 있는 것을 좋아하지 않을 것. 그렇다면 구글로 로그인하기는 어떤식으로 이루어지는 걸까? 로 시작한 OAuth 공부이다.
OAuth에는 다음과 같은 주체가 있다. 내가 쉽게 이해하기 위해 예시를 추가했다.
이후 본문에선 '리소스 소유자', '클라이언트', '인가 서버', '리소스 서버' 라고 칭함.
OAuth를 이용하기 전 클라이언트를 리소스 서버에 등록해야한다.
- 애플리케이션 식별하는 고유 id
- 외부에 노출되어도 괜찮음.
- id에 대한 비밀번호
- 외부에 노출되어선 안됨.
POST /token HTTP/1.1
grant_type=authorization_code
&code=xxxxxxxxxxxxxxx
&redirect_uri=https%ajldfwf
웹 브라우저를 통해 클라이언트가 리소스 서버에 접근하는 경우에 사용되며, 주로 클라이언트가 웹 애플리케이션인 경우에 사용
GET /authorize HTTP/1.1
?response_type=token
&client_id=sdffjq1235alkd
&redirect_uri=https%ajldfwf
POST가 아닌 GET 요청
일반적으로 OAuth 2.0 인증 프로토콜에서는 액세스 토큰을 요청하는데 POST 요청을 사용하는 경우가 많지만, implicit 플로우는 액세스 토큰을 요청할 때 특별한 인증 코드(authorization code)를 받아올 필요가 없으며, 단지 액세스 토큰만 받으면 되기 때문에 GET 요청 사용
grant_type이 없다
grant_type 매개변수는 클라이언트가 사용하는 권한 부여 방식을 식별하는 역할
implicit 플로우는 이미 클라이언트가 인가되었다고 간주하고, grant_type 파라미터를 생략하고 액세스 토큰을 바로 요청
(1) 리소스 서버는 클라이언트가 이미 리소스 소유자에게 인가를 받은 상태라고 가정하고 등록된 클라이언트인지 확인 (client_id, redirect_uri 일치 확인)
(2) 등록된 클라이언트라면 액세스 토큰을 redirect_uri로 보냄
authorization code 없이 바로 액세스 토큰을 발급
- 클라이언트가 인가 코드를 요청하지 않는다는 것.
클라이언트 인증 이루어지지 않음.
- 클라이언트가 누구인지 확인하지 않고 액세스 토큰을 발급한다는 의미.
✦ 등록된 클라이언트인지 확인하는 것과 클라이언트 인증은 다른 것
► 등록된 클라이언트 확인
- 리소스 서버가 클라이언트로부터 authorization code 또는 액세스 토큰 발급을 요청받았을 때
해당 클라이언트가 등록된 클라이언트인지를 확인하는 것을 의미.- 리소스 서버에 클라이언트를 등록할 때 발급받은
클라이언트 아이디(client_id)와 클라이언트 비밀번호(client_secret)가 올바른지 확인► 클라이언트 인증
- 클라이언트가 가지고 있는 authorization code나 액세스 토큰이 유효한지,
리소스 서버에 접근 권한이 있는지를 확인하는 것을 의미.
POST /token HTTP/1.1
grant_type=password
&username=resource_owner_name
&password_uri=resource_owner_password
클라이언트가 자체 리소스를 사용하거나, 또는 이미 리소스 서버와 신뢰 관계를 가지고 있을 때 주로 사용.
이 방식에서는 클라이언트 자체가 리소스 서버에 접근하는 경우(예: API 서버에 접근하는 서비스) 자신의 신원을 인증하고 액세스 토큰을 발급받는 방식
사실상 리소스 오너와 oauth 클라이언트가 동일한 개체일때 복잡한 플로우를 가져가기보단 직접적으로 API호출을 통해 토큰을 발급받는 것
POST /token HTTP/1.1
grant_type=client_credentials
&client_id=your_client_id
&client_secret=your_client_secret
(1) 클라이언트는 자신의 자격증명(client_id, client_secret)을 사용하여 인증
(2) 클라이언트는 authorization code나 리디렉션없이 client_id와 client_secret을 리소스 서버로 보내 액세스 토큰을 요청.
(3) 리소스 서버는 클라이언트로부터 받은 client_id와 client_secret을 확인하여 클라이언트에게 액세스 토큰 발급
✦ bearer token
POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
OAuth 2.0에서 클라이언트가 리소스 서버에 요청을 보낼 때,
HTTP 헤더에 Bearer Token을 포함하여 액세스 토큰을 전달.
리소스 서버는 이 Bearer Token을 검증하여 클라이언트의 요청이 유효한지 확인하고,
해당 액세스 토큰이 리소스에 접근할 권한이 있는지 확인.
일반적으로 access token은 만료기간이 있으며, 만료되면 더 이상 사용할 수 없다.
refresh token는 access token보다 더 오래 유효하며 이를 이용하여 access token이 만료되었을 때 refresh token으로 새로운 access token과 새로운 refresh token을 받을 수 있다.
- 어뷰징(abusing) 이란 부정한 목적을 가지고 시스템을 이용하거나,
시스템의 취약점을 악용하여 불법적인 행위를 하는 것.
더 보안적으로 민감한 사용처들의 프로토콜 채택 (금융권, 의료계, 증권시장 등)
OAuth 1.0 -> 2.0 으로 넘어오면서 클라이언트의 복잡성 해소를 위해 다소 보안을 희생한 trade off 가 있었음
이런 부분이 민감한 사용처들이 사용하기엔 보완이 필요했음
여러 RFC 보안책들을 하나로 모아 스펙화 시키고 현재 구현에 모범 적용 사례들을 스펙화 시킴
토큰 탈취에 취약한 implicit 배제
유저에게 직접 아이디, 비밀번호 받는 resource owner password credentials 배제
Device Authorization Grant 추가
- IoT와 관련된 여러 스마트 기기에 적합 사용하는 해당 기기가 아닌 다른 기기를 통해 인증을 받는 플로우
POST /token HTTP/1.1
grant_type=urn%3Aietf%3AParams%3Aoauth%3Agrant-type%3Adevice_code
&device_code=QdlkfwodfkSwldkfRkdmwdf
&client_id=143205482
OAuth 2.0의 Authorizaton code grant에 추가된 PKCE
Authorization code flow 시작시 클라이언트가 랜덤값에 대한 hash를 인가 서버에게 보냄,
그리고 액세스 토큰 요청을 보낼 때 해당 해쉬값의 원문을 같이보냄
-> 첫 요청을 탈취하더라도 해쉬 연산을 역연산을 할 수 없기 때문에
첫 요청을 시작한 클라이언트와 마지막으로 토큰을 발급받고자하는 클라이언트가 동일한 서버임을 확인할 수 있음
리프레시 토큰은 access token보다 긴 사용기간을 가지고 있었고, 똑같은 리프레시 토큰을 가지고 새로운 access token을 발급받았다면 2.1 부터는 refresh token이 일회성이 되어서 refresh token으로 새로운 access token을 발급받으면 기존에 있던 refresh token은 사용할 수 없게되고 새로운 refresh token을 발급받는 회전방식을 채택
OAuth 2.0에서 토큰을 발급받았던 flow에서 추가적으로 JWT기반의 ID 토큰이라는 또다른 토큰을 같이 받을 수 있음
OAuth 2.0에서 사용자 정보를 알아보기 위해서는 토큰을 가지고 API call을 해야했었던 것과는 다르게
직접적으로 ID 토큰을 파싱하고 안에 있는 서명값을 검증함으로써 API call을 하지 않고도 사용자에 대한 정보를 가져올 수 있음.
이것이 Open ID가 많이 쓰이는 이유고, 트래픽이 늘어나는 인터넷 환경에서 Open ID Connect가 2.1스펙보다 먼저 IDP(IDentity Provider)를 구현하는 이유
통신 부하를 줄이기 위해 Open ID connect가 생겼구나-> api call 하지 않으니 !
생활코딩 - OAuth 2.0
https://ko.wikipedia.org/wiki/OAuth
https://datatracker.ietf.org/doc/html/rfc6749#section-1.2
https://hudi.blog/oauth-2.0/
https://www.youtube.com/watch?v=DQFv0AxTEgM
https://www.samsungsds.com/kr/insights/oidc.html
글 잘 봤습니다.