2023년 1월 1일
08:00 AM
Buffering ...

최근 글 👑

Oauth2 필터체인 동작 방식 흐름 및 이해

2024. 2. 5. 18:18ㆍ스프링 시큐리티 -세션/Oauth2.0

 

 

 

 

[Oauth2 Filter 흐름 및 이해]

 

이 포스팅을 보기전 

 

[스프링 시큐리티 Oauth2.0] Oauth2.0 동작방식 (tistory.com)

 

[스프링 시큐리티 Oauth2.0] Oauth2.0 동작방식

[소개] Oauth2를 사용하기 위해서 Oauth의 흐름을 알아보도록 한다. [Oauth2 사용자] Oauth의 경우 총 4명의 사용자들을 정의 할 수 있다. ● Resource Owner(사용자) : 일반적으로 사용자를 가르키며 소셜 서

thaud153.tistory.com

 

이 Oauth2의 동작이 어떤식으로 이루어지는지 보고 오길 바란다.

 

 

 

1. Authorization Code 요청 하기

 

● code를 요청하는 방식에는 두 가지 방식이 있다.

 

1. 프론트에서 요청 후 백엔드에게 전송

 

이 방식을 사용한다면 백 채널에서는 코드를 받는 필터는 동작하지 않게 되고

프론트에서 코드를 받은 순간 필터가 작동한다.

 

2. 백엔드에서 코드를 요청 후 리다이렉트 경로로 코드를 받음.

 

이 방식은 백엔드 자체에서 코드를 발급 요청을 한 후 리다이렉트 경로를 이용해서

코드를 받은 후 처리한다.

 

우리는 2번째 방식에 대해 알아볼 것 이다.

 

1. 사용자에게 oauth2 화면을 보여준다 

 

 

 

 

2. 경로

 

naver,google,kakao와 같은경우

/oauth2/authorization/code/google

 

 

/oauth2/authorization/code/naver"

 

"/oauth2/authorization/code/kakao"

 

이러한 기본경로를 가지고있다.

 

이 경로의 의미는 oauth2.authorization/code/{registerationId}

가 들어온다면 

 

 

 

 

 

Oauth2AuthorizationRequestRedirectFilter가 동작하게 된다.

 

인터셉트의 조건은 oauth2/authorization/code/{registertionId}의 경로로 들어오면

이 필터가 시작되고 이 필터가 구글혹은 네이버등의 인증창을 리다이렉트 시켜서 

사용자에게 구글 인증을 보이게 하는 필터이다.

 

 

 

 

 

code는 이러한 방식으로 필터체인이 동작하는데

 

 

1.  사용자가 oauth2/authorization/{registrationId} 링크로 들어온다

 

●  Oauth2AuthorizationRequestRedirectFilter가 oauth2/authorization/code/{registerationId}로 들어오게 된다면

인터셉트를 하여 이 경로로 들어온 사용자를 해당 인증 페이지로 리다이렉트 시킨다 

 

2. DefaultOauth2AuthorizationRequestResolver

 

● 사용자를 인증 서버 (구글 로그인)로 리다이렉트 하기전 Oauth2AuthorizationRequest 객체를 생성하는

역활을 한다.

 

● 즉 이클래스는 인증 서버로 보낼 인증 요청을 구성하는데 사용된다.

 

요청 매칭 들어오는 요청이 oauth2/authorization/{registrationId}와
같이 oauth2를 시작하는데 사용되는 URL 패턴과

일치하는지 확인한다.

 

Oauth2AuthorizationRequest  생성 

 

● 일치하는 요청을 발견한다면 이 클래스는 해당 요청에 기반하여 Oauth2AuthorizationRequest 객체를 생성한다.

 

● 이 객체에는 인증 요청에 필요한 모든 정보가 포함된다.

 

client_ id : 인증을 요청하는 클라이언트 id임.

 

redirct_uri : 인증 후 사용자를 리다이렉할 클라이언트 url

 

scope : 클라이언트가 요청하는 권한의 범위

 

state : CSRF 공격으로부터 보호하고 인증 요청과 응답 사이의 연속성을 유지하기 위한 값

 

