안녕하세요 현재 REST API로 카카오톡 로그인을 구현하고 있습니다.
Spring Security와 OAuth2-Client를 통해 Spring 환경에서 인가 코드를 받아 서버에 회원 정보를 저장하고, JWT를 발급하여localhost:3000/login/oauth2/success
로 리다이렉트 시켜주는 로직을 구현하고 배포하였습니다.
로컬 서버 환경과(localhost:8080)과 브라우저 환경에서 로그인 테스트를 했을 때는 잘 작동하는데,
로컬 리액트 환경에서 {배포 주소}/oauth2/authorization/kakao
로 요청 후 카카오톡 로그인 진행하면
자꾸 {배포 주소}/oauth2/code/kakao/
에서 넘어가지 않고에러가 발생합니다…
Spring Security 설정에 문제가 있는 걸까요?
브라우저에서는 잘 되지만 로컬 리액트에서는 에러가 나는 이유가 궁금합니다 ㅠ
앱 ID 933037
이건 리액트 에러 캡쳐 사진입니다
package com.dansup.server.config.security;
import com.dansup.server.config.jwt.JwtAuthenticationFilter;
import com.dansup.server.config.oauth.CustomOAuth2UserService;
import com.dansup.server.config.oauth.OAuth2AuthenticationFailureHandler;
import com.dansup.server.config.oauth.OAuth2AuthenticationSuccessHandler;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import java.util.List;
@Configuration
@RequiredArgsConstructor
@EnableWebSecurity
public class SecurityConfig {
private final JwtAuthenticationFilter jwtAuthenticationFilter;
private final OAuth2AuthenticationSuccessHandler oAuth2AuthenticationSuccessHandler;
private final OAuth2AuthenticationFailureHandler oAuth2AuthenticationFailureHandler;
private final CustomOAuth2UserService customOAuth2UserService;
private static final String[] swagger = {
"/v2/api-docs",
"/swagger-resources/**",
"/swagger-ui.html",
"/swagger/**",
"/webjars/**"
};
@Bean
public SecurityFilterChain configure(HttpSecurity httpSecurity) throws Exception {
return httpSecurity
.cors().configurationSource(corsConfigurationSource())
.and()
.formLogin().disable()
.httpBasic().disable()
.csrf().disable()
.headers().frameOptions().disable()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers(swagger).permitAll()
.antMatchers(HttpMethod.GET, "/danceclasses/**").permitAll()
.antMatchers(HttpMethod.GET,"/profile/**").permitAll()
.antMatchers("/login/**").permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling()
.accessDeniedHandler(new CustomAccessDeniedHandler())
.authenticationEntryPoint(new CustomAuthenticationEntryPoint())
.and()
.oauth2Login()
.successHandler(oAuth2AuthenticationSuccessHandler)
.failureHandler(oAuth2AuthenticationFailureHandler)
.userInfoEndpoint()
.userService(customOAuth2UserService)
.and()
.and()
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
.build();
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
config.setAllowCredentials(true);
config.addAllowedOriginPattern("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.setExposedHeaders(List.of("*"));
source.registerCorsConfiguration("/**", config);
return source;
}
}
package com.dansup.server.config.oauth;
import com.dansup.server.api.user.domain.User;
import com.dansup.server.api.user.domain.UserRole;
import com.dansup.server.api.user.repository.UserRepository;
import com.dansup.server.common.exception.BaseException;
import com.dansup.server.common.response.ResponseCode;
import com.dansup.server.config.security.CustomUserDetails;
import com.dansup.server.config.jwt.JwtTokenProvider;
import com.dansup.server.config.jwt.dto.JwtTokenDto;
import com.dansup.server.config.jwt.refresh.RefreshTokenService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import org.springframework.web.util.UriComponentsBuilder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
@Slf4j
@RequiredArgsConstructor
public class OAuth2AuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
private final JwtTokenProvider tokenProvider;
private final RefreshTokenService refreshTokenService;
private final UserRepository userRepository;
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException {
CustomUserDetails oAuth2User = (CustomUserDetails) authentication.getPrincipal();
String targetUrl = null;
JwtTokenDto jwtTokenDto = tokenProvider.createJwtToken(oAuth2User.getName());
refreshTokenService.saveRefreshToken(jwtTokenDto.getRefreshToken(), oAuth2User.getName());
targetUrl = UriComponentsBuilder
.fromUriString(setSuccessRedirectUrl(request.getServerName(), request.getServerPort()))
.queryParam("accessToken", jwtTokenDto.getAccessToken())
.queryParam("refreshToken", jwtTokenDto.getRefreshToken())
.queryParam("isGuest", isGuest(oAuth2User.getName()))
.build()
.toUriString();
log.info("[targetUrl]: {}", targetUrl);
getRedirectStrategy().sendRedirect(request, response, targetUrl);
}
private String setSuccessRedirectUrl(String requestUrl, int requestPort) {
String redirectUrl = null;
log.info("[Request URL]: {}, {}", requestUrl, requestPort);
if(requestUrl.equals("localhost") && requestPort == 8080) {
redirectUrl = "http://localhost:8080/login/oauth2/success";
}
if(requestUrl.equals("localhost") && requestPort == 3000) {
redirectUrl = "http://localhost:3000/login/oauth2/success";
}
if (requestUrl.equals("takgyun.shop")) {
redirectUrl = "http://localhost:3000/login/oauth2/success";
}
return redirectUrl;
}
private boolean isGuest(String email) {
User user = userRepository.findByEmail(email).orElseThrow(
() -> new BaseException(ResponseCode.USER_NOT_FOUND)
);
return user.getUserRole().equals(UserRole.ROLE_GUEST);
}
}