krkarma777 / online-store

SEED: An open-market platform built with JDK 17, Spring Boot, and Oracle DB, focusing on RESTful architecture and secure user experiences.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

OAuth2 Login Issue: Mismatch Between Database username and principal.getName()

krkarma777 opened this issue · comments

Issue Description
During the integration of Naver OAuth2 for login functionality, we encountered an issue where the username stored in the database does not match the username retrieved from principal.getName() after a successful authentication. This inconsistency is causing problems in user identification and authentication flow within our application.

Expected Behavior
After a successful OAuth2 login, the principal.getName() method should return a username that matches the one stored in our database for the authenticated user. This ensures a consistent user experience and allows for seamless integration of OAuth2 authenticated users with our application's existing user management system.

Current Behavior
Currently, after a successful login via Naver OAuth2, the principal.getName() returns a value that does not match the username stored in our database for the corresponding user. This discrepancy leads to authentication errors and affects the overall user experience.

Steps to Reproduce
Implement Naver OAuth2 login as per the standard integration process.
Perform a login using Naver OAuth2.
After successful authentication, attempt to retrieve the username using principal.getName().
Observe that the retrieved username does not match the one stored in the database for the authenticated user.
Possible Solutions
Investigate the mapping of OAuth2 user attributes to ensure the correct attribute is being used as the username.
Review the configuration of the OAuth2 client to confirm if additional settings are required for Naver OAuth2 integration.
Explore customizing the OAuth2UserService to manually map the correct user attribute to the username.
Additional Context
OAuth2 Configuration: [Briefly describe your OAuth2 configuration, focusing on any customizations or specific settings applied for Naver OAuth2.]
Authentication Flow: [Provide a high-level overview of your authentication flow to help with understanding the context.]
We are seeking solutions or suggestions to resolve this mismatch and ensure that the username retrieved through principal.getName() correctly matches the one stored in our database for OAuth2 authenticated users.

image

 public User getCurrentUser(Principal principal) {
        log.info("principle= [{}]", principal);
        log.info("principal.getName()= [{}]", principal.getName());

        return userService.findByUsername(principal.getName())
                .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "사용자를 찾을 수 없습니다."));
    }
@Service
@RequiredArgsConstructor
public class CustomOAuth2UserService extends DefaultOAuth2UserService {

    private final KakaoLoginService kakaoLoginService;
    private final NaverLoginService naverLoginService;

    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {

        OAuth2User user = super.loadUser(userRequest);
        Map<String, Object> attributes = user.getAttributes();

        /* 네이버 로그인 로직 */
        if (attributes.get("message")!=null) {
            String token = naverLoginService.login(attributes);
            return new NaverOAuth2User(user, token);
        }
        /* 카카오 로그인 로직 */
        if (attributes.get("kakao_account") != null) {
            String token = kakaoLoginService.login(attributes);
            return new KakaoOAuth2User(user, token);
        }

        return null;
    }
@Service
@RequiredArgsConstructor
public class NaverLoginService implements SocialOauth2Service{

    private final UserRepository userRepository;
    private final JWTUtil jwtUtil;

    @Value("${jwt.expiredMs}") private String expiredMs;

    @Override
    public String login(Map<String, Object> attributes) {

        // 메시지 상태 확인 후, 성공적으로 정보를 가져왔는지 검증
        if (!"success".equals(attributes.get("message").toString())) {
            throw new OAuth2AuthenticationException("OAuth2 공급자로부터 사용자 정보를 성공적으로 가져오지 못했습니다.");
        }
        // attributes에서 response를 추출하여 사용자 정보 설정
        Map<String, Object> response = (Map<String, Object>) attributes.get("response");

        String email = response.get("email").toString();
        Optional<User> userOpt = userRepository.findByUsername(email);
        String role = "자영업자";
        User userEntity = new User();
        if (userOpt.isEmpty()) {
            userEntity.setUsername(email); // 사용자 고유 이메일을 username으로 사용
            userEntity.setEmail(response.get("email").toString());
            userEntity.setPhoneNumber(response.get("mobile").toString());
            userEntity.setRealName(response.get("name").toString());
            userEntity.setRole(UserRole.ROLE_자영업자); // 모든 사용자를 자영업자로 설정
            userEntity.setPassword(UUID.randomUUID().toString());
            userRepository.save(userEntity);
        } else {
            String gettedRole = userOpt.get().getRole().toString();
            UserRole userRole = UserRole.fromRoleString(gettedRole);
            role = userRole.getDescription();
        }
        return jwtUtil.createJwt(response.get("id").toString(), role, Long.parseLong(expiredMs));
    }
}

This issue has been successfully resolved with the implementation of the user ID as the username for Naver OAuth2 authentication. This approach has addressed the mismatch between the database username and principal.getName(), ensuring consistent user identification throughout the application.
image