java.lang.ClassCastException: class java.lang.String cannot be cast to class com.linked.classbridge.dto.user.CustomOAuth2User (java.lang.String is in module java.base of loader 'bootstrap'; com.linked.classbridge.dto.user.CustomOAuth2User is in unnamed module of loader 'app')
Authentication 객체의 getPrincipal() 메소드가 CustomOAuth2User 객체 대신 문자열을 반환하기 때문에 발생. 일반적으로 Authentication 객체가 아직 완전히 인증되지 않았거나, 인증 과정에서 문제가 발생했을 때 발생.
회원가입(/signup)요청 시 필요한 UserDTO를 반환해주는 loadUser 메소드는 Spring Security의 인증 과정 중에 호출되며, 그 결과는 Authentication 객체의 Principal로 설정됨. 따라서 사용자가 아직 등록되지 않은 상태인 추가 정보 입력 단계에서는 Authentication 객체에서 UserDTO를 받을 수 없음.
세션에 UserDTO 넣어두고 controller에서 호출하도록 코드 변경
@PostMapping("/auth/signup")
public ResponseEntity<SuccessResponse<?>> signup(@RequestBody AuthDTO.SignUp signupRequest) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null && authentication.getPrincipal() instanceof CustomOAuth2User) {
CustomOAuth2User user = (CustomOAuth2User) authentication.getPrincipal();
UserDTO userDTO = user.getUser();
signupRequest.setUserDTO(userDTO);
}
userService.addUser(signupRequest);
return ResponseEntity.status(CREATED).body(
SuccessResponse.of("user created successfully")
);
}
@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
String registrationId = userRequest.getClientRegistration().getRegistrationId();
String accessToken = userRequest.getAccessToken().getTokenValue();
if (registrationId.equals("google")) {
// Google API 호출
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setBearerAuth(accessToken);
HttpEntity<String> entity = new HttpEntity<>(headers);
ResponseEntity<GoogleResponse> response = restTemplate.exchange(
"<https://www.googleapis.com/oauth2/v1/userinfo>",
HttpMethod.GET,
entity,
GoogleResponse.class
);
GoogleResponse googleResponse = response.getBody();
Optional<User> existingUserOptional = userRepository.findByEmail(googleResponse.getEmail());
if (existingUserOptional.isPresent()) {
User existingUser = existingUserOptional.get();
if (existingUser.getAuthType() != AuthType.GOOGLE) {
throw new RestApiException(ALREADY_REGISTERED_OTHER_AUTH_TYPE);
} else {
UserDTO userDTO = new UserDTO();
userDTO.setProvider(existingUser.getProvider());
userDTO.setProviderId(existingUser.getProviderId());
userDTO.setEmail(existingUser.getEmail());
userDTO.setUsername(existingUser.getUsername());
userDTO.setAuthType(existingUser.getAuthType());
// List<UserRole> 에서 List<String> 로 변환, "ROLE_" prefix 제거
List<String> roles = existingUser.getRoles().stream()
.map(role -> role.name().substring(5))
.collect(Collectors.toList());
userDTO.setRoles(roles);
return new CustomOAuth2User(userDTO); // // Spring Security의 인증 객체(Authentication)에 저장
}
} else {
UserDTO userDTO = new UserDTO();
userDTO.setProvider(googleResponse.getProvider());
userDTO.setProviderId(googleResponse.getProviderId());
userDTO.setEmail(googleResponse.getEmail());
userDTO.setUsername(googleResponse.getName());
userDTO.setAuthType(AuthType.GOOGLE);
userDTO.setRoles(Collections.singletonList("USER"));
return new CustomOAuth2User(userDTO);
}
} else {
throw new RestApiException(NOT_SUPPORTED_AUTH_TYPE);
}
}