-
Notifications
You must be signed in to change notification settings - Fork 1
feat: 소셜 로그인 방식 변경 #310
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
feat: 소셜 로그인 방식 변경 #310
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,49 @@ | ||
| package UMC_7th.Closit.domain.user.dto; | ||
|
|
||
|
|
||
| import jakarta.validation.constraints.NotBlank; | ||
| import jakarta.validation.constraints.NotNull; | ||
| import lombok.AllArgsConstructor; | ||
| import lombok.Builder; | ||
| import lombok.Data; | ||
| import lombok.NoArgsConstructor; | ||
|
|
||
| @Data | ||
| @Builder | ||
| @AllArgsConstructor | ||
| @NoArgsConstructor | ||
| public class OAuthLoginRequestDTO { | ||
|
|
||
| private String idToken; | ||
| /** | ||
| * 토큰 타입 (ID_TOKEN 또는 ACCESS_TOKEN) | ||
| */ | ||
| @NotNull(message = "토큰 타입은 필수입니다.") | ||
| private TokenType tokenType; | ||
|
|
||
| /** | ||
| * 소셜 플랫폼에서 발급받은 토큰 | ||
| */ | ||
| @NotBlank(message = "토큰은 필수입니다.") | ||
| private String token; | ||
|
|
||
| /** | ||
| * 토큰 타입 열거형 | ||
| */ | ||
| public enum TokenType { | ||
| ID_TOKEN, // ID Token (OpenID Connect) | ||
| ACCESS_TOKEN // Access Token (OAuth 2.0) | ||
| } | ||
|
|
||
| // 기존 호환성을 위한 생성자 (deprecated) | ||
| @Deprecated | ||
| public OAuthLoginRequestDTO(String idToken) { | ||
| this.tokenType = TokenType.ID_TOKEN; | ||
| this.token = idToken; | ||
| } | ||
|
|
||
| // 기존 호환성을 위한 getter (deprecated) | ||
| @Deprecated | ||
| public String getIdToken() { | ||
| return tokenType == TokenType.ID_TOKEN ? token : null; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,30 +2,52 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import UMC_7th.Closit.global.common.SocialLoginType; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import com.fasterxml.jackson.databind.JsonNode; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import lombok.RequiredArgsConstructor; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @RequiredArgsConstructor | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public class GoogleUserInfo implements OAuthUserInfo { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final GoogleIdToken.Payload payload; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final JsonNode userInfoJson; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // ID Token용 생성자 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public GoogleUserInfo(GoogleIdToken.Payload payload) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.payload = payload; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.userInfoJson = null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Access Token용 생성자 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public GoogleUserInfo(JsonNode userInfoJson) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.payload = null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.userInfoJson = userInfoJson; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public String providerId () { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return payload.getSubject(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public String providerId() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (payload != null) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return payload.getSubject(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return userInfoJson.get("id").asText(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public String getEmail () { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return payload.getEmail(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public String getEmail() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (payload != null) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return payload.getEmail(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return userInfoJson.get("email").asText(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public String getName () { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return payload.get("name").toString(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public String getName() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (payload != null) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return payload.get("name").toString(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return userInfoJson.get("name").asText(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
33
to
47
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion getEmail과 getName 메서드에서 일관성 및 안전성을 개선해야 합니다. 메서드 구현에서 몇 가지 문제점이 있습니다:
@Override
public String getEmail() {
if (payload != null) {
return payload.getEmail();
}
- return userInfoJson.get("email").asText();
+ JsonNode emailNode = userInfoJson.get("email");
+ return emailNode != null ? emailNode.asText() : null;
}
@Override
public String getName() {
if (payload != null) {
- return payload.get("name").toString();
+ Object name = payload.get("name");
+ return name != null ? name.toString() : null;
}
- return userInfoJson.get("name").asText();
+ JsonNode nameNode = userInfoJson.get("name");
+ return nameNode != null ? nameNode.asText() : null;
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public SocialLoginType getProvider () { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public SocialLoginType getProvider() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return SocialLoginType.GOOGLE; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,49 @@ | ||||||||||||||||||||||||||
| package UMC_7th.Closit.domain.user.entity; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| import UMC_7th.Closit.global.common.SocialLoginType; | ||||||||||||||||||||||||||
| import com.fasterxml.jackson.databind.JsonNode; | ||||||||||||||||||||||||||
| import lombok.RequiredArgsConstructor; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| @RequiredArgsConstructor | ||||||||||||||||||||||||||
| public class KakaoUserInfo implements OAuthUserInfo { | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| private final JsonNode userInfoJson; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||
| public String providerId() { | ||||||||||||||||||||||||||
| return userInfoJson.get("id").asText(); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
Comment on lines
+12
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. providerId() 메서드에서 null 체크가 누락되어 있습니다. JSON에서 "id" 필드가 없거나 null인 경우 NullPointerException이 발생할 수 있습니다. NaverUserInfo와 달리 null 체크가 없습니다. 다음과 같이 수정하여 안전성을 개선하세요: @Override
public String providerId() {
- return userInfoJson.get("id").asText();
+ JsonNode idNode = userInfoJson.get("id");
+ if (idNode != null) {
+ return idNode.asText();
+ }
+ throw new IllegalStateException("카카오 응답에서 사용자 ID를 가져올 수 없습니다.");
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||
| public String getEmail() { | ||||||||||||||||||||||||||
| JsonNode kakaoAccount = userInfoJson.get("kakao_account"); | ||||||||||||||||||||||||||
| if (kakaoAccount != null && kakaoAccount.has("email")) { | ||||||||||||||||||||||||||
| return kakaoAccount.get("email").asText(); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| throw new IllegalStateException("카카오 계정에서 이메일 정보를 가져올 수 없습니다."); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||
| public String getName() { | ||||||||||||||||||||||||||
| JsonNode properties = userInfoJson.get("properties"); | ||||||||||||||||||||||||||
| if (properties != null && properties.has("nickname")) { | ||||||||||||||||||||||||||
| return properties.get("nickname").asText(); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| JsonNode kakaoAccount = userInfoJson.get("kakao_account"); | ||||||||||||||||||||||||||
| if (kakaoAccount != null && kakaoAccount.has("profile")) { | ||||||||||||||||||||||||||
| JsonNode profile = kakaoAccount.get("profile"); | ||||||||||||||||||||||||||
| if (profile.has("nickname")) { | ||||||||||||||||||||||||||
| return profile.get("nickname").asText(); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| return "카카오 사용자"; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||
| public SocialLoginType getProvider() { | ||||||||||||||||||||||||||
| return SocialLoginType.KAKAO; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| package UMC_7th.Closit.domain.user.entity; | ||
|
|
||
| import UMC_7th.Closit.global.common.SocialLoginType; | ||
| import com.fasterxml.jackson.databind.JsonNode; | ||
| import lombok.RequiredArgsConstructor; | ||
|
|
||
| @RequiredArgsConstructor | ||
| public class NaverUserInfo implements OAuthUserInfo { | ||
|
|
||
| private final JsonNode userInfoJson; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 생성자 null 체크 추가 권장
@RequiredArgsConstructor
public class NaverUserInfo implements OAuthUserInfo {
- private final JsonNode userInfoJson;
+ private final JsonNode userInfoJson;
+
+ public NaverUserInfo(JsonNode userInfoJson) {
+ this.userInfoJson = Objects.requireNonNull(userInfoJson, "사용자 정보 JSON은 null일 수 없습니다.");
+ }그리고 import 추가: import java.util.Objects;🤖 Prompt for AI Agents |
||
|
|
||
| @Override | ||
| public String providerId() { | ||
| JsonNode response = userInfoJson.get("response"); | ||
| if (response != null && response.has("id")) { | ||
| return response.get("id").asText(); | ||
| } | ||
| throw new IllegalStateException("네이버 응답에서 사용자 ID를 가져올 수 없습니다."); | ||
| } | ||
|
|
||
| @Override | ||
| public String getEmail() { | ||
| JsonNode response = userInfoJson.get("response"); | ||
| if (response != null && response.has("email")) { | ||
| return response.get("email").asText(); | ||
| } | ||
| throw new IllegalStateException("네이버 계정에서 이메일 정보를 가져올 수 없습니다."); | ||
| } | ||
|
|
||
| @Override | ||
| public String getName() { | ||
| JsonNode response = userInfoJson.get("response"); | ||
| if (response != null) { | ||
| if (response.has("name")) { | ||
| return response.get("name").asText(); | ||
| } | ||
| if (response.has("nickname")) { | ||
| return response.get("nickname").asText(); | ||
| } | ||
| } | ||
| return "네이버 사용자"; | ||
| } | ||
|
|
||
| @Override | ||
| public SocialLoginType getProvider() { | ||
| return SocialLoginType.NAVER; | ||
| } | ||
| } | ||
|
|
||
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
잘못된 Maven Group ID ‑
org.mockitox→org.mockitoorg.mockitox:mockito-core는 존재하지 않아 빌드 실패가 발생합니다.📝 Committable suggestion
🤖 Prompt for AI Agents