스프링에서 리다이렉트했는데 자꾸 로그인 페이지로 넘어갈 때
문제
OAuth2SuccessHandler에서 프론트에 토큰 값을 전달하기 위해 redirect를 설정했더니 다시 로그인 페이지로 리다이렉트되는 현상
해결
현재 OAuth2SuccessHandler 설정
@RequiredArgsConstructor
@Component
public class OAuth2SuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
private final JwtProvider jwtProvider;
@Override
public void onAuthenticationSuccess(
HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws IOException {
super.clearAuthenticationAttributes(request);
CustomOAuth2User auth2User = (CustomOAuth2User) authentication.getPrincipal();
Long userId = auth2User.getUserId();
String role = auth2User.getRole();
String generatedToken = jwtProvider.generateToken(userId, role, ACCESS_TOKEN_DURATION);
response.setHeader(HEADER_AUTHORIZATION, generatedToken);
response.sendRedirect("/login/success");
}
}
프론트에서는 응답에 포함된 토큰값을 쿠키에 저장하여 인증을 유지한다.
때문에 인증에 성공하면 정해진 경로로 우회한다.
그리고 문제의 현상인 로그인페이지로 넘어가게 되는데,
이 현상에는 감춰져 있는 요청 처리가 있다.
먼저, 웹서버 없이 로컬에서 구현하기 때문에 위 엔드포인트를 처리할 수 있는 컨트롤러가 정의되어 있지 않다.
따라서 스프링은 자연스레 /error 페이지로 우회시킨다.
문제는 이 /error 경로를 spring security에서 authenticated로 보호되고 있기 때문에 사용자가 인증되었는지 확인하고
안되어있다면 다시 로그인 페이지로 넘어가는 것이다.
그렇다면 해결방안은 /error를 인증없이 접근할 수 있도록 하는 것이다.
물론, 웹서버를 실행시켜 엔드포인트 LB를 진행해도 되지만 구현할 때마다 키는 것은 불편하므로 이렇게 해결하는 편이 좋겠다 생각했다.
@RequiredArgsConstructor
@Configuration
@EnableWebSecurity
public class OAuth2LoginConfig {
private final CustomOAuth2UserService oAuth2UserService;
private final OAuth2SuccessHandler oAuth2SuccessHandler;
private final JwtAuthenticationFilter jwtAuthenticationFilter;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.oauth2Login(oauth2Login ->
oauth2Login
.successHandler(oAuth2SuccessHandler)
.userInfoEndpoint(userInfoEndpointConfig ->
userInfoEndpointConfig.userService(oAuth2UserService)));
http.sessionManagement((sessionManagement) ->
sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
http.addFilterAfter(jwtAuthenticationFilter, OAuth2LoginAuthenticationFilter.class);
// 로컬 환경에서는 서버 사이드로 구현하기 때문에 일부 엔드포인트 개방
http.authorizeHttpRequests(a ->
a.requestMatchers("/login/success").permitAll());
http.authorizeHttpRequests(a ->
a.requestMatchers("/error").permitAll()
.requestMatchers("/api/login").permitAll()
.requestMatchers("/login/success").permitAll()
.anyRequest().authenticated());
return http.build();
}
}
'프로젝트' 카테고리의 다른 글
[소마] 리팩토링: 로직 개선하기 (0) | 2024.03.14 |
---|---|
[소마] OAuth2.0 인증 성공 후, AuthenticationSuccessHandler 테스트해보자 (0) | 2024.02.19 |
[소마] JWT 검증하기 전에 parsing 해보자 (0) | 2024.01.26 |
[소마] jwt 인증 프로세스에서 공통 로직을 분리하자 (0) | 2024.01.26 |
[소마] 로그인 페이지 서버사이드 mvc 구현에서 endpoint 호출로 수정 (0) | 2024.01.17 |