[OAuth 프로토콜이란?]
어떤 회사가 자신의 서비스를 운영하기 위해 어떤 리소스가 필요하다고 가정하자. 근데, 해당 리소스를 처음부터 수집하고 가공하는 일은 노력이 많이들기도 하고, 서비스 사용자에게도 불편한 경험이 될 수 있다. 이 때 구글이나 네이버 같은 대기업에서는 당사에서 미리 만들어 놓은 리소스를 사용할 수 있도록 api 를 공개하는 경우가 있다. 이 때 구글, 네이버 같은 기관은 OAuth provider 라고 말한다. 이 리소스는 민감한 정보(사용자의 개인정보 등)를 포함할 수 있기 때문에 안전하게 미리 약속된 방식으로 데이터를 주고 받을 필요가 있다.
이처럼 에서 HTTP 상으로 정보를 안전하게 주고 받을 수 있도록 통일한 규약을 OAuth 프로토콜이라고 한다.
1. 구성요소 4가지
아래는 OAuth 프로토콜 상에서 정의되는 4가지 역할에 대한 간단한 개념을 설명한다.
- resource owner : 리소스 소유자로서, 해당 리소스로의 접근을 허락할 수 있는 주체이다. 사람인 경우에는 end-user 라고 한다. (ex. 개인정보의 resource owner 는 end-user이다.)
- resource server : 리소소를 hosting 하는 서버를 말하며, access 토큰을 이용해 리소스 요청을 받고 응답한다. (ex. end-user 의 개인정보를 저장하고 있는 naver 서버)
- client : resource owner를 대신해서 리소스 요청하는 application (ex. 소셜로그인을 통해 사용자의 개인정보를 가져오는 온라인 게임 서비스)
- authorization server : resource owner 임을 성공적으로 확인한 후에 client 에게 access token 을 발급하는 서버.
개념상으로는 resource server 와 authorization server 가 분리되어 있지만, 물리적으로는 하나로 합쳐져 있을수도 있고, 여러대로 나뉘어 있을수도 있다. 보통 관념상 resource server 와 authorization server 를 한 기업에서 담당하는 경우가 많기 때문에 (예를 들어 네이버나 구글 등), oauth 프로토콜을 잘 따르면서 이 두가지의 서버를 갖고 관련 서비스를 제공하는 기업을 oauth provider 라고 하는 듯하다.
2. 프로토콜 흐름
위의 프로토콜 흐름도가 잘 이해되지 않는다면, OAuth 4가지 역할 부분의 그림을 참고해도 된다.
이해를 돕기 위해 소셜로그인 상황을 떠올려보자. 그러면 아래와 같이 구체화할 수 있다.
(단 OAuth에서의 Client(모바일 어플 등)와 Resource owner(client 입장에서의 사용자)와 혼동하면 안된다!)
- Client - 모바일 어플리케이션
- Resource Owner - 해당 앱을 사용하는 사용자
- Authorization server & Resource server - 구글, 네이버 등
- 모바일 앱은 사용자에게 개인정보에 대한 허가를 요청한다. 직접적으로 요청하는 방법도 있지만 가장 흔히 접하는 경우는 authorization server 를 이용해서 간접적으로 요청하는 방법이다. 예로 네이버 소셜로그인 할 때, 네이버에서 제공하는 로그인 창이 나타난 걸 본 경험이 있을 것이다.
- 모바일 앱은 요청이 허가되었음을 확인한다. 사용자가 해당 리소스 사용에 대한 요청을 허가했다는 응답을 authorization grant 라고 하며, grant 하는 방법 여러가지이다. 표준에 명시적으로 정의된 4가지 방법(authorization code/implicit/resource owner password credentials/client credentials)과 extension grant type 으로 나뉜다.
- 모바일 앱은 authorization grant 결과를 바탕으로 authorization server 에 access token 을 요청한다. 이 때 현재 요청하는 모바일 앱이 정당한 oauth 이용자인지 인증하는 과정을 포함한다. (client id, client secret 등으로 검사)
- Authorization server 는 모바일 앱에 대한 인증을 수행하고, 모바일 앱이 제출한 authorization grant 결과가 유효한지 검사한다. 모두 다 유효하면 access 토큰을 발급한다.
- 모바일 앱은 access 을 제시함으로써 resource server 에 리소스 요청을 할 수 있다.
- Resource server 는 해당 토큰이 유효하다면, 요청을 처리한다.
3. Authorization Grant Type
authorization grant 는 resource owner가 client로 하여금 해당 리소스를 사용해도 된다고 허락한 것을 의미하며, 4가지의 방식이 존재한다.
(1) Authorization Code
resource owner 가 사용허가를 application(oauth client)에 직접하지 않고, authorization server 에게 간접적으로 하는 방식이다. resource owner 가 authorization server 에 직접 허가를 한 뒤에 허가의 증거로 auth server 는 임시 코드를 발급해준다. client 는 이 임시 코드를 application 에 제출하게 되고, 최종적으로 application이 임시코드(resource owner의 허락 증거물)를 authorization server 에 제출함으로써 허락이 완료된다. (이 때 oauth client 자체에 대한 인증까지 완료되면 access 토큰이 발급된다.) 임시토큰을 authorization code 라고 한다.
이 방식은 oauth client 대한 인증 뿐만 아니라, access token 을 외부 노출 없이 안전하게 전달할 수 있다는 장점이 있다.
(2) Implicit
authorization code 의 간소화된 방식으로, 스크립트 언어를 사용하는 in-browser application 형태의 client 에서 주로 사용한다. authorization code 대신에 access token 을 바로 발급받는다. application(client) 자체에 대한 인증도 이루어지지 않는다.(경우에 따라서 redirection uri 방식으로 지원하는 경우도 있음)
절차가 간단하기 때문에 더 효율적이라는 장점이 있지만, access token 이 노출될 수 있다는 보안상 취약점이 존재한다.
(3) resource owner password credentials
username and password 등의 방식이다. 자원 소유자의 비밀번호가 직접적으로 access token 을 얻는데 사용된다. authorization code 대신 owner 의 password를 전달한다고 생각하면 된다. 모바일 os 등 접근이 제한된 client 에게 적용가능한다. 즉 resource owner 와 client 사이의 신뢰가 높아야한다. resource owner의 정보를 client가 직접 다루기 때문에 다른 인증 방법이 불가할 때만 사용하도록 권장된다.
(4) client credentials
client가 소유하고 있는 어떤 정보가 그 자체로 authorization grant 로 사용된다. client가 스스로 resource server 의 역할을 할 때나, 기존에 authorization server에 의해 허가된 인증(access token 등)을 재사용하는 경우 등에서 사용된다.
4. Access & Refresh token
(1) access 토큰, refresh 토큰 의미
- protected resource를 요청할 때는 꼭 액세스 토큰을 제시해야한다. 토큰은 client에게 발행된 인증에 관한 내용을 담는 암호화된 문자열이다. 인증 범위나 인증 기간 등의 정보를 포함하는데, resource owner 에 의해 grant 되어야하는 부분이다. 액세스 토큰 자체에 대한 권장사항은 RFC6750 을 참고해야함.
- 리프레시 토큰은 액세스 토큰과 비슷한 형태를 띄고 있는데, 보통 액세스 토큰보다 만료기간 길다는 차이가 있다. 이는 보안상의 문제로 인한 절충안인데, 만약 만료기간인 긴 토큰이 갈취당했을 경우를 생각해보자. 그러면 공격자는 해당 토큰이 만료되기 전까지는 protected resource 를 마음껏 요청해서 받아올 수 있다. 이런 위험성을 줄이고자 access token 의 만료기간을 상대적으로 짧게하고, refresh token 를 길게 한다. 그래서 액세스 토큰이 만료되었을 때, refresh token 을 이용하여 새로운 access token 발급을 요청하게 된다.
(2) access 토큰 재발급 시나리오
- 4가지 방법 중 하나의 authorization grant 방법으로 access token 을 요청한다.
- client 인증 + authorization grant 유효성 검사 => access 토큰과 refresh 토큰 발행
- access token으로 protected resource 요청
- access token이 유효하면, 해당 리소스 제공
- 토큰이 만료될 때까지 (C)와 (D)를 반복한다. 이후에 만료된 access token으로 protected resource 요청
- 만료된 토큰이라고 응답
- refresh token으로 새로운 access token 발급해달라고 요청한다. 이 때 client에 대한 인증도 함께 이루어진다.
- client 인증 + refresh token 유효성 검사 => access token 을 재발급(경우에 따라 refresh token 도 재발급 가능)
[Client Registration]
프로토콜을 이용하기 전에, client는 authorization server 에 등록되어 있어야한다. 각 provider에 client를 등록하는 방법에 대해서는 정확한 규정이 없다. client가 authorization server 사이에 직접적으로 등록될 필요도 없다. redirect URI, client type 등의 필요한 client 정보를 얻을 수 있는 신뢰할 만한 어떤 채널을 통해 간접적으로 등록될 수 있다.
1. Client Types
(1) 기밀성에 따른 분류
authorization server 와 얼마나 안전하게 인증할 수 있는지에 따라 confidential과 public 으로 나눌 수 있다. 이렇게 나누는 목적은 authorization server 입장에서 client의 안전성에 따라 resource의 공개 범위를 결정하게 하기 위함이다.
- confidential : 기밀성을 유지할 수 있는 client를 의미. 안전한 server에 접근 권한이 철저하게 제한된 서버등을 예로 들 수 있다.
- public : 기밀성을 유지할 수 없는 client 를 의미, resource 나 토큰이 그대로 노출된다. resource owner가 소유하고 있는 device 등을 예로 들 수 있는데, native application이나 web brower-based application 등이 있다.
(2) type에 따른 client 예시
한 클라이언트는 여러 components로 구성될 수 있는데, 각각의 component가 각자 다른 client type과 security context를 갖는다면 (ex, 웹앱과 모바일 네이티브 앱), 각각의 구성요소를 authorization server 에 등록해야한다. 대표적인 client 의 예시는 다음과 같다.
- web app
: 웹앱은 웹서버에서 운영되는 confidential client 이다. 클라이언트 자체 정보나 resource owner의 토큰 등은 모두 웹서버에 저장되고, resource owner 가 접근 불가능하다. - user-agent-based app
: public client 이다. client 의 코드를 웹 서버로부터 다운받을 수 있고, 인증 정보에 접근가능하다. - native app
: public client 이다. resource owner 의 device에 의해 설치 및 실행되고, resource owner 가 쉽게 추출할 수 있다. 뿐만 아니라 같은 장치 내의 다른 어플리케이션이 쉽게 접근할 수도 있다.
2. Client Authentication
client identification을 확인하고 싶다면, authorization server 와 client 간의 인증절차를 거쳐야한다. Confidential clients는 인증에 필요한 정보를 authorization server 와 나눠 가질 수 있다. (ex, password, public/private key pair, etc.) 하지만 public clients 에 대해서는 identify 를 목적으로 인증을 할 수 없다. public client 임을 증명할 수 있는 어떤 데이터가 있다고 하더라고, 충분히 갈취당할 수 있기 때문이다. confidential clients 인증 방법에는 아래와 같은 방법이 존재한다.
- Client Password
: Http basic 인증 방식(RFC2617)을 사용한다. Authorization 헤더에 "Basic $(password)" 형태로 담아서 전송해도 되고, 또는 request-body에 client_id와 client_secret을 담아서 보내도 된다. 하지만 직접적으로 request-body에 클라이언트 정보를 담는 것을 권장되지 않고, 직접적으로 HTTP Basic 인증 방식을 사용할 수 없는 경우에만 이용하도록 제한한다. request-body에 포함될 정보를 request-uri에 절대로 담아서는 안된다. 액세스 토큰 재발급 요청을 예로 들면 다음과 같다.
- Other Authentication Methods
: 다른 적당한 HTTP 인증 방식을 사용할 수 있다.
[Protocal Endpoints]
인증과정에서 필요한 서로 다른 두 인증 객체 사이의 endpoint를 다음과 같이 정의할 수 있다.
- Authorization endpoint
: resource owner 로 부터 authorization grant를 받기 위해 사용됨. (user-agent redirection 방식) authorization server가 client에게 authorization grant를 전달하기 위해서는 Redirection endpoint를 이용함. - Token endpoint
: client 가 access token을 위해 authorization grant를 제출할 때 사용됨
[출처]
'웹 프로젝트 (IBAS) > SpringBoot api 개편' 카테고리의 다른 글
DDD, 어그리게이트 분리를 위한 리팩토링 (0) | 2022.06.27 |
---|---|
OAuth2 naver 회원 id 형식 문제 (네아로) (0) | 2022.05.14 |
[Spring Boot] 4. 로컬 개발을 위한 CORS 설정 - (2) Spring MVC 와 Spring Security (0) | 2022.04.15 |
[SpringBoot] 6. ManyToMany 를 "일대다/다대일"로 풀어서 사용하기 (+ 영속성 전이 문제) (0) | 2022.03.20 |
[Spring boot] 5. 멀티모듈? MSA? 좋은 아키텍쳐가 뭐야?! (1) | 2022.03.09 |