OAuth2.0 이 뭐에요 ?
Open Authorization의 약자로, 웹 애플리케이션이나 모바일 앱 등에서 인증(Authentication)과 인가(Authorization)를 처리하기 위한 표준 프로토콜이다. 표준이기 때문에, 사용자가 직접 자신의 자격 증명을 애플리케이션에 직접 제공하지 않고도, 신뢰할 수 있는 제 3자 서비스(Goolge, Kakao 등)을 통해 자신의 자원을 안전하게 공유할 수 있도록 설계되었다. 뒤에 붙은 2.0 은 버전을 의미한다.
OAuth 2.0 의 특징
- 주로 사용자의 권한을 관리한다는 것에 목적이 있다. 사용자가 누구인지 인증하는 것에도 쓰이지만, 결국 주된 목적은 권한 관리에 있다.
- 사용자의 민감한 정보(비밀번호)를 노출하지 않고도, 제 3자가 사용자의 자원(이메일, 캘린더 등)에 접근할 수 있도록 설계할 수 있다.
- Token 기반으로 서버 간의 인증을 처리한다. 이때 AccessToken 과 RefreshToken 의 개념이 들어간다.
- 서명을 사용했던 1.0 버전대 대신 2.0 버전에서는 Bearer Token 기반 인증을 사용한다.
- 권한을 부여하는 여러 Grant Type 이 있다. (Authorization Code, Client Credentials 등).
OAuth 2.0 Roles (역할) 에 대하여.
요소 | 역할 | 예시 |
Client | 리소스 요청자 (애플리케이션) | 쇼핑몰 앱, 모바일 앱 |
User | 일반(실제) 사용자 | Google 계정을 가진 사용자 |
Resource Owner | 리소스 소유자 | Gmail 사용자 |
Resource Server | 보호된 리소스를 호스팅하는 서버 | Google Drive API |
Authorization Server | 사용자 인증 및 Access Token 발급 서버 | Google OAuth 서버, Keycloak |
Client 를 Resource Server 에 등록하는 방법
필요한 요소들
- Client ID : 애플리케이션 식별자
- Client Secret : 애플리케이션에 따른 비밀번호
- Authorized Redirect URIs : Authorized Code 를 전달해줄 url
중요한 것은, Client ID 와 Redirect URI 를 Resource Server 에 전달해주면, Client Secret 을 발급해준다는 것이다.
Resource Owner 에게 개인정보를 수집해도 되는지 물어봐야 한다.
위 이미지는, Resource Owner 인 나에게 Google 에게 나의 이름, 이메일 주소 등을 공유해도 되는지 물어보는 창이다. 이 창이 뜨고, 계속(Allow) 버튼을 누르는 과정에서 어떤 일이 일어나는 걸까?
< 이 예시의 역할정리 먼저 >
- Resource Owner : 사용자
- Client : Leetcode.com
- Resource Server : Google
- Authorization Server : Google
1. 일단 Client 와 Resource Server 는 (Client 를 이미 Resource Server 에 등록했으므로) 등록한 Client ID 와 Password, Redirect URL 를 알고있다.
2. 이 시점에서 Resource Owner(사용자)가 `구글로 로그인하기` 버튼을 클릭하면 다음과 같은 정보가 담긴 url 이 Resource Server 로 날아간다.
url 구조 | GET/ (Resource Server의 지정된 주소) ?client_id=(Client_id) &scope=B,C &redirect_uri=(Redirect URL) |
url 예시 (keycloak) |
http://localhost:8081/realms/oauth2/protocol/openid-connect/auth?response_type=code&client_id=oauth2-client-app&scope=profile email&redirect_url=http://localhost:8080 |
이 때 Scope 란, 모든 자원에 대해서 인가를 허용할 수 없으니, 그 범위를 지정하는 것이다.
여기서는 이름, 이메일일것이다.
3. 이제 Resource Owner(사용자)가 로그인을 하고, Allow 버튼을 클릭했다. 그렇게되면 Resource Server 는 특정 UserA 가 scope B 와 C 에 대해서 허용했다. 라는 내용을 알게된다. 즉, 내(사용자)가 Google 에게 이렇게 말한것이다. "leetcode(Client) 에게 너가 이미 알고있는 내 이름과 이메일 등을 공유하도록 허용할게."
4. 그러면 이제 그 증거로 Resource Server 인 Google 인 Resource Owner 인 나(사용자)에게 Authorization code 가 담긴 url 를 전송한다. Redirect Url 에 담아서!
url 구조 | GET/ (Redirect URL)?code=(Authorization code) |
url 예시 (keycloak) |
http://localhost:8080/?session_state=6b4ea5ee-cc4f-4b9c-8623-e9f2b2d0d25c&iss=http%3A%2F%2Flocalhost%3A8081%2Frealms%2Foauth2&code=c54dad36-a58d-4393-9759-d5d01113ed87.6b4ea5ee-cc4f-4b9c-8623-e9f2b2d0d25c.fa88663a-c0dd-4f7f-9502-b985b7f46632 |
... 와 동시에 Client 에게도 이 url 이 전달된다.
5. 이제 Client 에서 AccessToken 을 받아올 차례다. Client 는 토큰 값을 얻어오기 위해서 발급받은 Authorization code 가 담긴 url 요청을 Resource Server 로 보낸다.
url 구조 | POST/ (Resource Server의 지정된 주소) grant_type=authorization_code client_id=(Client ID) client_secret=(Client Password) redirect_uri=(Redirect URL) code=(Authorization code) |
url 예시 (keycloak) |
http://localhost:8081/realms/oauth2/protocol/openid-connect/token (나머지 요소들은 POST 요청의 Body에 넣는다) |
그러면 이제 Client 와 Resource Sever는 AccessToken을 나눠갖는다.
이제 AccessToken 이 발급되었다!
이 엑세스 토큰에 어떤 정보가 들어있을까? 앞서 말했다시피, OAuth 2.0 은 `인가`를 우선한다고 했다.
이제 이 Access Token은, 특정 사용자를, 특정 클라이언트에서, 특정 자원(Scope)에 대한 인가를 허용한다는 증명이 되는 셈이다. 이제 이 세가지의 요소 중에 하나라도 바뀐다면 자원에 접근되지 않을 것이다.
그런데 사실, AccessToken 과 함께 발급되는 토큰이 하나 더 있다.
바로, RefreshToken 이다.
(A) 토큰을 요청한다
(B) AccessToken 과 RefreshToken 을 발급받는다
(C) AccessToken 으로 지정된 Resource 에 접근한다
(D) Resource 를 받아온다
(E) 시간이 흐른 뒤, 또 AccessToken 으로 지정된 Resource 에 접근한다
(F) 이번에는 AccessToken 이 만료되어서, Resource에 접근할 수 없게 된다.
(G) AccessToken 을 재발급 받기 위해 RefreshToken 을 Authorization Server 에 요청한다.
(H) Authorization Server 는 AccessToken 을 발급해주고, 최초에 발급했던 것과 마찬가지로 만료 시간(expires_in)도 함께 발급한다.
결론.
RefreshToken 은 AccessToken 을 재발급 하기 위해서 존재한다!
1. AccessToken 에 만료 시간을 주는 이유
- 탈취 위험 감소
AccessToken이 노출되더라도 짧은 만료 시간 덕분에 공격자가 사용할 수 있는 시간을 제한하는 등 - 최소 권한 보장
사용자의 권한이 변경되었을 때도 단순히 AccessToken 을 만료시키는 방식으로 최소 권한을 보장
2. RefreshToken 이 필요한 이유
- 끊김 없는 세션 유지
사용자가 로그아웃하지 않는 한, 로그인을 다시 요구하지 않는다. - 서버 부하 감소
매번 Authorization Server 와 통신하지 않고, Resource Server가 Authorization Server와 독립적으로 토큰을 검증 - 보안성 증가
RefreshToken 은 클라이언트 내부에서만 사용되므로 외부 노출 가능성이 낮기 때문에, AccessToken 이 탈취되더라도 Refresh Token 이 없으면 재발급이 불가능하다.
'Framework > Spring' 카테고리의 다른 글
[OAuth2] 기본적인 로그인 연동은 이미 스프링에서 구현해놓았다? (0) | 2024.12.08 |
---|---|
[OAuth2] Spring Security 가 OAuth2 를 구현하는 방법 (0) | 2024.12.08 |
[Spring Security] HttpBasic 방식을 비활성화 하는 이유 (0) | 2024.11.27 |
[Spring Security] HttpSecurity 객체와 필터 체이닝 (1) | 2024.11.26 |
[HandlerExceptionResolver] Spring MVC의 예외 처리 흐름 (0) | 2024.11.26 |