[SB] 소셜로그인 (OAuth2) - Naver

0

SpringBoot

목록 보기
6/6

Before ...

[ SpringBoot OAuth2 소셜로그인에 대해 알아보자. ]

Others ...

[ 소셜로그인 (OAuth2) - Google ]
[ 소셜로그인 (OAuth2) - Kakao ]

애플리케이션 등록


  1. 네이버 개발자 센터 접속 후 로그인
  2. Application -> 애플리케이션 등록
  3. 애플리케이션 이름 지정 후 사용 API는 네이버 로그인 선택
  4. 필요한 정보 선택
  5. 로그인 오픈 API 서비스 환경에서 PC 웹 선택 후 URL 지정
    서비스 URL : http://localhost:8080
    Callback URL : http://localhost:8080/login/oauth2/code/naver
  6. Client ID와 Client Secret을 저장

GetAttributes 전달 객체

<naver>
{
    resultcode=00, 
    message=success, 
    response = {
        id=pvdq1FSG3VZlD7Cp3JuWfAFi-3xir6A-WPlP5f8kXIo, email=chb20050@gmail.com, 
        name=안창범
    }
}

googlefacebook과는 달리 ...

kakaonaver 에서 받아온 정보는 객체 안에 객체가 있는 형식이라 추출할 때, 다른 처리 방식이 필요함


데이터 변환

위에서 확인한 값들을 우리가 만든 User 엔티티에 맞게끔 변환해서 가입을 시켜줘야 한다.


  • provider = "google", "kakao", "naver", "facebook"
  • providerId = google의 sub값, kakao와 facebook의 id값, naver의 response의 id 값
  • loginId = provider_providerId 로 설정
  • nickname = 각 사이트에 등록한 이름으로 설정
  • email = google과 facebook의 email값, kakao의 kakao_account의 email값, naver의 response의 email값

구현 예제

application.yml

spring:
  # OAuth 로그인
  security:
    oauth2:
      client:
        registration:
          google:
            client-id: 발급받은 클라이언트 ID
            client-secret: 발급받은 클라이언트 보안 비밀번호
            scope:
              - email
              - profile

          kakao:
            client-id: 발급받은 REST API 키
            client-secret: 발급받은 Client Secret 코드
            scope:
              - account_email
              - profile_nickname
            authorization-grant-type: authorization_code
            redirect-uri: http://localhost:8080/login/oauth2/code/kakao
            client-name: Kakao
            client-authentication-method: POST

          naver:
            client-id: 발급받은 Client ID
            client-secret: 발급받은 Client Secret
            scope:
              - name
              - email
            client-name: Naver
            authorization-grant-type: authorization_code
            redirect-uri: http://localhost:8080/login/oauth2/code/naver

          facebook:
            client-id: 발급받은 앱 ID
            client-secret: 발급받은 앱 시크릿 코드
            scope:
              - email
              - public_profile

        provider:
          kakao:
            authorization-uri: https://kauth.kakao.com/oauth/authorize
            token-uri: https://kauth.kakao.com/oauth/token
            user-info-uri: https://kapi.kakao.com/v2/user/me
            user-name-attribute: id

          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

OAuth2UserInfo

사이트별로 값을 추출하는 방식은 다르지만 추출해야 하는 값은 같기 때문에 통일성을 위해 interface 생성

OAuth2UserInfo.java

public interface OAuth2UserInfo {
    String getProviderId();
    String getProvider();
    String getEmail();
    String getName();
}
@AllArgsConstructor
public class NaverUserInfo implements OAuth2UserInfo{

    private Map<String, Object> attributes;

    @Override
    public String getProviderId() {
        return (String) attributes.get("id");
    }

    @Override
    public String getProvider() {
        return "naver";
    }

    @Override
    public String getEmail() {
        return (String) attributes.get("email");
    }

    @Override
    public String getName() {
        return (String) attributes.get("name");
    }
}

OAuth2UserService

OAuth2UserService.java

@Service
@RequiredArgsConstructor
@Slf4j
public class PrincipalOauth2UserService extends DefaultOAuth2UserService {

    private final UserRepository userRepository;
    private final BCryptPasswordEncoder encoder;

    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
        OAuth2User oAuth2User = super.loadUser(userRequest);
        log.info("getAttributes : {}", oAuth2User.getAttributes());

        OAuth2UserInfo oAuth2UserInfo = null;

        String provider = userRequest.getClientRegistration().getRegistrationId();

        if(provider.equals("google")) {
            log.info("구글 로그인 요청");
            oAuth2UserInfo = new GoogleUserInfo( oAuth2User.getAttributes() );
        } else if(provider.equals("kakao")) {
            log.info("카카오 로그인 요청");
            oAuth2UserInfo = new KakaoUserInfo( (Map)oAuth2User.getAttributes() );
        } else if(provider.equals("naver")) {
            log.info("네이버 로그인 요청");
            oAuth2UserInfo = new NaverUserInfo( (Map)oAuth2User.getAttributes().get("response") );
        } else if(provider.equals("facebook")) {
            log.info("페이스북 로그인 요청");
            oAuth2UserInfo = new FacebookUserInfo( oAuth2User.getAttributes() );
        }

        String providerId = oAuth2UserInfo.getProviderId();
        String email = oAuth2UserInfo.getEmail();
        String loginId = provider + "_" + providerId;
        String nickname = oAuth2UserInfo.getName();


        Optional<User> optionalUser = userRepository.findByLoginId(loginId);
        User user = null;

        if(optionalUser.isEmpty()) {
            user = User.builder()
                    .loginId(loginId)
                    .nickname(nickname)
                    .provider(provider)
                    .providerId(providerId)
                    .role(UserRole.USER)
                    .build();
            userRepository.save(user);
        } else {
            user = optionalUser.get();
        }

        return new PrincipalDetails(user, oAuth2User.getAttributes());
    }
}

결과

참조

https://chb2005.tistory.com/183

profile
꿈을 계속 간직하고 있으면 반드시 실현할 때가 온다. - 괴테.

0개의 댓글

관련 채용 정보