카카오 로그인 CORS 오류

문의 시, 사용하시는 개발환경과 디벨로퍼스 앱ID를 알려주세요.


Window
back
spring boot 3.2.2
spring security 기본 3.2.2
ID 1034475
front
next.js 14버전

  http
                .cors(corsCustomizer -> corsCustomizer.configurationSource(new CorsConfigurationSource() {

                    @Override
                    public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {

                        CorsConfiguration configuration = new CorsConfiguration();

                        configuration.setAllowedOrigins(Collections.singletonList("https://localhost:3000"));
                        configuration.setAllowedMethods(Collections.singletonList("*"));
                        configuration.setAllowCredentials(true);
                        configuration.setAllowedHeaders(Collections.singletonList("*"));
                        configuration.setMaxAge(3600L);

                        return configuration;
                    }
                }));
        http
                .csrf(AbstractHttpConfigurer::disable)
                .formLogin(AbstractHttpConfigurer::disable)
                .httpBasic(AbstractHttpConfigurer::disable)
                .authorizeHttpRequests((authorizeRequests) -> authorizeRequests
                        .requestMatchers(new MvcRequestMatcher(introspector, "/")).permitAll()
                        .requestMatchers(new MvcRequestMatcher(introspector, "/api/**")).hasRole("MEMBER")
                        .anyRequest().authenticated()
                )
                .oauth2Login(oauth2Login ->
                        oauth2Login
                                .userInfoEndpoint(userInfoEndpointConfig ->
                                        userInfoEndpointConfig.userService(customOAuth2UserService))
                                .successHandler((request, response, authentication) -> {
                                    // 로그인 성공 후 리다이렉션할 URL 지정
                                    response.sendRedirect("http://localhost:8081");
                                }))
@Configuration
public class CorsMvcConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry corsRegistry) {

        corsRegistry.addMapping("/**")
                .allowedOrigins("http://localhost:3000");
    }
}

서버 단 Security CORS 설정 입니다.

const fetchData = async () => {
  console.log(1);
  try {
    const response = await fetch('http://localhost:8081/api/pin');
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    const data = await response.json();
    console.log(data); // 서버에서 받은 데이터 출력
  } catch (error) {
    console.error('Error fetching data:', error);
  }
};

프론트에서 보내는 요청입니다.

저희가 발생하는 오류는 다음과 같습니다.
localhost/:1 Access to XMLHttpRequest at ‘카카오계정’ (redirected from ‘http://localhost:8081/api/pin’) from origin ‘http://localhost:3000/’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.


사진도 함께 업로드 하겠습니다!
서버의 CORS 서버의 설정에서는 문제가 없어 보이는데 저희가 어떤걸 놓치고 있는걸까요 ㅠㅠ

카카오 로그인 인가코드 요청한 프론트 코드블럭 공유 부탁드려요.

죄송합니다 주제가 약간 어긋난 것 같습니다. 일단 부탁하신 정보에 대한건, 프론트에서 인가코드를 요청하지 않고 바로 http://localhost:8081/login/oauth2/code/kakao 이 url로 get요청을 보냅니다.
그리고 이럴 경우에 서버에서도 db에 카카오에 신청한 유저 정보가 잘 저장되는 것을 확인 할 수 있었습니다.

문제는 이후에 success handler를 이용해서 localhost:3000/ 으로 리다이렉트를 하고 서버에 get요청을 했을 때에 해당하는 데이터 정보를 CORS에 의해 차단당해서 오류가 발생합니다. CORS 설정은 다 잘 되어 있는 것 같은데 계속 같은 오류가 발생합니다 ㅠㅠ 세션 정보도 쿠키안에서 확인할 수 있었습니다.

프론트의 로그인 버튼을 클릭했을 때 서버에서 실행되는 쿼리

백엔드에서 유저를 저장하는 service

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

    private final UserRepository userRepository;
    private final HttpSession httpSession;

    /**
     * loadUser 메서드에서는 DefaultOAuth2UserService를 사용하여 OAuth2UserRequest에 대한 OAuth2User 객체를 로드합니다.
     * 그러면 로그인하는 사용자의 공급자 등록 ID 및 사용자 이름 속성 이름과 같은 사용자 정보를 가져와서 OAuthAttributes 객체로 변환합니다.
     */
    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {

        OAuth2UserService<OAuth2UserRequest, OAuth2User> delegate = new DefaultOAuth2UserService();
        OAuth2User oAuth2User = delegate.loadUser(userRequest);

        String registrationId = userRequest.getClientRegistration().getRegistrationId();
        String userNameAttributeName = userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName();

        OAuthAttributes attributes = OAuthAttributes.of(registrationId, userNameAttributeName, oAuth2User.getAttributes());

        User user = saveOrUpdate(attributes);
        httpSession.setAttribute("user", user);

        return new DefaultOAuth2User(
                Collections.singleton(new SimpleGrantedAuthority("ROLE_MEMBER")),
                attributes.getAttributes(),
                attributes.getNameAttributeKey()
        );
    }

    /**
     *  UserRepository 를 사용하여 OAuthAttributes 에서 가져온
     *  사용자 정보를 데이터베이스에 저장하거나 업데이트합니다.
     */
    private User saveOrUpdate(OAuthAttributes attributes) {
        User user = userRepository.findBySocialId(attributes.getSocialId())
                .map(entity -> entity.update(attributes.getNickname(),attributes.getImage(), Role.ROLE_MEMBER))
                .orElse(attributes.toEntity());

        return userRepository.save(user);
    }
}

