[ SpringBoot OAuth2 소셜로그인에 대해 알아보자. ]
[ 소셜로그인 (OAuth2) - Google ]
[ 소셜로그인 (OAuth2) - Kakao ]
<naver>
{
resultcode=00,
message=success,
response = {
id=pvdq1FSG3VZlD7Cp3JuWfAFi-3xir6A-WPlP5f8kXIo, email=chb20050@gmail.com,
name=안창범
}
}
google과 facebook과는 달리 ...
kakao 와 naver 에서 받아온 정보는 객체 안에 객체가 있는 형식이라 추출할 때, 다른 처리 방식이 필요함
위에서 확인한 값들을 우리가 만든 User 엔티티에 맞게끔 변환해서 가입을 시켜줘야 한다.
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
사이트별로 값을 추출하는 방식은 다르지만 추출해야 하는 값은 같기 때문에 통일성을 위해 interface 생성
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");
}
}
@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());
}
}