💻 뚝딱뚝딱/북북클럽

[개발일지 #012] Oauth 로그인 구현 (네이버)

뚜루리 2025. 4. 24. 14:57
728x90
320x100

🎯 오늘의 목표

  • Oauth 로그인 구현 (네이버)

 


⚙️ 진행한 작업

  • Oauth 로그인 구현 (네이버)

🛠️ 개발내용

📌  네이버 개발자 센터에서 앱 등록

  • 구글과 마찬가지로 네이버도 네이버 개발자 센터에 등록을 해야 한다.

애플리케이션 이름을 정하고 네이버 로그인의 어떤 항목의 권한을 얻을 것인지 선택해준다.

나는 연락처 이메일 주소랑 별명을 필수로 나중에 프로필 사진도 넣을 것 같아서 프로필 사진도 추가로 설정해주었음.

 

내용 들을 쭉쭉 입력하고 아래에 등록하기 버튼을 누르면 클라이언트 아이디와 비밀키가 발급완료됨.

 

 


📌  NaverOAuth2UserService 생성

  • GoogleOAuth2UserService와 거의 똑같이 만들되, 응답 형태가 response 내부에 있다는 것만 다름
@RequiredArgsConstructor
@Service
public class NaverOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {

    private final UserRepository userRepository;

    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
        OAuth2User delegate = new DefaultOAuth2UserService().loadUser(userRequest);
        Map<String, Object> response = (Map<String, Object>) delegate.getAttributes().get("response");

        String email = (String) response.get("email");
        String name = (String) response.get("name");
        String providerId = (String) response.get("id");
        AuthProvider provider = AuthProvider.NAVER;

        return userRepository.findByEmail(email)
                .map(CustomUserDetails::new)
                .orElseGet(() -> {
                    if (userRepository.existsByNickname(name)) {
                        throw new OAuth2AuthenticationException("이미 사용 중인 닉네임입니다.");
                    }

                    User newUser = userRepository.save(User.createSocialUser(email, name, provider, providerId));
                    return new CustomUserDetails(newUser);
                });
    }
}

 

 

📌  OAuth2UserProviderRouter에 네이버 서비스 연결

private final GoogleOAuth2UserService googleOAuth2UserService;
private final NaverOAuth2UserService naverOAuth2UserService;

@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
    String provider = userRequest.getClientRegistration().getRegistrationId();

    return switch (provider) {
        case "google" -> googleOAuth2UserService.loadUser(userRequest);
        case "naver" -> naverOAuth2UserService.loadUser(userRequest);
        default -> throw new OAuth2AuthenticationException("지원하지 않는 소셜 로그인입니다: " + provider);
    };
}

 

📌  OAuth2UserProviderRouter.java 수정

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

    private final GoogleOAuth2UserService googleOAuth2UserService;
    private final NaverOAuth2UserService naverOAuth2UserService; //추가
    // 추후 NaverOAuth2UserService, KakaoOAuth2UserService 등 추가 가능

    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
        String provider = userRequest.getClientRegistration().getRegistrationId(); // "google"

        return switch (provider) {
            case "google" -> googleOAuth2UserService.loadUser(userRequest);
            case "naver" -> naverOAuth2UserService.loadUser(userRequest); //추가
            // case "kakao" -> kakaoOAuth2UserService.loadUser(userRequest);
            default -> throw new OAuth2AuthenticationException("지원하지 않는 소셜 로그인입니다: " + provider);
        };
    }
}

 

📌  application.yml 설정

spring:
  security:
    oauth2:
      client:
        registration:
          naver:
            client-id: 네이버_클라이언트_ID
            client-secret: 네이버_클라이언트_SECRET
            client-authentication-method: post
            authorization-grant-type: authorization_code
            redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
            scope:
              - name
              - email
              - profile_image
            client-name: Naver
        provider:
          naver:
            authorization-uri: https://nid.naver.com/oauth2.0/authorize
            token-uri: https://nid.naver.com/oauth2.0/token
            user-info-uri: https://openapi.naver.com/v1/nid/me
            user-name-attribute: response

 

 


✅ 그리고 테스트를 진행하는데 ... 아래와 같은 에러가 발생함.

java.lang.IllegalArgumentException: This class supports
client_secret_basic
,
client_secret_post
, and
none
by default. Client [naver] is using [post] instead. Please use a supported client authentication method, or use
setRequestEntityConverter
to supply an instance that supports [post].

Spring Security 6에서는 기본적으로 client_secret_basic, none 방식만 지원하고 client_secret_post 방식은 직접 명시적으로 설정하지 않으면 에러가 남. 네이버 로그인은 post 방식만 지원하는데, Spring Security에서는 post가 client_secret_post에 해당함 → 그래서 에러 발생함.

 

그래서 아래와 같이 수정해주었음.

spring:
  security:
    oauth2:
      client:
        registration:
          naver:
            client-authentication-method: client_secret_post  ✅

 

 


[테스트]

 

브라우저에서 http://localhost:8080/oauth2/authorization/naver 에 접속

 

동의하고 회원가입을 마치면 위와 같이 응답 메시지가 생성됨.

728x90
320x100