Skip to content

Commit

Permalink
♻️ refactor: 사용자 중복 OAuth 로그인 검증 로직 추가 (#52)
Browse files Browse the repository at this point in the history
  • Loading branch information
loveysuby committed Sep 29, 2024
1 parent eb5faec commit 1283381
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static slvtwn.khu.toyouserver.domain.SocialAuthProvider.KAKAO;

import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
Expand All @@ -13,59 +14,75 @@
import slvtwn.khu.toyouserver.common.feign.auth.kakao.web.KakaoTokenResponse;
import slvtwn.khu.toyouserver.common.feign.auth.kakao.web.KakaoUserResponse;
import slvtwn.khu.toyouserver.domain.User;
import slvtwn.khu.toyouserver.domain.UserSocialAccount;
import slvtwn.khu.toyouserver.dto.SocialAuthRequest;
import slvtwn.khu.toyouserver.dto.SocialAuthResponse;
import slvtwn.khu.toyouserver.persistance.EventRepository;
import slvtwn.khu.toyouserver.persistance.UserRepository;
import slvtwn.khu.toyouserver.persistance.UserSocialAccountRepository;

@Service
@RequiredArgsConstructor
public class KakaoAuthStrategy implements SocialAuthStrategy {

@Value("${oauth.kakao.client-id}")
private String kakaoClientId;
@Value("${oauth.kakao.redirect-uri}")
private String kakaoRedirectUri;
@Value("${oauth.kakao.grant-type}")
private String kakaoGrantType;
private final UserSocialAccountRepository userSocialAccountRepository;
@Value("${oauth.kakao.client-id}")
private String kakaoClientId;
@Value("${oauth.kakao.redirect-uri}")
private String kakaoRedirectUri;
@Value("${oauth.kakao.grant-type}")
private String kakaoGrantType;

private final KakaoAuthApiClient kakaoAuthApiClient;
private final KakaoResourceApiClient kakaoResourceApiClient;
private final KakaoAuthApiClient kakaoAuthApiClient;
private final KakaoResourceApiClient kakaoResourceApiClient;

private final UserRepository userRepository;
private final UserRepository userRepository;

private final JwtProvider jwtProvider;
private final JwtProvider jwtProvider;

// TODO: 파사드로 카카오 요청 + 유저 저장 부분 분리
// 현재 외부 네트워크에 트랜잭션이 의존하는 상태
@Override
@Transactional
public SocialAuthResponse login(SocialAuthRequest request) {
KakaoTokenResponse tokenResponse = kakaoAuthApiClient.getOAuth2AccessToken(
kakaoGrantType,
kakaoClientId,
kakaoRedirectUri,
request.authorizationCode()
);
KakaoUserResponse userResponse = kakaoResourceApiClient.getUserInformation(
"Bearer " + tokenResponse.accessToken());
User user = registerUser(userResponse);
Token token = jwtProvider.issueTokens(user.getId());
return SocialAuthResponse.of(user.getId(), user.getName(), KAKAO, token);
}
// TODO: 파사드로 카카오 요청 + 유저 저장 부분 분리
// 현재 외부 네트워크에 트랜잭션이 의존하는 상태
@Override
@Transactional
public SocialAuthResponse login(SocialAuthRequest request) {
KakaoTokenResponse tokenResponse = kakaoAuthApiClient.getOAuth2AccessToken(
kakaoGrantType,
kakaoClientId,
kakaoRedirectUri,
request.authorizationCode()
);
KakaoUserResponse userResponse = kakaoResourceApiClient.getUserInformation(
"Bearer " + tokenResponse.accessToken());
User user = findOrCreateUser(userResponse);
Token token = jwtProvider.issueTokens(user.getId());
return SocialAuthResponse.of(user.getId(), user.getName(), KAKAO, token);
}

@Override
public boolean support(String provider) {
return provider.equals("KAKAO");
}
@Override
public boolean support(String provider) {
return provider.equals("KAKAO");
}

private User registerUser(KakaoUserResponse userResponse) {
User user = userRepository.findById(Long.parseLong(userResponse.id())).orElse(null);
if (user == null) {
user = User.create(userResponse.kakaoAccount().profile().nickname(),
userResponse.kakaoAccount().profile().profileImageUrl(), KAKAO);
}
userRepository.save(user);
return user;
}
}
private User findOrCreateUser(KakaoUserResponse userResponse) {
Optional<UserSocialAccount> account = userSocialAccountRepository.findByProviderSerial(
userResponse.id());
if (account.isPresent()) {
UserSocialAccount verifiedSocialAccount = account.get();
return userRepository.findById(verifiedSocialAccount.getUserId()).orElseThrow(
() -> new IllegalStateException("등록된 카카오 계정에 해당하는 유저가 없습니다."));
} else {
return registerUser(userResponse);
}
}

private User registerUser(KakaoUserResponse userResponse) {
User user = User.create(
userResponse.kakaoAccount().profile().nickname(),
userResponse.kakaoAccount().profile().profileImageUrl(),
KAKAO
);
userRepository.save(user);
UserSocialAccount newAccount = UserSocialAccount.createAccountByKakao(user.getId(), userResponse.id());
userSocialAccountRepository.save(newAccount);
return user;
}
}
36 changes: 36 additions & 0 deletions src/main/java/slvtwn/khu/toyouserver/domain/UserSocialAccount.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package slvtwn.khu.toyouserver.domain;


import static jakarta.persistence.GenerationType.IDENTITY;

import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Table(name = "user_social_accounts")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Getter
public class UserSocialAccount {

@Id
@GeneratedValue(strategy = IDENTITY)
private Long id;

@Enumerated(EnumType.STRING)
private SocialAuthProvider provider;
private String providerSerial;
private Long userId;

public static UserSocialAccount createAccountByKakao(Long userId, String providerSerial) {
return new UserSocialAccount(null, SocialAuthProvider.KAKAO, providerSerial, userId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package slvtwn.khu.toyouserver.persistance;

import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import slvtwn.khu.toyouserver.domain.UserSocialAccount;

public interface UserSocialAccountRepository extends JpaRepository<UserSocialAccount, Long> {
Optional<UserSocialAccount> findByProviderSerial(String providerSerial);
}

0 comments on commit 1283381

Please sign in to comment.