social login은 잘 동작을 하는 것 같은데 그 이후에 프론트에서 서버에 api를 요청을 할 때 오류가 발생합니다. 오류는 처음에 올렸던 것에서 확인하실 수 있습니다!

추가적인 오류 메세지를 첨부합니다


네트워크 헤더에 해당하는 내용도 첨부하겠습니다.
image

CORS 에러는 브라우저에서 차단하는 것입니다.

즉, 클라이언트 측 브라우저에서 Ajax라 부르는 브라우저의 XMLHttpRequest 비동기 통신으로 허가되지 않은 다른 도메인을 호출했을때 브라우저가 차단 합니다.

CORS(Cross-Origin Resource Sharing) 에러에 관해

첨부해주신 에러 로그를 보면 localhost:3000의 요청을 통해 카카오 로그인 후 localhost:8081 에서 차단된 것으로 개발하신 시스템 설정문제입니다.

localhost:3000에서 어떤 처리하는지 코드블럭 공유해주시면 추가로 확인해보겠습니다.

댓글 알림이 안 와서 이제 봤습니다 ㅠ
공유 요청 주신 localhost:3000 에 대한 비동기 요청 코드 블럭입니다

const fetchData = async () => {
    console.log(1)
    try {
      const response = await axios.get('http://localhost:8081/api/pin')
      console.log(response.data) // 서버에서 받은 데이터 출력
    } catch (error) {
      console.error('Error fetching data:', error)
    }
  }
  useEffect(() => {
    fetchData()
  }, [])

페이지가 나오면서 localhost:8081/api/pin 으로 get요청을 보냅니다.
이때 pin 요청 이후에 authentication → login으로 이어집니다.


로그인을 한 이후에도 똑같이 동작 하는 걸 볼 수 있었습니다.

<div onClick={fetchData}>on</div>
<a href="http://localhost:8081/oauth2/code/kakao">로그인로그인로그인</a>

테스트 중 새로고침이 불편해 비동기 호출을 버튼으로 만들었고 로그인 a태그는 이렇게 되어 있습니다.

세션 정보는 쿠키에 저장되어 있습니다.

그래서 인증은 되는 것 같은데

login?continue=https… 여기로 요청을 보내는 이유가 뭔지를 모르겠습니다.ㅠㅠ

맨 처음 글 작성 한 것에 보시면 CORS orgin 설정에 localhost:3000으로 되어있습니다. 이 설정이 문제일까요…?

authorize 하면 카카오 계정 로그인 안되어 있을때 login 페이지 로 이동하는 것은 정상동작입니다.
그리고 a href로 인가코드요청하면 cors 발생하지 않습니다.
localhost:8081/oauth2/code/kakao 로 href 이동 후, 백엔드에서 302리다이렉트로 login 페이지로 이동해도 정상작동해야합니다.


“테스트 중 새로고침이 불편해 비동기 호출을 버튼으로 만들었고”

localhost:8081/api/pin 응답 받은 후, 이 기능과 별개로
<a href=“http://localhost:8081/oauth2/code/kakao” 링크 클릭해서 진행하는게 아닌가요?

프론트에서 어떻게 처리하는지 더 설명해주시겠어요?
(설명하신것과 다르게 인가코드 요청을 302 리다이렉트가 아닌 비동기 통신으로 요청하시는 것 같네요. )

아래와 같이 처리 되야 정상 동작입니다.

(1) ‘http://localhost:3000/’ 에서 a href 로 http://localhost:8081/oauth2/code/kakao 에 302 리다이렉트
(2) http://localhost:8081/oauth2/code/kakao 에서 302 리다이렉트로 인가코드요청
(3) 인가코드요청 URL에서 302 리다이렉트로 카카오 계정 로그인 페이지 이동