2025. 3. 14. 17:22ㆍSpringboot/security
※전체코드 : https://github.com/gks930620/spring_securty_all
https://brilliantdevelop.tistory.com/226에 이어 jwt방식에 oauth2로그인을 적용해보겠다.
백엔드서버인 spring boot를 기준으로 설명한다.
예시는 카카오 로그인이다.
세션/JWT 방식과 Oauth 이해.
세션과 JWT는 사용자 정보를 어디다 저장하느냐의 대한 차이인거고,
Oauth는 이 사용자 정보를 어떻게 얻냐에 대한 거다.
전통적인 SSR 방식 : Oauth를 사용하면 인가코드 방식으로 카카오의 사용자정보를 얻고, 이 정보를 세션에 저장
굳이 SSR방식에서 JWT를 사용할 필요는 없다.
서버가 여러개여도 세션클러스터링을 통해 해당 세션을 얻으면 되기때문에 JWT 필요없다.
프론트/ 백엔드 분리 : Oauth를 사용하면 역시 인가코드 방식으로 사용자정보를 얻고, 이 정보를 JWT에 저장
이 때 oauth를 통해 oauth서버(카카오)에서 사용자정보를 얻는건 백엔드.
이게 일반적인 상황이다.
다만 프론트/백엔드 분리가 된 상황에서도(또는 백엔드 프로젝트가 따로 없는)
프론트가 만약 모바일 앱이라면 Oauth를 백엔드가 아니라 모바일앱에서 직접 access_token을
발급 받을 수 있다. 이건 인가코드 방식이 아니라 access_token 직접 방식.
(사실 이게 더 간단하다..)
여기서는 프론트가 모바일앱에 한정되지 않고 CSR방식의 웹이든 모바일 앱이든 상관없이
프론트/백엔드가 분리된 상황에서 백엔드가 Oauth를 인가코드 방식으로 사용자정보를 얻고,
이 정보를 JWT에 저장하는 방식에 대해 설명한다.
책임분배
Oauth2 로그인에서 프론트와 백엔드가 어떤 역할까지 수행할 건지에 문제이다.
프론트에서 인가코드만 백엔드로 전달할 것인지,
프론트가 access_token까지 얻은 후 백엔드로 전달할 것인지 등이다.
이전 글에서 했던 웹 seesion방식의 Oauth2 기능은 인가코드만 백엔드로 전달하는 형태였다.

보시다시피 웹 session방식에서는 백엔드가 인가코드-access token - 리소스서버 과정을
전부 담당하고 있다.
이런식으로 프론트가 인가코드만 백엔드에 전달하는 방식은 다음과 같은 장점이 있다.
- 보안성 증가: Access Token이 외부(클라이언트)에 노출되지 않음.
- 클라이언트의 부담 감소: 클라이언트는 인가 코드만 받아서 서버로 넘기면 되므로 구현이 단순해짐.
- 토큰 관리가 서버에서 일관되게 이루어짐
동작방식
클라이언트가 로그인버튼 클릭

먼저 클라이언트가 localhost:8080/custom-oauth2/login/kakao에 요청한다.
웹 세션방식에서는 /oauth2/authorization/kakao주소인데 이는 security가 기본적으로 인식하는 URL이다.
/oauth2/authorization/kakao로 요청을 하면 security는 클라이언트에게
authorization-uri : https://kauth.kakao.com/oauth/authorize 로 redirect하는게 기본 동작이지만
브라우저가 아닌 JWT방식에서는 클라이언트에게 redirect 를 하게 할 수는 없다.
그래서 security 기본동작이 실행되지 않게 /custom-oauth2/login/kakao로 요청하고
Controller에서 원하는 동작을 작성해야 한다.
이 Controller에서 해야 할 일들이
OAuth2AuthorizationRequest객체 저장하기 + 클라이언트한테 URL전달하기이다.
※ Oauth2AuthorizationRequest객체는 ID,pw 입력한 클라이언트,
인가코드로 로그인요청하는 클라이언트 등을 백엔드에서 확인하는 객체이다.
(A는 ID,pw를 입력했고, 카카오로부터 인가코드를 얻었는데 , B가 A의 인가코드를 얻어서 로그인신청하는상황 등)
클라이언트가 카카오서버 로그인페이지 요청

서버로부터 받은 authorizationURL로 카카오서버에 로그인페이지를 요청한다.
이 부분은 클라이언트가 알아서 하면 된다.
클라이언트가 ID,PW입력 후 카카오서버로부터 인가코드 받기

클라이언트가 redirect -uri로 백엔드서버에 요청

이 때 클라이언트는 인가코드, state등을 포함해서 요청해야 한다.
이 state 값이 처음의 저장한 Oauth2AuthorizationRequest를 식별하는데 쓰임
이제 본격적인 백엔드과정에서 로그인과정이 진행된다
백엔드서버에서 카카오 Oauth2 로그인과정

그림과 같이 Oauth2AuthorizationRequest를 검사 (같은 클라이언트인지 검사)를 했다면
인가코드로 토큰요청 -> access token 획득 ->UserRequest요청 -> 유저정보 획득
-> CustomOauth2UserDetailsService 실행 및 로그인정보객체 return 까지.
웹 session방식의 Oauth2로그인방식과 차이가 없다.
결국 카카오서버로부터 유저정보 얻어서 우리서버DB에 저장을 하게 될 뿐이다.

이후 successHandler에 의해 로그인성공에 관한 jwt발급을 해주면 된다.
로그인성공 후 access token을 이용한 로그인

로그인 성공 이후라면 어차피 카카오로 로그인한 유저정보가 우리서버DB에 저장되어있다.
그래서 이후에는 https://brilliantdevelop.tistory.com/226 와 같이 똑같이
access token, refresh토큰을 보내면 된다.