diff --git a/src/main/java/com/with/picme/common/message/ErrorMessage.java b/src/main/java/com/with/picme/common/message/ErrorMessage.java index cc9b214..f6d803d 100644 --- a/src/main/java/com/with/picme/common/message/ErrorMessage.java +++ b/src/main/java/com/with/picme/common/message/ErrorMessage.java @@ -38,7 +38,12 @@ public enum ErrorMessage { /** * user */ - CANT_GET_USERINFO("유저 아이디를 갖고올 수 없습니다."); + CANT_GET_USERINFO("유저 아이디를 갖고올 수 없습니다."), + + /* + social login + */ + CHECK_KAKAO_USER_FAIL("카카오 계정 확인 실패"); private final String message; } diff --git a/src/main/java/com/with/picme/common/message/ResponseMessage.java b/src/main/java/com/with/picme/common/message/ResponseMessage.java index 4754dd4..67fd107 100644 --- a/src/main/java/com/with/picme/common/message/ResponseMessage.java +++ b/src/main/java/com/with/picme/common/message/ResponseMessage.java @@ -21,8 +21,12 @@ public enum ResponseMessage { /* user */ - GET_USER_INFO("유저 정보 갖고오기 성공"); + GET_USER_INFO("유저 정보 갖고오기 성공"), + /* + social login + */ + SOCIAL_SIGNIN_SUCCESS("소셜 로그인 성공"); private final String message; } diff --git a/src/main/java/com/with/picme/controller/AuthController.java b/src/main/java/com/with/picme/controller/AuthController.java index 34cff9b..92093b6 100644 --- a/src/main/java/com/with/picme/controller/AuthController.java +++ b/src/main/java/com/with/picme/controller/AuthController.java @@ -1,10 +1,7 @@ package com.with.picme.controller; import com.with.picme.common.ApiResponse; -import com.with.picme.dto.auth.AuthSignInRequestDto; -import com.with.picme.dto.auth.AuthSignInResponseDto; -import com.with.picme.dto.auth.AuthSignUpRequestDto; -import com.with.picme.dto.auth.AuthSignUpResponseDto; +import com.with.picme.dto.auth.*; import com.with.picme.service.AuthServiceImpl; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -13,8 +10,8 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.validation.Valid; -import static com.with.picme.common.message.ResponseMessage.SUCCESS_SIGN_IN; -import static com.with.picme.common.message.ResponseMessage.SUCCESS_SIGN_UP; + +import static com.with.picme.common.message.ResponseMessage.*; @RestController @RequestMapping("/auth") @@ -33,4 +30,11 @@ public ResponseEntity signInUser(@RequestBody AuthSignInRequestDto AuthSignInResponseDto response = authService.signInUser(request); return ResponseEntity.ok(ApiResponse.success(SUCCESS_SIGN_IN.getMessage(), response)); } + + @PostMapping("/kakao/signin") + public ResponseEntity loginSocialUser(@Valid @RequestBody AuthSocialSignInRequestDto request){ + AuthSignUpResponseDto response = authService.loginSocialUser(request); + return ResponseEntity.ok(ApiResponse.success(SOCIAL_SIGNIN_SUCCESS.getMessage(), response)); + } + } diff --git a/src/main/java/com/with/picme/dto/auth/AuthSocialSignInRequestDto.java b/src/main/java/com/with/picme/dto/auth/AuthSocialSignInRequestDto.java new file mode 100644 index 0000000..c9030f3 --- /dev/null +++ b/src/main/java/com/with/picme/dto/auth/AuthSocialSignInRequestDto.java @@ -0,0 +1,10 @@ +package com.with.picme.dto.auth; + +import javax.validation.constraints.NotBlank; + +public record AuthSocialSignInRequestDto ( + Long uid, + @NotBlank(message = "소셜타입은 필수 입력값입니다.") + String socialType +){ +} diff --git a/src/main/java/com/with/picme/dto/auth/kakao/KakaoUser.java b/src/main/java/com/with/picme/dto/auth/kakao/KakaoUser.java new file mode 100644 index 0000000..543687c --- /dev/null +++ b/src/main/java/com/with/picme/dto/auth/kakao/KakaoUser.java @@ -0,0 +1,20 @@ +package com.with.picme.dto.auth.kakao; + +import com.with.picme.entity.ProviderType; +import lombok.Builder; + +@Builder +public record KakaoUser( + Long userId, + String email, + ProviderType providerType +) { + public static KakaoUser of(Long userId, String email){ + return KakaoUser + .builder() + .userId(userId) + .email(email) + .providerType(ProviderType.kakao) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/com/with/picme/entity/AuthenticationProvider.java b/src/main/java/com/with/picme/entity/AuthenticationProvider.java index 3be4b08..b059108 100644 --- a/src/main/java/com/with/picme/entity/AuthenticationProvider.java +++ b/src/main/java/com/with/picme/entity/AuthenticationProvider.java @@ -13,6 +13,7 @@ @Setter @Entity @NoArgsConstructor +@Table(name = "\"AuthenticationProvider\"") public class AuthenticationProvider { @Id @GeneratedValue(strategy = IDENTITY) @@ -20,6 +21,7 @@ public class AuthenticationProvider { private Long id; @Column(name="provider_type") + @Enumerated(EnumType.STRING) private ProviderType provider; @OneToOne(fetch = FetchType.LAZY) diff --git a/src/main/java/com/with/picme/entity/ProviderType.java b/src/main/java/com/with/picme/entity/ProviderType.java index e099149..fffedf8 100644 --- a/src/main/java/com/with/picme/entity/ProviderType.java +++ b/src/main/java/com/with/picme/entity/ProviderType.java @@ -1,5 +1,9 @@ package com.with.picme.entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; + public enum ProviderType { + @Enumerated(EnumType.STRING) kakao, naver, google -} +} \ No newline at end of file diff --git a/src/main/java/com/with/picme/repository/AuthenticationProviderRepository.java b/src/main/java/com/with/picme/repository/AuthenticationProviderRepository.java new file mode 100644 index 0000000..9db9c11 --- /dev/null +++ b/src/main/java/com/with/picme/repository/AuthenticationProviderRepository.java @@ -0,0 +1,14 @@ +package com.with.picme.repository; + +import com.with.picme.entity.AuthenticationProvider; +import com.with.picme.entity.ProviderType; +import org.springframework.data.jpa.repository.EntityGraph; +import org.springframework.data.jpa.repository.JpaRepository; + + +import java.util.Optional; + +public interface AuthenticationProviderRepository extends JpaRepository { + @EntityGraph(attributePaths = "user") + Optional findByIdAndProvider(Long id, ProviderType providerType); +} \ No newline at end of file diff --git a/src/main/java/com/with/picme/service/AuthService.java b/src/main/java/com/with/picme/service/AuthService.java index 1c5ed90..d2e1930 100644 --- a/src/main/java/com/with/picme/service/AuthService.java +++ b/src/main/java/com/with/picme/service/AuthService.java @@ -1,12 +1,11 @@ package com.with.picme.service; -import com.with.picme.dto.auth.AuthSignInRequestDto; -import com.with.picme.dto.auth.AuthSignInResponseDto; -import com.with.picme.dto.auth.AuthSignUpRequestDto; -import com.with.picme.dto.auth.AuthSignUpResponseDto; +import com.with.picme.dto.auth.*; public interface AuthService { AuthSignUpResponseDto createUser(AuthSignUpRequestDto request); AuthSignInResponseDto signInUser(AuthSignInRequestDto request); + + AuthSignUpResponseDto loginSocialUser(AuthSocialSignInRequestDto reqeust); } diff --git a/src/main/java/com/with/picme/service/AuthServiceImpl.java b/src/main/java/com/with/picme/service/AuthServiceImpl.java index 11fd807..5269084 100644 --- a/src/main/java/com/with/picme/service/AuthServiceImpl.java +++ b/src/main/java/com/with/picme/service/AuthServiceImpl.java @@ -1,13 +1,14 @@ package com.with.picme.service; +import com.with.picme.common.message.ErrorMessage; import com.with.picme.config.SaltEncrypt; import com.with.picme.config.jwt.JwtTokenProvider; import com.with.picme.config.jwt.UserAuthentication; -import com.with.picme.dto.auth.AuthSignInRequestDto; -import com.with.picme.dto.auth.AuthSignInResponseDto; -import com.with.picme.dto.auth.AuthSignUpRequestDto; -import com.with.picme.dto.auth.AuthSignUpResponseDto; +import com.with.picme.dto.auth.*; +import com.with.picme.dto.auth.kakao.KakaoUser; +import com.with.picme.entity.AuthenticationProvider; import com.with.picme.entity.User; +import com.with.picme.repository.AuthenticationProviderRepository; import com.with.picme.repository.UserRepository; import lombok.RequiredArgsConstructor; import org.springframework.security.core.Authentication; @@ -16,6 +17,9 @@ import javax.persistence.EntityNotFoundException; +import java.util.Objects; +import java.util.Optional; + import static com.with.picme.common.message.ErrorMessage.*; @RequiredArgsConstructor @@ -25,6 +29,7 @@ public class AuthServiceImpl implements AuthService { private final UserRepository userRepository; private final SaltEncrypt saltEncrypt; private final JwtTokenProvider tokenProvider; + private final AuthenticationProviderRepository authenticationProviderRepository; @Override public AuthSignUpResponseDto createUser(AuthSignUpRequestDto request) { @@ -66,6 +71,31 @@ public AuthSignInResponseDto signInUser(AuthSignInRequestDto request) { return AuthSignInResponseDto.of(user, accessToken); } + @Override + public AuthSignUpResponseDto loginSocialUser(AuthSocialSignInRequestDto request){ + User user = findByKey(KakaoUser.of(request.uid(), request.socialType())); + if (Objects.isNull(user)) + throw new EntityNotFoundException(CHECK_KAKAO_USER_FAIL.getMessage()); + String accessToken = updateAccessTokenAndRefreshToken(user); + return AuthSignUpResponseDto.of(user, accessToken); + } + + public User findByKey(KakaoUser kakaoUser){ + Optional authenticationProvider = authenticationProviderRepository + .findByIdAndProvider(kakaoUser.userId(), + kakaoUser.providerType()); + // 카카오 계정은 확인, 우리 서비스에 이미 로그인함 + if(authenticationProvider.isPresent()) { + Long userId = authenticationProvider.get().getUser().getId(); + //유저 테이블에서 찾기 , 못찾을 경우 에러 날려야 하는지 궁굼.. ->node에서는 return null로 날림 + User user = userRepository.findById(userId) + .orElseThrow(() -> new EntityNotFoundException(ErrorMessage.CANT_GET_USERINFO.getMessage())); + return user; + } + // 카카오 계정은 확인 됐지만, 우리 서비스에는 로그인 안됨 + return null; + } + private User checkPassword(String email, String password) { User user = userRepository.findByEmail(email); if (saltEncrypt.isMatch(password, user.getPassword())) @@ -73,4 +103,12 @@ private User checkPassword(String email, String password) { else throw new IllegalArgumentException(INVALID_PASSWORD.getMessage()); } + + private String updateAccessTokenAndRefreshToken(User user){ + Authentication authentication = new UserAuthentication(user.getId(), null, null); + String accessToken = tokenProvider.generateAccessToken(authentication); + String refreshToken = tokenProvider.generateRefreshToken(authentication); + user.updateRefreshToken(refreshToken); + return accessToken; + } }