[작성일: 2023. 09. 19]
네이버 로그인
참고로 나는 페이스북이 가입이 되어있지 않고 사용할 일이 없을 거 같아서 구글과 네이버만 연동하려고 한다.
페이스북 연동은 하지 않았지만 필요한 코드는 작성했다. 우선 google은 sub라는 id가 존재하지만 facebook과 naver은 sub가 존재하지 않는다. 그래서 username이 만들어질 때 sub에 null값이 들어가게 된다.
이 문제를 해결하기 위해 provider 클래스와 OAuth2Userinfo 인터페이스, 인터페이스를 구현할 GoogleUserInfo 클래스를 따로 만들어준다.
public interface OAuth2UserInfo {
String getProviderId();
String getProvider();
String getEmail();
String getName();
}
public class GoogleUserInfo implements OAuth2UserInfo{
private Map<String, Object> attributes; // getAttributes()
public GoogleUserInfo(Map<String, Object> attributes) {
this.attributes = attributes;
}
@Override
public String getProviderId() {
return (String)attributes.get("sub");
}
@Override
public String getProvider() {
return "google";
}
@Override
public String getEmail() {
return (String)attributes.get("email");
}
@Override
public String getName() {
return (String)attributes.get("name");
}
}
PrincipalOauth2UserService는 아래와 같이 수정해볼 수 있다.
물론 나는 페이스북은 만들지 않았기 때문에 구글만 작성해뒀다.(추후 네이버를 위해)
OAuth2UserInfo oAuth2UserInfo = null;
if (userRequest.getClientRegistration().getRegistrationId().equals("google")) {
System.out.println("구글 로그인 요청");
oAuth2UserInfo = new GoogleUserInfo(oAuth2User.getAttributes());
} else {
System.out.println("우리는 구글만 지원합니다.");
}
// 회원가입
String provider = oAuth2UserInfo.getProvider(); // google
String providerId = oAuth2UserInfo.getProviderId();
String email = oAuth2UserInfo.getEmail();
String username = provider + "_" + providerId; // google_sub
String password = customBCryptPasswordEncoder.encode("겟인데어");
String role = "ROLE_USER";
DB를 살펴보면 provider의 유무로 일반 로그인과 구글 로그인의 차이를 알 수 있다.
우리는 지금 OAuth2-Client 라이브러리를 사용하고 있다. 기본적으로 Provider가 있는데, 이 provider에 모든 포털 사이트를 넣을 순 없다. 구글은 sub에 id를 담아주고 페이스북은 id에 id를 담아주는 것처럼 getAttribute가 다양하기 때문이다. 이제부터 연동할 naver도 provider가 제공되지 않는다.
네이버로는 구현해본 경험이 있기 때문에 애플리케이션만 생성했다.
구글 로그인으로 거의 다 코드가 작성되어 있기 때문에 네이버에는 추가할 게 별로 없었다.
우선 yml에 NAVER 정보를 넣어보자. google과 마찬가지로 id와 secret 정보는 환경변수로 넣었다.
redirect-url은 naver 애플리케이션 생성 시 적었던 Callback URL과 똑같이 적어주어야 한다.
security:
oauth2:
client:
registration:
google:
client-id: ${GOOGLE_CLIENT_ID}
client-secret: ${GOOGLE_CLIENT_SECRET}
scope:
- email
- profile
naver:
client-id: ${NAVER_CLIENT_ID}
client-secret: ${NAVER_CLIENT_SECRET}
scope:
- name
- email
client-name: Naver
authorization-grant-type: authorization_code
redirect-uri: http://localhost:8080/login/oauth2/code/naver
provider:
naver:
authorization-url: https://nid.naver.com/ouath2.0/authorize # 네이버 로그인 창
token-url: https://nid.naver.com/oauth2.0/token # 접근 토큰 발급 요청
user-info-uri: https://openapi.naver.com/v1/nid/me # 프로필 정보 조회
user-name-attribute: response # 회원 정보를 json으로 받는데 resopnse라는 키값으로 네이버가 리턴 해준다.
NaverUserInfo 클래스를 만들고 OAuth2UserInfo를 구현한다. (구글과 똑같이 하되 sub은 id로, provider는 naver로만 바꿔주면 된다.)
PrincipalOauth2UserService에는 네이버 부분을 추가한다.
네이버는 response에 정보가 담겨있기 때문에 response를 가지고 오면 된다.
OAuth2UserInfo oAuth2UserInfo = null;
if (userRequest.getClientRegistration().getRegistrationId().equals("google")) {
System.out.println("구글 로그인 요청");
oAuth2UserInfo = new GoogleUserInfo(oAuth2User.getAttributes());
} else if (userRequest.getClientRegistration().getRegistrationId().equals("naver")) {
System.out.println("네이버 로그인 요청");
oAuth2UserInfo = new NaverUserInfo((Map)oAuth2User.getAttributes().get("response"));
} else {
System.out.println("우리는 구글과 네이버만 지원합니다.");
}
로그인을 진행해보자.
일반 로그인, 구글 로그인, 네이버 로그인이 전부 db에 저장되었다.
여기까지 기본 로그인 + OAuth2.0 로그인을 통합해서 구현해보았다.
🐣 출처: 인프런 최주호님 강의
이 글은 인프런의 최주호님 SpringBoot Security & JWT 강의를 보고 작성한 글입니다.
강의를 들으면서 정리한 글이므로 틀린 내용이나 오타가 있을 수 있습니다.