diff --git a/src/main/java/solitour_backend/solitour/auth/controller/OauthController.java b/src/main/java/solitour_backend/solitour/auth/controller/OauthController.java index c745848..931f75f 100644 --- a/src/main/java/solitour_backend/solitour/auth/controller/OauthController.java +++ b/src/main/java/solitour_backend/solitour/auth/controller/OauthController.java @@ -4,11 +4,11 @@ import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @@ -18,12 +18,16 @@ import solitour_backend.solitour.auth.entity.Token; import solitour_backend.solitour.auth.entity.TokenRepository; import solitour_backend.solitour.auth.exception.TokenNotExistsException; +import solitour_backend.solitour.auth.exception.UnsupportedLoginTypeException; +import solitour_backend.solitour.auth.exception.UserRevokeErrorException; import solitour_backend.solitour.auth.service.OauthService; import solitour_backend.solitour.auth.service.dto.response.AccessTokenResponse; import solitour_backend.solitour.auth.service.dto.response.LoginResponse; import solitour_backend.solitour.auth.service.dto.response.OauthLinkResponse; import solitour_backend.solitour.auth.support.google.GoogleConnector; import solitour_backend.solitour.auth.support.kakao.KakaoConnector; +import solitour_backend.solitour.auth.support.kakao.dto.request.CreateUserInfoRequest; +import solitour_backend.solitour.auth.support.naver.NaverConnector; import solitour_backend.solitour.user.user_status.UserStatus; @@ -35,6 +39,7 @@ public class OauthController { private final OauthService oauthService; private final KakaoConnector kakaoConnector; private final GoogleConnector googleConnector; + private final NaverConnector naverConnector; private final TokenRepository tokenRepository; @GetMapping(value = "/login", params = {"type", "redirectUrl"}) @@ -43,6 +48,22 @@ public ResponseEntity access(@RequestParam String type, @Requ return ResponseEntity.ok(response); } + @PostMapping(value = "/login/kakao", params = {"code", "redirectUrl"}) + public ResponseEntity kakaoLogin(HttpServletResponse response, + @RequestParam String code, @RequestParam String redirectUrl, + @RequestBody CreateUserInfoRequest createUserInfoRequest) { + LoginResponse loginResponse = oauthService.requestkakaoAccessToken(code, redirectUrl, createUserInfoRequest); + + String accessCookieHeader = setCookieHeader(loginResponse.getAccessToken()); + String refreshCookieHeader = setCookieHeader(loginResponse.getRefreshToken()); + + response.addHeader("Set-Cookie", accessCookieHeader); + response.addHeader("Set-Cookie", refreshCookieHeader); + + return ResponseEntity.ok(loginResponse.getLoginStatus()); + } + + @GetMapping(value = "/login", params = {"type", "code", "redirectUrl"}) public ResponseEntity login(HttpServletResponse response, @RequestParam String type, @RequestParam String code, @RequestParam String redirectUrl) { diff --git a/src/main/java/solitour_backend/solitour/auth/service/OauthService.java b/src/main/java/solitour_backend/solitour/auth/service/OauthService.java index 413b16c..f7d90da 100644 --- a/src/main/java/solitour_backend/solitour/auth/service/OauthService.java +++ b/src/main/java/solitour_backend/solitour/auth/service/OauthService.java @@ -14,6 +14,8 @@ import org.springframework.transaction.annotation.Transactional; import solitour_backend.solitour.auth.entity.Token; import solitour_backend.solitour.auth.entity.TokenRepository; +import solitour_backend.solitour.auth.exception.RevokeFailException; +import solitour_backend.solitour.auth.exception.UnsupportedLoginTypeException; import solitour_backend.solitour.auth.service.dto.response.AccessTokenResponse; import solitour_backend.solitour.auth.service.dto.response.LoginResponse; import solitour_backend.solitour.auth.service.dto.response.OauthLinkResponse; @@ -27,6 +29,12 @@ import solitour_backend.solitour.auth.support.kakao.dto.KakaoTokenAndUserResponse; import solitour_backend.solitour.auth.support.kakao.dto.KakaoTokenResponse; import solitour_backend.solitour.auth.support.kakao.dto.KakaoUserResponse; +import solitour_backend.solitour.auth.support.kakao.dto.request.CreateUserInfoRequest; +import solitour_backend.solitour.auth.support.naver.NaverConnector; +import solitour_backend.solitour.auth.support.naver.NaverProvider; +import solitour_backend.solitour.auth.support.naver.dto.NaverTokenAndUserResponse; +import solitour_backend.solitour.auth.support.naver.dto.NaverTokenResponse; +import solitour_backend.solitour.auth.support.naver.dto.NaverUserResponse; import solitour_backend.solitour.image.s3.S3Uploader; import solitour_backend.solitour.user.entity.User; import solitour_backend.solitour.user.exception.BlockedUserException; @@ -49,6 +57,8 @@ public class OauthService { private final KakaoProvider kakaoProvider; private final GoogleConnector googleConnector; private final GoogleProvider googleProvider; + private final NaverConnector naverConnector; + private final NaverProvider naverProvider; private final UserImageService userImageService; private final TokenRepository tokenRepository; private final UserImageRepository userImageRepository; @@ -83,6 +93,25 @@ public LoginResponse requestAccessToken(String type, String code, String redirec return new LoginResponse(accessCookie, refreshCookie, user.getUserStatus()); } + @Transactional + public LoginResponse requestkakaoAccessToken(String code, String redirectUrl, + CreateUserInfoRequest createUserInfoRequest) { + User user = checkAndSaveKakaoUser(code, redirectUrl, createUserInfoRequest); + user.updateLoginTime(); + final int ACCESS_COOKIE_AGE = (int) TimeUnit.MINUTES.toSeconds(30); + final int REFRESH_COOKIE_AGE = (int) TimeUnit.DAYS.toSeconds(30); + + String token = jwtTokenProvider.createAccessToken(user.getId()); + String refreshToken = jwtTokenProvider.createRefreshToken(user.getId()); + + tokenService.synchronizeRefreshToken(user, refreshToken); + + Cookie accessCookie = createCookie("access_token", token, ACCESS_COOKIE_AGE); + Cookie refreshCookie = createCookie("refresh_token", refreshToken, REFRESH_COOKIE_AGE); + + return new LoginResponse(accessCookie, refreshCookie, user.getUserStatus()); + } + private Cookie createCookie(String name, String value, int maxAge) { Cookie cookie = new Cookie(name, value); cookie.setSecure(true); @@ -92,6 +121,23 @@ private Cookie createCookie(String name, String value, int maxAge) { return cookie; } + private User checkAndSaveKakaoUser(String code, String redirectUrl, CreateUserInfoRequest createUserInfoRequest) { + KakaoTokenAndUserResponse response = kakaoConnector.requestKakaoUserInfo(code, redirectUrl); + KakaoTokenResponse tokenResponse = response.getKakaoTokenResponse(); + KakaoUserResponse kakaoUserResponse = response.getKakaoUserResponse(); + + String id = kakaoUserResponse.getId().toString(); + User user = userRepository.findByOauthId(id) + .orElseGet(() -> saveActiveKakaoUser(kakaoUserResponse, createUserInfoRequest)); + + checkUserStatus(user); + + Token token = tokenRepository.findByUserId(user.getId()) + .orElseGet(() -> tokenService.saveToken(tokenResponse.getRefreshToken(), user)); + + return user; + } + private User checkAndSaveUser(String type, String code, String redirectUrl) { if (Objects.equals(type, "kakao")) { KakaoTokenAndUserResponse response = kakaoConnector.requestKakaoUserInfo(code, redirectUrl); @@ -169,8 +215,29 @@ private String getGoogleUserImage(GoogleUserResponse response) { return USER_PROFILE_NONE; } + private User saveActiveKakaoUser(KakaoUserResponse kakaoUserResponse, CreateUserInfoRequest createUserInfoRequest) { + String imageUrl = getDefaultUserImage(createUserInfoRequest.getSex()); + UserImage savedUserImage = userImageService.saveUserImage(imageUrl); + + User user = User.builder() + .userStatus(UserStatus.ACTIVATE) + .oauthId(String.valueOf(kakaoUserResponse.getId())) + .provider("kakao") + .isAdmin(false) + .userImage(savedUserImage) + .name(createUserInfoRequest.getName()) + .sex(createUserInfoRequest.getSex()) + .nickname(RandomNickName.generateRandomNickname()) + .email(kakaoUserResponse.getKakaoAccount().getEmail()) + .name(createUserInfoRequest.getName()) + .age(Integer.valueOf(createUserInfoRequest.getAge())) + .createdAt(LocalDateTime.now()) + .build(); + return userRepository.save(user); + } + private User saveKakaoUser(KakaoUserResponse response) { - String imageUrl = getKakaoUserImage(response); + String imageUrl = getDefaultUserImage(response.getKakaoAccount().getGender()); UserImage savedUserImage = userImageService.saveUserImage(imageUrl); User user = User.builder() @@ -261,22 +328,25 @@ private void changeToDefaultProfile(User user, UserImage userImage) { } private String getDefaultProfile(User user) { - String sex = user.getSex(); - if (sex.equals("male")) { - { + if (user.getSex() != null) { + if (user.getSex().equals("male")) { return USER_PROFILE_MALE; + } else { + return USER_PROFILE_FEMALE; } - } else { - return USER_PROFILE_FEMALE; } + return USER_PROFILE_NONE; } - private void deleteUserProfileFromS3(UserImage userImage, String defaultImageUrl) { - String userImageUrl = userImage.getAddress(); - if (userImageUrl.equals(USER_PROFILE_MALE) || userImageUrl.equals(USER_PROFILE_FEMALE)) { - return; + private void deleteUserProfileFromS3 (UserImage userImage, String defaultImageUrl){ + String userImageUrl = userImage.getAddress(); + if (userImageUrl.equals(USER_PROFILE_MALE) || userImageUrl.equals(USER_PROFILE_FEMALE) + || userImageUrl.equals( + USER_PROFILE_NONE)) { + return; + } + s3Uploader.deleteImage(userImageUrl); + userImage.changeToDefaultProfile(defaultImageUrl); } - s3Uploader.deleteImage(userImageUrl); - userImage.changeToDefaultProfile(defaultImageUrl); + } -} diff --git a/src/main/java/solitour_backend/solitour/auth/service/TokenService.java b/src/main/java/solitour_backend/solitour/auth/service/TokenService.java index 99eebc6..b4c2758 100644 --- a/src/main/java/solitour_backend/solitour/auth/service/TokenService.java +++ b/src/main/java/solitour_backend/solitour/auth/service/TokenService.java @@ -30,10 +30,10 @@ public void deleteByMemberId(Long memberId) { } @Transactional - public Token saveToken(KakaoTokenResponse tokenResponse, User user) { + public Token saveToken(String refreshToken, User user) { Token token = Token.builder() .user(user) - .oauthToken(tokenResponse.getRefreshToken()) + .oauthToken(refreshToken) .build(); tokenRepository.save(token); diff --git a/src/main/java/solitour_backend/solitour/auth/support/kakao/dto/request/CreateUserInfoRequest.java b/src/main/java/solitour_backend/solitour/auth/support/kakao/dto/request/CreateUserInfoRequest.java new file mode 100644 index 0000000..ddba8c8 --- /dev/null +++ b/src/main/java/solitour_backend/solitour/auth/support/kakao/dto/request/CreateUserInfoRequest.java @@ -0,0 +1,12 @@ +package solitour_backend.solitour.auth.support.kakao.dto.request; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@Getter +public class CreateUserInfoRequest { + private String name; + private String age; + private String sex; +}