--------------------------------------------------------------------------------

 

인증 URL 구성 : 위의 정보를 사용하여 사용자를 인증 서버 URL 리다이렉트할 준비를 한다.

 

●리다이렉트 실행 

 

oauth2AuthorizationRequestRedirctFilter가 이 oauth2AuthorzationRequest를 사용하여 사용자를 

실제 인증서버로 리다이렉트 한다.

 

 

3. Maches가 yes인 경우

 

● DefaultOauth2AuthorizationRequestResolver가 생성한 Oauth2AuthorizationRequest가

현재 들어온 인증 정보와 같은지 비교함.

 

즉 사용자가 처음에 요청한 인증 정보와 인증 서버로부터 리디렉션될 요청의 정보와 일치하는지

확인하는 과정임.

 

이 맥락에서 "일치한다"라는 것은 사용자가 인증을 요청할 때 사용한 {registerationId} -> 구글 네이버 카카오 등

이 서버로 돌아온 요청의 정보와 같다는 의미임.

 

4. action : /login

 

● {action}/oauth2/code/{registrationId}

 

-> 여기에 적힌 url 경로는 우리가 properties에서 설정한 url 경로임.

 

 

● 시큐리티가 이 경로를 요청하게되고 시큐리티는 Oauth2AuthorizationRequest에서 들어있는 값의 정보를

 

HttpSessionOauth2AuthorizationRequestRepository에 Oauth2AuthorizationRequest의 객체를 저장한다.

 

 

HttpSessionOauth2AuthorizationRequestRepository는 Oauth2AuthorzationRequest객체를

저장한다.

 

sendRedirct

 

client_id , response_type , state , redirect_url등이 저장된 Oauth2AuthorzationRequest를

인증서버로 전송한다.

 

●인증서버에 정상적으로 요청을 하였다면 인증 서버에서 액세스 토큰과 바꾸기 위한

code를 발급한다.

 

 

여기까지가 code발급이다. 해당 code발급은 보통은 프론트에서 진행하게 되며

프론트에서 code를 백엔드 채널로 주는 경우가 보통이다.

 

 

 

[Code를 받은 후 -> AccesToken 요청]

 

 

 

 

 

1. 코드를 받은 후 인증서버는 프로퍼티스에 저장되어 있는 redirct_url 경로로 리다이렉트 시킨다.

리다이렉트 경로는 /login/oauth2/code/{registrationid}이다.

 

2.  /login/oauth2/code/{registrationid}

 

 

●  이 경로로 들어오게 되면 Oauth2LoginAuthenticationFilter가 받게 된다.

 

 

3. HttpSessionOauth2AuthorizationRequestRepository

 

 

●인증을 시작할 때 생성된 Oauth2AuthorizationRequest를 저장하는 저장소이다.

 

●이 저장소는 HTTP 세션을 사용하여 인증 요청을 저장하며 , 나중에 인증 요청을 나타내는 객체이다.

 

●위에서도 설명했다싶이 인증 서버로부터 리다이렉를 받을 때 필요한 정보들이 들어있다.

 

 

4.Oauth2AuthorizationResponse 

 

● 인증 서로부터 응답을 나타내는 객체이다.

 

이 객체는 리다이렉션 후에 상태 등이 포함되어있다.

 

 

5. Oauth2LoginAuthenticationToken

 

● 이 토큰에는 인증코드 , 클라이언트 정보(클라이언트 id , 시크릿 번호)를 담아

 

Oauth2AuthorizationCodeAuthenticationProvider에 전달한다. 

 

즉 이 객체는 인증 코드를 액세스 토큰으로 교환하는데 필요한 정보를 담고 있는 토큰이며

"미인증"상태로 사용된다.

 

그리고 나서 , 액세스토큰을 받아 사용자 인증을 완료하면 토큰은 "인증" 상태로 바뀌며

사용자의 인증 정보를 애플리케이션 내에서 참조할 수 있음.

 

 

 

6.OAuth2AuthorizationCodeAuthenticationProvider 

 

● 인증 코드를 액세스 토큰으로 교환하는 과정을 처리하는 객체이다.

 

