현재 Flow

  1. 카카오로 시작하기 버튼 클릭 ( 백엔드서버:8080/oauth2/authorization/kakao )
  2. spring security oauth2 내부에서 인가코드를 통해 -> 닉네임, 이메일 받아오기
  3. 이메일로 회원조회해서 없으면 회원가입 후 로그인 / 있으면 로그인하여 oauth2User 생성
  4. 로그인 성공 후 ( 프론트엔드서버:3000/oauthkakao ) 로 redirect
  5. 프론트서버에서 다시 jwt token을 받기 위해 요청을 보냄 ( 백엔드서버:8080/api/users/login )
  6. body에 token 넣어서 반환
  7. 프론트에서 token을 localstorage에 저장해 요청시 header에 token을 넣어서 처리

문제

@Configuration
@RequiredArgsConstructor
@EnableWebSecurity
public class SecurityConfig{

    private final CorsFilter corsFilter;
    private final CustumOauth2UserService custumOauth2UserService;
    private final AuthenticationSuccessHandler authenticationSuccessHandler;
    private final JwtAuthenticationFilter jwtAuthenticationFilter;
    private final AuthenticationFailHandler authenticationFailHandler;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .addFilter(corsFilter)
            .csrf(CsrfConfigurer::disable)
            .**sessionManagement(configurer -> configurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS))**
            .httpBasic(HttpBasicConfigurer::disable)
            .formLogin(AbstractHttpConfigurer::disable)
            .authorizeHttpRequests(authorize -> authorize
                .requestMatchers("/api/manager/**").hasAnyRole("MANAGER")
                .anyRequest().permitAll()
            ).oauth2Login(oauth2 -> oauth2
                .userInfoEndpoint(userInfo -> userInfo.userService(custumOauth2UserService))
                .successHandler(authenticationSuccessHandler)
                .failureHandler(authenticationFailHandler)
            ).addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }
}

Jwt Token을 사용하기 때문에 Security Config에서 Session을 stateless 로 설정

현재 Flow에서 5번의 jwt token의 요청을 받을 때,

@PostMapping("/login/kakao")
    public Response loginCheck(@AuthenticationPrincipal OAuth2User oAuth2User){
        if (oAuth2User == null) return Response.error("404", ErrorCode.USER_NOT_FOUND.getMessage());

        String email = oAuth2User.getAttribute("email");

        return Response.success(Result.toResponseDto(usersService.loginCheck(email)));
    }

@AuthentiPrincipal 어노테이션을 사용해 저장된 로그인 객체를 가져오려했지만, 로그인 된 상태가 없기 때문에 oAuth2User 객체가 null이라 에러가 발생하게 된다.

이를 해결하기 위해서는 oAuth2Login이 성공했을 때 successHandler를 통해 authenticationSuccessHandler를 호출하는데,

이 때 JwtToken을 응답해야한다.

하지만 프론트 서버로 redirect를 해야하기 때문에 body에 jwt accesstoken을 넣어서 전달할 수 없는 문제가 발생