[TroubleShooting] CSR OAuth2 Login

이프·2025년 2월 6일

trouble-shooting

목록 보기
4/8

문제 발생

새로 시작한 COCOMU 프로젝트에서 문제가 발생했다.

  • CSR 방식으로 Oauth2 Login
  • GitHub Oauth2 Login

발생한 문제 (1)

이번 프로젝트에서 OAuth로만 회원가입 및 로그인을 진행하는데 email 주소로 중복 검증을 하기로 했다. 하지만 GitHub OAuth2 로그인 페이지에서 계속 리다이렉션 초과 예외만 발생했다.

원인이 뭘까?

@Service
@Transactional
@RequiredArgsConstructor
@Slf4j
public class CustomOauth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {

    private final UserAuthRepository userAuthRepository;

    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
        OAuth2User oAuth2User = new DefaultOAuth2UserService().loadUser(userRequest);
        String registrationId = userRequest.getClientRegistration().getRegistrationId();

        CustomOAuth2User customOauth2User = OAuth2Factory.create(registrationId, oAuth2User.getAttributes());
        validateSignup(customOauth2User.getName());
        signUpUser(customOauth2User);

        return customOauth2User;
    }

    private void signUpUser(CustomOAuth2User customOauth2User) {
        User user = User.createUser(customOauth2User.getNickname());
        UserAuth userAuth = UserAuth.signUp(customOauth2User.getName(), user, customOauth2User.getProvider());
        userAuthRepository.save(userAuth);
    }

    private void validateSignup(String id) {
        userAuthRepository.findById(id).ifPresent(userAuth -> {
            String provider = userAuth.getOAuth2Provider().name();
            throw new OAuth2AuthenticationException(new OAuth2Error("duplicate_user"), "이미 가입된 사용자입니다 (" + provider + ")");
        });
    }

}

코드를 보면, email로 검증을 하고 있는데 github OAuth에서는 github 계정 주인이 email 제공을 허용해야한다.

debug point를 찍어서 확인한 결과 email=null 인 것을 확인했다.
Ah.. 이 부분 때문에, signUp 메서드에서 예외가 발생하고 따로 예외 처리가 없었기 때문에 OAuth2 인증이 계속 발생하면서 무한루프가 발생한 것 이었다.

하는 수 없이 정책을 바꿨다.

다른 OAuth도 추가 할 예정이기 때문에 각 OAuth에서 제공하는 provider와 사용자 Id로 처리하기로 계정 검증을 하도록 수정했다.


문제발생 (2)

Login을 하기 위해 먼저 2가지 flow로 확인하려고 했다.
1. OAuth 로그인 -> REST API로 "token"을 반환
2. Token 프로세싱

하지만, Spring Boot의 OAuth2 자동 구성 기능을 최대한 활용하려다가 문제를 만났다. OAuth2 자동 구성 기능은 기본적으로 callback url로 리다이렉션 하기 때문에 front 측 url로 리다이렉션 해줘야한다.

근데 막 생각해보니 너무 찝찝한 부분이 있어서 아래와 같은 내용으로 고수들에게 물어봤다. (카카오톡 오픈채팅방)

이해한 내용

인터넷 검색을 해보니 oauth로 로그인 및 회원가입이 정상적으로 성공하면 security filter chain에서 oauth2Login 메서드의 successHandler로 front 측으로 리다이렉션 해주는 방식이 대부분이더라구요.

예상되는 문제

만약 백엔드는 개발 환경으로 ec2에 배포 중이고, front는 로컬 개발 환경에서 ec2 api를 통해 정상동작하는지 테스트 해보는 상황이 발생할 것으로 예상됩니다.
그런데 배포중인 스프링 부트는 successHandler에서 localhost:3000으로 redirect하도록 작성되어있다면 react가 같은 ec2 인스턴스에서 배포되고 있지 않은 이상 결과를 확인할 수 없을 것 같다는 생각이 들었습니다.

궁금한 내용

제가 생각한 내용이 맞는지 궁금합니다.
맞다면, 다른 해결 방안이 있을까요..? front로 Redirect하는게 아니라 그냥 rest api로는 처리할 수 없는지 궁금합니다.
틀렸다면, 어느 포인트를 놓쳤는지 궁금합니다.

답변의 결과는 REST API로 처리 할 수 있고 Spring OAuth의 자동구성을 사용하면 안되는 것이다. 이게 Client Side OAuth를 구현하는 방법이다.


소감

Spring OAuth 아키텍쳐도 모두 이해하지 못하고 편하게 하려다가 봉변 맞았다.

profile
if (이런 시나리오는 어떨까?) then(테스트로 검증하고 해결) else(다음 시나리오 고민)

0개의 댓글