● 인증 코드 검증 : 사용자로부터 받은 인증 코드가 유효한지 확인한다.

 

 

 

7. RestTemplate -> ResponseEntity

 

  액세스 토큰 요청

 

  Oauth2.0 액세스 토큰으로 교환하기위 인증 서버 엔드포인트 (/token)으로 post요청을 보낸다.

 

이 요청은 필요한 모든 파라미터를 포함하며 , client_id , clint_secret ,code ,grant_type ,redirct url

등이 포함된다.

 

요청 엔티티 구성 :  RestTemplate은 RequestEntity 객체를 사용하여 요청 본문 , 헤더 ,

Http 메서드 , URL등 요청에 필요한 정보를 구성한다.

 

RequestEntity는 RestTemplate에 의해 엔드포인트로 보내지게 되고 이 요청을 받은 객체가

ResponseEntity가 된다.

 

 

8. ResponseEntity

 

비로소 액세스 토큰을 받게 되었다.

 

이 객체는 일반적으로 json 형태로 액세스 토큰과 관련된 (access_token , token_type , expires_in ,

refresh_token ,scope의 정보들을 가지고있다)

 

Http 상태코드

 

요청이 성공적이였는지 에러가 발생했는지의 여부의 상태를 저장하는 상태코드를 가지고있다.

 

 

9. Oauth2AuthorizationCodeAuthenitcationToken

 

비로소 이 토큰은 "미인증" 상태에서 "인증"상태로 바뀌게 된다.

 

인증 후 

 

●인증 서버로 부터 액세스 토큰을 성공적으로 받았다면 이 객체는

 access token,refresh token등을 포함하게 된다.

 

● 즉 이 객체는 초기에는 액세스 토큰과 리프레쉬 토큰을 포함하지 않지만

인증 과정을 완료하고 난 후 이 액세스 토큰을 포함하게 되며 인증된 사용자를 나타나는데 사용된다.

 

● 이렇게 변환된 토큰은 OAuth2AuthenticationToken불린다.

 

 

 

10.  Oauth2Request

 

 

이 객체는 Oauth2.0 인증 프로세스 중 액세스 토큰을 교환한 후 생성 된다.

 

  액세스 토큰 

 

사용자가 인증 서버로부터 받은 액세스 토큰을 가지고있다.

 

등록된 클라이언트 정보

 

Oauth2UserRequest는 Oauth2 클라이언트 구성 정보를 포함한다.

 

이는 ClientRegistration 객체에 의해 나타내어지며
클라이언트 id , 시크릿 , 인증 방법 , 토큰 url등이 포함되어있다.

 

이 객체는 DefaultOauth2Service 일 때 매개변수 값으로 들어오게 되며 

DefaultOauth2Service의 반환 값은 Oauth2User가 된다.

 

 

11. DefaultOauth2Service

 

●이 객체는 Oauth2UserRequest의 매개변수 값을 받으며

이 받은 객체를 바탕으로 DefaultOauth2Service에서 DB와 연결한 후 사용하는 것이 일반적이다.

 

 

 

--------------- ---------------------------------

 

여기까지가 액세스 토큰을 가져오는것이고

 

유저의 정보를 가져오는 것은 매우 간단한다.

 

 

DefaultOauth2Service의 클래스에

 

@Override
//여기에 들어오는 userRequest 액세스토큰과 , 코드등이 들어있음 유저 정보는 X
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
    ClientRegistration clientRegistration = userRequest.getClientRegistration();

    OAuth2UserService<OAuth2UserRequest,OAuth2User> oAuth2UserService
            = new DefaultOAuth2UserService();



    //이 메서드 호출로 유저의 정보를 가져옴.
    //이 메서드 호출로 oauth2User에는 유저 정보가 들어있음.
    OAuth2User oAuth2User = oAuth2UserService.loadUser(userRequest);

 

 

이러한 클래스가 있다.

 

oauth2UserService.loadUser(userRequest)를 넣으면

 

시큐리티에서 액세스토큰을 기반으로 유저 정보를 가져오는데 

유저 정보의 담긴 객체 이름이 Oauth2User이다.