리액트와 스프링 부트 OAuth 2.0 with Google

HOSEON YOO·2024년 3월 9일
0

개요

  • Spring Boot v3.2.2

국비학원 최종 프로젝트는 리액트(프론트)와 스프링 부트(백엔드)로 구성하였는데, 프론트와 백엔드 둘 중에 어디에서 OAuth 2.0을 구현하면 되는지에 대한 고민에 빠지게 되었다. 그러던 중, 개발자 유미님의 채널을 알게 되었고 스프링 OAuth2 클라이언트 JWT 2 : 동작 원리와 프론트/백 책임 분배 영상을 통해 고민을 해결할 수 있었다. 결론적으로는 백엔드에서 OAuth 2.0의 모든 책임을 지는 걸로 결정하였다.

스프링 부트 OAuth 2.0 동작 방식

스프링 부트 OAuth2 Client 라이브러리는 로그인 페이지 요청, 인증 코드와 액세스 토큰 요청/응답이 내부적으로 구현되어있어서 개발자가 직접 구현해야 하는 부분은 사용자 정보 응답을 받아서 처리하는 로직만 구현하면 된다.

내부적으로 구현되어있다 보니 정해놓은 규칙이 있는데 개발자는 이를 따라야 한다.

프론트 로그인 요청 URL

window.location.href = "http://localhost:8080/oauth2/authorization/서비스명"

백엔드 로그인 성공 리디렉션 URI

http://localhost:8080/login/oauth2/code/서비스명

프로젝트 생성 및 의존성 추가

  1. Spring Initializr 에서 프로젝트 생성
  2. 의존성 추가
    1. Spring Web
    2. Spring Boot DevTools
    3. Lombok
    4. Spring Security
    5. OAuth2 Client

Google Cloud Platform과 스프링 부트 설정

스프링 OAuth2 클라이언트 7 : 구글 소셜 로그인 신청 개발자 유미님의 영상을 참고하면 된다.

  1. OAuth 동의 화면과 사용자 인증 정보 설정
  2. application.properties 설정

사용자 정보 응답받는 로직

필자는 구글 로그인만 사용하기 때문에 클래스 이름 앞에 Google을 붙여서 작성했다. 카카오나 네이버 로그인을 추가로 작성하는 경우에는 보편적으로 CustomOAuth2Service라고 작성한다.

스프링 부트가 액세스 토큰으로 사용자 정보를 응답받는 로직이다. 사용자 정보는 OAuth2User에 담겨 있다.

@Service
public class GoogleOAuth2UserService extends DefaultOAuth2UserService {
    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
        OAuth2User oAuth2User = super.loadUser(userRequest);

        // TODO : 개발자 구현 로직
        System.out.println(oAuth2User);
        
        return oAuth2User;
    }
}

구글 로그인 성공 후 로직

위의 사용자 정보 응답받는 로직 이후에 실행된다고 보면 된다. 로그인 성공 후 프론트로 이동하도록 설정했다.

@Component
public class GoogleOAuth2UserSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
        OAuth2User oAuth2User = (OAuth2User) authentication.getPrincipal();

        // TODO : 개발자 구현
        System.out.println(oAuth2User);

        response.sendRedirect("http://localhost:3000"); // frontend-base-url
    }
}

스프링 시큐리티 설정

최종 프로젝트가 프론트와 백엔드로 구성되어있어서 csrf, formLogin, httpBasic, session을 사용하지 않도록 설정한다.

@RequiredArgsConstructor
@Configuration
@EnableWebSecurity
public class SecurityConfig {
    private final GoogleOAuth2UserService googleOAuth2UserService;
    private final GoogleOAuth2UserSuccessHandler googleOAuth2UserSuccessHandler;
    
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .csrf(CsrfConfigurer::disable);

        http
                .formLogin(FormLoginConfigurer::disable);

        http
                .httpBasic(HttpBasicConfigurer::disable);

        http
                .oauth2Login(oAuth2LoginConfigurer -> oAuth2LoginConfigurer
                        .loginPage("http://localhost:3000/login") // frontend-login-url
                        .userInfoEndpoint(userInfoEndpointConfig -> userInfoEndpointConfig
                                .userService(googleOAuth2UserService)
                        )
                        .successHandler(googleOAuth2UserSuccessHandler)
                );

        http
                .authorizeHttpRequests(authorizeHttpRequestsConfigurer -> authorizeHttpRequestsConfigurer
                        .anyRequest().authenticated()
                );
        http
                .sessionManagement(sessionManagementConfigurer -> sessionManagementConfigurer
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                );

        return http.build();
    }
}

참고자료

profile
안녕하세요~ 👋, 대한민국 개발자 유호선입니다.

0개의 댓글

관련 채용 정보