Backend/SpringBoot

OAuth 연동

Dean83 2026. 2. 6. 11:46

모바일일 경우에는 OAuth 연동을 모바일쪽에서 직접 구현 -> 해당 정보를 백앤드로 전달 해주었다. 웹페이지의 경우에도 그렇게 할 수 있으나 클라이언트 측에 키값이 존재한다는 점이 불안 요소가 있다. (물론 이를 보완할 수도 있다. 키값만 db에 저장한다든지, 서버가 전달 해준다든지 등등)

 

서버에서 OAuth를 연동할 경우 장점은,

  • 키값 안전하게 보호
  • 각기 다른 플랫폼에 OAuth 연동해도 연동이 일괄적으로 간편
    • 이부분은 클라이언트 쪽에선 진짜...하나 추가될 때 마다 괴로웠음
    • 스프링부트에서는 설정만 추가하고 필요하면 코드만 살짝 바꾸면 된다.

 

일단, 구글 기준으로 스프링부트에서 연동하는 내용을 정리해 둔다. 

 

우선순위 부터 보자면

  • 각 플랫폼의 dev 사이트에서 프로젝트 생성
  • 프로젝트에서 OAuth 연동을 위한 콜백 Uri 지정
  • builld.gradle 에 라이브러리 추가
  • 발급된 클라이언트ID, 비밀번호를 스프링부트의 환경변수에 삽입 및 application.yaml 설정
  • SecurityConfig 설정
  • 연동 Service 코드 구현
  • JWT 연동하여 토큰 발급 후 프론트엔드에 전달

 

각 플랫폼의 dev 혹은 console 사이트에서 프로젝트 생성

이 부분 설정법은 금방 쉽게 찾을 수 있기 때문에 설정을 해주어야 한다는 사실만 기억하면 되고 여기선 다루지 않는다. 

다만 아래 2가지는 기억하는게 좋다. 

  • 프로젝트에서 클라이언트 생성시, 웹 애플리케이션으로 생성할 것
  • 웹 애플리케이션에서 승인된 리디렉션 URI에 주소값을 넣을것
    • 구글 예 : 개발중일경우 : http://localhost:8080/login/oauth2/code/google
      • /login/oauth2/code/google 이게 항상 일치해야 한다.

 

Build.gradle 추가

  • Oauth2 를 위한 라이브러리가 있다.
  • 각 플랫폼에 요청을 위한 uri가 security에 고정되어 있다. 
    • 구글 : http://localhost:8080/oauth2/authorization/google
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'

 

application.yaml 수정

  • Spring Security의 oauth2 항목을 설정해주면 된다.
  • 다른 플랫폼과 연동시 단순히 registration, provider 쪽에 항목을 추가해주면 된다.
  • 구글의 경우 provider 부분은 필수는 아니고 선택사항이다. 그러나 kakao 같은 경운 필수로 넣어야 한다.
  • provider 에 있는 각 주소들은 해당 플랫폼에서 제공하는 주소이니, 값의 변화가 없다.
  • scope 하단에 서버가 가져올 정보를 명시한다. 각 제공처 마다 다르니 주의할것.
    • 구글의 경우 profile 을 추가 하면 이름을 가져 올 수 있다.
    • 이를 가져오기 위해선 구글 콘솔 -> OAuth 에서 해당 정보를 가져오겠다는 것을 설정을 통해 해 주어야 한다.
spring:
  security:
    oauth2:
      client:
        registration:
          google:
            client-id: ${GOOGLE_CLIENT_ID}
            client-secret: ${GOOGLE_SECRET}
            scope:
              - email
              - profile
        provider:
          google:
            authorization-uri: https://accounts.google.com/o/oauth2/v2/auth
            token-uri: https://oauth2.googleapis.com/token
            user-info-uri: https://www.googleapis.com/oauth2/v3/userinfo
            user-name-attribute: sub

 

OAuthService 구현

  • OAuth2UserService 를 implement 하여 구현한다.
  • 이메일이 없을경우 처리는 비즈니스 로직 부분이다. 
  • 필요하다면 profile 등 을 통해 이름을 가져올 수도 있다. (application.yaml 설정 및 각 서비스 도메인 설정 필요)
@Service
@RequiredArgsConstructor
public class OAuthService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {
    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
        OAuth2UserService<OAuth2UserRequest, OAuth2User> oAuth2UserService = new DefaultOAuth2UserService();
        OAuth2User oAuth2User = oAuth2UserService.loadUser(userRequest);
        Map<String,Object> attributes = oAuth2User.getAttributes();

        String email = (String) attributes.get("email");

        ....//비즈니스 로직 구현 부분

        return new DefaultOAuth2User(
                Set.of(new SimpleGrantedAuthority("ROLE_USER")),
                attributes,
                "sub"
        );
    }
}

 

 

SecurityConfig 설정 추가

  • oauth2Login 설정만 해주면 된다.
  • userService 에 위에 설정한 서비스를 넣어준다.
  • 따로 csrf 설정이나 authorizeHttpRequests.requestMatchers 설정을 하지 않아도, Spring Security에서 별도로 다른 filter를 태운다
  • 로그인 성공, 실패 콜백을 등록하여, 로그인 성공시 JWT 토큰 발급 등을 할 수 있도록 할 필요가 있다.
	....
    private final OAuthService oAuthService;
    private final OAuthSuccessHandler oAuthSuccessHandler;
    private final OAuthFailureHandler oAuthFailureHandler;
    ...

	@Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    
                http.oauth2Login(oauth -> oauth.userInfoEndpoint(
                        info -> info.userService(oAuthService)                                              
                        .successHandler(oAuthSuccessHandler)
                        .failureHandler(jwtLoginFailureHandler)
                ))

				....

 

로그인 성공, 실패 핸들러

  • 성공 핸들러 예만 첨부한다.
  • 요점은, 토큰 발급 후 프론트엔드 에서 원하는 주소로 re-direct 해주어야 한다는 점이다. (실패시 에도 마찬가지)
  • redirect 할 때 토큰을 바로 노출하는건 좋지 않고, 쿠키에 넣어 전달 -> 클라이언트가 쿠키에서 가져와 처리 하는게 좋다 (프론트와 협의 필요)
@Component
@RequiredArgsConstructor
public class OAuth2SuccessHandler
        implements AuthenticationSuccessHandler {

    private final JwtProvider jwtProvider;

    public void onAuthenticationSuccess(HttpServletRequest request, 
    HttpServletResponse response, 
    Authentication authentication) throws IOException, ServletException {

        String token = jwtProvider.createToken(authentication);

        response.sendRedirect(
            "http://frontend.com/login?token=" + token
        );
    }
}

 

접근 테스트 (구글)

  • http://localhost:8080/login/oauth2/code/google  주소를 통해 브라우저로 접속하여 테스트 한다. (개발환경)
  • 프론트엔드 페이지가 이미 구현완료 되었다면 프론트엔드를 통해 완료한다.