From 9db3b25af174d324020c01216d1ed2b144ee287e Mon Sep 17 00:00:00 2001 From: Seokyeong Date: Mon, 12 Feb 2024 17:21:53 +0900 Subject: [PATCH 1/6] rename: AuthServiceProvicer -> AuthService --- .../member/application/auth/AuthService.java | 80 +++++++++++++++++- .../application/auth/AuthServiceProvider.java | 82 ------------------- .../presentation/auth/AuthController.java | 14 ++-- 3 files changed, 84 insertions(+), 92 deletions(-) delete mode 100644 src/main/java/com/fullcar/member/application/auth/AuthServiceProvider.java diff --git a/src/main/java/com/fullcar/member/application/auth/AuthService.java b/src/main/java/com/fullcar/member/application/auth/AuthService.java index e581f8c..684ca98 100644 --- a/src/main/java/com/fullcar/member/application/auth/AuthService.java +++ b/src/main/java/com/fullcar/member/application/auth/AuthService.java @@ -1,8 +1,82 @@ package com.fullcar.member.application.auth; - +import com.fullcar.core.config.jwt.JwtExceptionType; +import com.fullcar.core.config.jwt.JwtTokenProvider; +import com.fullcar.core.exception.CustomException; +import com.fullcar.core.response.ErrorCode; +import com.fullcar.member.application.car.CarService; import com.fullcar.member.domain.member.Member; +import com.fullcar.member.domain.member.MemberRepository; +import com.fullcar.member.domain.member.MemberSocialType; +import com.fullcar.member.domain.member.service.MailService; +import com.fullcar.member.presentation.auth.dto.response.AuthResponseDto; +import com.fullcar.member.presentation.auth.dto.response.AuthTokenResponseDto; +import com.fullcar.member.presentation.auth.dto.response.SocialInfoResponseDto; +import com.fullcar.member.presentation.auth.dto.request.WithdrawRequestDto; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import java.io.IOException; + +@Component +@RequiredArgsConstructor +public class AuthService { + private final JwtTokenProvider jwtTokenProvider; + private final MemberRepository memberRepository; + private final AppleAuthService appleAuthService; + private final KakaoAuthService kakaoAuthService; + private final CarService carService; + private final MailService mailService; + + public AuthResponseDto socialLogin(SocialInfoResponseDto socialResponseDto) { + Member member = memberRepository.findBySocialId(socialResponseDto.getSocialId()); + String accessToken = jwtTokenProvider.generateAccessToken(member); + + return AuthResponseDto.builder() + .accessToken(accessToken) + .refreshToken(socialResponseDto.getRefreshToken()) + .build(); + } + + public AuthTokenResponseDto getNewToken(String refreshToken) { + // refresh 만료 + if (jwtTokenProvider.validateToken(refreshToken) == JwtExceptionType.EXPIRED_JWT_TOKEN) { + throw new CustomException(ErrorCode.SIGNIN_REQUIRED); + } + + // 해당 refreshToken을 가진 멤버가 존재하는지 확인 + Member member = memberRepository.findByRefreshTokenOrThrow(refreshToken); + String newAccessToken = jwtTokenProvider.generateAccessToken(member); + + return AuthTokenResponseDto.builder() + .accessToken(newAccessToken) + .refreshToken(refreshToken) + .build(); + } + + @Transactional + public void socialLogout(Member member) { + memberRepository.findByIdAndIsDeletedOrThrow(member.getId(), false).clearRefreshTokenAndDeviceToken(); + memberRepository.flush(); + } + + @Transactional + public void withdrawMember(Member member, WithdrawRequestDto withdrawRequestDto) throws IOException { + if (withdrawRequestDto.getSocialType() == MemberSocialType.APPLE) { + appleAuthService.revoke(member); + } + else if (withdrawRequestDto.getSocialType() == MemberSocialType.KAKAO) { + kakaoAuthService.revoke(member); + } + else { + throw new CustomException(ErrorCode.INVALID_SOCIAL_TYPE); + } + + carService.deleteCar(member.getCarId()); + mailService.deleteMail(member.getId()); + memberRepository.saveAndFlush(member.deleted()); -public interface AuthService { - void deleteUser(Member member); + // TODO: 이벤트 기반으로 게시글 및 요청 처리 + } } diff --git a/src/main/java/com/fullcar/member/application/auth/AuthServiceProvider.java b/src/main/java/com/fullcar/member/application/auth/AuthServiceProvider.java deleted file mode 100644 index 853ffca..0000000 --- a/src/main/java/com/fullcar/member/application/auth/AuthServiceProvider.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.fullcar.member.application.auth; - -import com.fullcar.core.config.jwt.JwtExceptionType; -import com.fullcar.core.config.jwt.JwtTokenProvider; -import com.fullcar.core.exception.CustomException; -import com.fullcar.core.response.ErrorCode; -import com.fullcar.member.application.car.CarService; -import com.fullcar.member.domain.member.Member; -import com.fullcar.member.domain.member.MemberRepository; -import com.fullcar.member.domain.member.MemberSocialType; -import com.fullcar.member.domain.member.service.MailService; -import com.fullcar.member.presentation.auth.dto.response.AuthResponseDto; -import com.fullcar.member.presentation.auth.dto.response.AuthTokenResponseDto; -import com.fullcar.member.presentation.auth.dto.response.SocialInfoResponseDto; -import com.fullcar.member.presentation.auth.dto.request.WithdrawRequestDto; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; - -import java.io.IOException; - -@Component -@RequiredArgsConstructor -public class AuthServiceProvider { - private final JwtTokenProvider jwtTokenProvider; - private final MemberRepository memberRepository; - private final AppleAuthService appleAuthService; - private final KakaoAuthService kakaoAuthService; - private final CarService carService; - private final MailService mailService; - - public AuthResponseDto socialLogin(SocialInfoResponseDto socialResponseDto) { - Member member = memberRepository.findBySocialId(socialResponseDto.getSocialId()); - String accessToken = jwtTokenProvider.generateAccessToken(member); - - return AuthResponseDto.builder() - .accessToken(accessToken) - .refreshToken(socialResponseDto.getRefreshToken()) - .build(); - } - - public AuthTokenResponseDto getNewToken(String refreshToken) { - // refresh 만료 - if (jwtTokenProvider.validateToken(refreshToken) == JwtExceptionType.EXPIRED_JWT_TOKEN) { - throw new CustomException(ErrorCode.SIGNIN_REQUIRED); - } - - // 해당 refreshToken을 가진 멤버가 존재하는지 확인 - Member member = memberRepository.findByRefreshTokenOrThrow(refreshToken); - String newAccessToken = jwtTokenProvider.generateAccessToken(member); - - return AuthTokenResponseDto.builder() - .accessToken(newAccessToken) - .refreshToken(refreshToken) - .build(); - } - - @Transactional - public void socialLogout(Member member) { - memberRepository.findByIdAndIsDeletedOrThrow(member.getId(), false).clearRefreshTokenAndDeviceToken(); - memberRepository.flush(); - } - - @Transactional - public void withdrawMember(Member member, WithdrawRequestDto withdrawRequestDto) throws IOException { - if (withdrawRequestDto.getSocialType() == MemberSocialType.APPLE) { - appleAuthService.revoke(member); - } - else if (withdrawRequestDto.getSocialType() == MemberSocialType.KAKAO) { - kakaoAuthService.revoke(member); - } - else { - throw new CustomException(ErrorCode.INVALID_SOCIAL_TYPE); - } - - carService.deleteCar(member.getCarId()); - mailService.deleteMail(member.getId()); - memberRepository.saveAndFlush(member.deleted()); - - // TODO: 이벤트 기반으로 게시글 및 요청 처리 - } -} diff --git a/src/main/java/com/fullcar/member/presentation/auth/AuthController.java b/src/main/java/com/fullcar/member/presentation/auth/AuthController.java index 3a5d1ec..52c879f 100644 --- a/src/main/java/com/fullcar/member/presentation/auth/AuthController.java +++ b/src/main/java/com/fullcar/member/presentation/auth/AuthController.java @@ -4,7 +4,7 @@ import com.fullcar.core.response.ApiResponse; import com.fullcar.core.response.SuccessCode; import com.fullcar.member.application.auth.AppleAuthService; -import com.fullcar.member.application.auth.AuthServiceProvider; +import com.fullcar.member.application.auth.AuthService; import com.fullcar.member.application.auth.KakaoAuthService; import com.fullcar.member.domain.member.Member; import com.fullcar.member.presentation.auth.dto.request.AppleAuthRequestDto; @@ -30,7 +30,7 @@ @RequiredArgsConstructor @Tag(name = "[Auth] 인증/인가 관련 API") public class AuthController { - private final AuthServiceProvider authServiceProvider; + private final AuthService authService; private final AppleAuthService appleAuthService; private final KakaoAuthService kakaoAuthService; @@ -43,7 +43,7 @@ public class AuthController { @PostMapping("/login/apple") public ApiResponse appleLogin(@RequestBody AppleAuthRequestDto appleAuthRequestDto) throws IOException { SocialInfoResponseDto socialResponseDto = appleAuthService.getMemberInfo(appleAuthRequestDto); - AuthResponseDto responseDto = authServiceProvider.socialLogin(socialResponseDto); + AuthResponseDto responseDto = authService.socialLogin(socialResponseDto); return ApiResponse.success(SuccessCode.APPLE_LOGIN_SUCCESS, responseDto); } @@ -57,7 +57,7 @@ public ApiResponse appleLogin(@RequestBody AppleAuthRequestDto @PostMapping("/login/kakao") public ApiResponse kakaoLogin(@RequestBody KakaoAuthRequestDto kakaoAuthRequestDto) { SocialInfoResponseDto socialResponseDto = kakaoAuthService.getMemberInfo(kakaoAuthRequestDto); - AuthResponseDto responseDto = authServiceProvider.socialLogin(socialResponseDto); + AuthResponseDto responseDto = authService.socialLogin(socialResponseDto); return ApiResponse.success(SuccessCode.KAKAO_LOGIN_SUCCESS, responseDto); } @@ -71,7 +71,7 @@ public ApiResponse kakaoLogin(@RequestBody KakaoAuthRequestDto @PostMapping("/token") @ResponseStatus(HttpStatus.OK) public ApiResponse getNewToken(@RequestBody AuthTokenRequestDto authTokenRequestDto) { - return ApiResponse.success(SuccessCode.GET_NEW_TOKEN_SUCCESS, authServiceProvider.getNewToken(authTokenRequestDto.getRefreshToken())); + return ApiResponse.success(SuccessCode.GET_NEW_TOKEN_SUCCESS, authService.getNewToken(authTokenRequestDto.getRefreshToken())); } @Operation(summary = "로그아웃 API") @@ -82,7 +82,7 @@ public ApiResponse getNewToken(@RequestBody AuthTokenReque @PostMapping("/logout") @ResponseStatus(HttpStatus.OK) public ApiResponse socialLogout(@CurrentMember Member member) { - authServiceProvider.socialLogout(member); + authService.socialLogout(member); return ApiResponse.success(SuccessCode.LOGOUT_SUCCESS); } @@ -93,7 +93,7 @@ public ApiResponse socialLogout(@CurrentMember Member member) { }) @DeleteMapping() public ApiResponse withdrawMember(@CurrentMember Member member, @RequestBody WithdrawRequestDto withdrawRequestDto) throws IOException { - authServiceProvider.withdrawMember(member, withdrawRequestDto); + authService.withdrawMember(member, withdrawRequestDto); return ApiResponse.success(SuccessCode.WITHDRAW_SUCCESS); } } From a1a42f3b61e6d7753ea0fc8c015b57e9fe82c8fd Mon Sep 17 00:00:00 2001 From: Seokyeong Date: Mon, 12 Feb 2024 18:24:38 +0900 Subject: [PATCH 2/6] feat: withdraw kakao user --- .../exception/CustomExceptionHandler.java | 10 ++++++++++ .../com/fullcar/core/response/ErrorCode.java | 1 + .../application/auth/KakaoAuthService.java | 19 +++++++++++-------- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/fullcar/core/exception/CustomExceptionHandler.java b/src/main/java/com/fullcar/core/exception/CustomExceptionHandler.java index 94ff377..d895c13 100644 --- a/src/main/java/com/fullcar/core/exception/CustomExceptionHandler.java +++ b/src/main/java/com/fullcar/core/exception/CustomExceptionHandler.java @@ -18,4 +18,14 @@ public ApiResponse handleCustomException(CustomException e) { .message(e.getMessage()) .build(); } + + @ExceptionHandler(UnauthorizedException.class) + @ResponseStatus(HttpStatus.UNAUTHORIZED) + public ApiResponse handleUnauthorizedException(UnauthorizedException e) { + + return ApiResponse.builder() + .status(401) + .message(e.getMessage()) + .build(); + } } diff --git a/src/main/java/com/fullcar/core/response/ErrorCode.java b/src/main/java/com/fullcar/core/response/ErrorCode.java index 8d6daa1..f7e83e3 100644 --- a/src/main/java/com/fullcar/core/response/ErrorCode.java +++ b/src/main/java/com/fullcar/core/response/ErrorCode.java @@ -32,6 +32,7 @@ public enum ErrorCode { INVALID_CLAIMS(UNAUTHORIZED, "올바르지 않은 Claim"), SIGNIN_REQUIRED(UNAUTHORIZED, "access, refreshToken 모두 만료되었습니다. 재로그인이 필요합니다."), INVALID_MEMBER(UNAUTHORIZED, "유효하지 않은 유저"), + INVALID_KAKAO_USER(UNAUTHORIZED, "이미 탈퇴되었거나 유효하지 않은 카카오 유저입니다."), /* 404 NOT FOUND */ NOT_EXIST_USER(NOT_FOUND, "존재하지 않는 사용자입니다."), diff --git a/src/main/java/com/fullcar/member/application/auth/KakaoAuthService.java b/src/main/java/com/fullcar/member/application/auth/KakaoAuthService.java index fa5e0fe..afc9ec6 100644 --- a/src/main/java/com/fullcar/member/application/auth/KakaoAuthService.java +++ b/src/main/java/com/fullcar/member/application/auth/KakaoAuthService.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fullcar.core.config.jwt.JwtTokenProvider; import com.fullcar.core.exception.NotFoundException; +import com.fullcar.core.exception.UnauthorizedException; import com.fullcar.core.response.ErrorCode; import com.fullcar.member.application.member.MemberMapper; import com.fullcar.member.domain.auth.SocialId; @@ -16,7 +17,6 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.http.*; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; @@ -94,8 +94,7 @@ private void createMember(SocialId socialId, String deviceToken, String refreshT // 회원 탈퇴 public void revoke(Member member) { - RestTemplate restTemplate = new RestTemplateBuilder().build(); - + RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); headers.set("Authorization", "KakaoAK " + adminKey); @@ -106,10 +105,14 @@ public void revoke(Member member) { HttpEntity> request = new HttpEntity<>(map, headers); - restTemplate.exchange( - KAKAO_UNLINK_ENDPOINT, - HttpMethod.POST, - request, - String.class); + try { + restTemplate.exchange( + KAKAO_UNLINK_ENDPOINT, + HttpMethod.POST, + request, + String.class); + } catch (HttpClientErrorException e) { + throw new UnauthorizedException(ErrorCode.INVALID_KAKAO_USER); + } } } From ea8dfaf94b28702dabceb603d85397ec93d461e3 Mon Sep 17 00:00:00 2001 From: Seokyeong Date: Tue, 13 Feb 2024 16:48:22 +0900 Subject: [PATCH 3/6] del: withdrawRequestDto --- .../member/application/auth/AuthService.java | 9 ++++----- .../member/application/member/MemberMapper.java | 3 +++ .../com/fullcar/member/domain/member/Member.java | 3 +++ .../{MemberSocialType.java => SocialType.java} | 2 +- .../member/presentation/auth/AuthController.java | 5 ++--- .../auth/dto/request/WithdrawRequestDto.java | 16 ---------------- 6 files changed, 13 insertions(+), 25 deletions(-) rename src/main/java/com/fullcar/member/domain/member/{MemberSocialType.java => SocialType.java} (83%) delete mode 100644 src/main/java/com/fullcar/member/presentation/auth/dto/request/WithdrawRequestDto.java diff --git a/src/main/java/com/fullcar/member/application/auth/AuthService.java b/src/main/java/com/fullcar/member/application/auth/AuthService.java index 684ca98..7db2a55 100644 --- a/src/main/java/com/fullcar/member/application/auth/AuthService.java +++ b/src/main/java/com/fullcar/member/application/auth/AuthService.java @@ -7,12 +7,11 @@ import com.fullcar.member.application.car.CarService; import com.fullcar.member.domain.member.Member; import com.fullcar.member.domain.member.MemberRepository; -import com.fullcar.member.domain.member.MemberSocialType; +import com.fullcar.member.domain.member.SocialType; import com.fullcar.member.domain.member.service.MailService; import com.fullcar.member.presentation.auth.dto.response.AuthResponseDto; import com.fullcar.member.presentation.auth.dto.response.AuthTokenResponseDto; import com.fullcar.member.presentation.auth.dto.response.SocialInfoResponseDto; -import com.fullcar.member.presentation.auth.dto.request.WithdrawRequestDto; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; @@ -62,11 +61,11 @@ public void socialLogout(Member member) { } @Transactional - public void withdrawMember(Member member, WithdrawRequestDto withdrawRequestDto) throws IOException { - if (withdrawRequestDto.getSocialType() == MemberSocialType.APPLE) { + public void withdrawMember(Member member) throws IOException { + if (member.getSocialType() == SocialType.APPLE) { appleAuthService.revoke(member); } - else if (withdrawRequestDto.getSocialType() == MemberSocialType.KAKAO) { + else if (member.getSocialType() == SocialType.KAKAO) { kakaoAuthService.revoke(member); } else { diff --git a/src/main/java/com/fullcar/member/application/member/MemberMapper.java b/src/main/java/com/fullcar/member/application/member/MemberMapper.java index 1dc9770..5f698f5 100644 --- a/src/main/java/com/fullcar/member/application/member/MemberMapper.java +++ b/src/main/java/com/fullcar/member/application/member/MemberMapper.java @@ -2,6 +2,7 @@ import com.fullcar.member.domain.auth.SocialId; import com.fullcar.member.domain.member.Company; +import com.fullcar.member.domain.member.SocialType; import com.fullcar.member.domain.member.service.MemberIdService; import com.fullcar.member.domain.member.Member; import com.fullcar.member.presentation.member.dto.request.OnBoardingRequestDto; @@ -59,6 +60,7 @@ public Member toKakaoLoginEntity(SocialId socialId, String deviceToken, String r .socialId(socialId) .deviceToken(deviceToken) .refreshToken(refreshToken) + .socialType(SocialType.KAKAO) .build(); } @@ -69,6 +71,7 @@ public Member toAppleLoginEntity(SocialId socialId, String appleRefreshToken, St .appleRefreshToken(appleRefreshToken) .deviceToken(deviceToken) .refreshToken(refreshToken) + .socialType(SocialType.APPLE) .build(); } } diff --git a/src/main/java/com/fullcar/member/domain/member/Member.java b/src/main/java/com/fullcar/member/domain/member/Member.java index 98d9862..57476ea 100644 --- a/src/main/java/com/fullcar/member/domain/member/Member.java +++ b/src/main/java/com/fullcar/member/domain/member/Member.java @@ -34,6 +34,9 @@ public class Member { private SocialId socialId; + @Enumerated(EnumType.STRING) + private SocialType socialType; + @Embedded private Company company; diff --git a/src/main/java/com/fullcar/member/domain/member/MemberSocialType.java b/src/main/java/com/fullcar/member/domain/member/SocialType.java similarity index 83% rename from src/main/java/com/fullcar/member/domain/member/MemberSocialType.java rename to src/main/java/com/fullcar/member/domain/member/SocialType.java index 6d8a238..e34871a 100644 --- a/src/main/java/com/fullcar/member/domain/member/MemberSocialType.java +++ b/src/main/java/com/fullcar/member/domain/member/SocialType.java @@ -6,7 +6,7 @@ @Getter @RequiredArgsConstructor(access = AccessLevel.PRIVATE) -public enum MemberSocialType { +public enum SocialType { KAKAO, APPLE } diff --git a/src/main/java/com/fullcar/member/presentation/auth/AuthController.java b/src/main/java/com/fullcar/member/presentation/auth/AuthController.java index 52c879f..f26fe01 100644 --- a/src/main/java/com/fullcar/member/presentation/auth/AuthController.java +++ b/src/main/java/com/fullcar/member/presentation/auth/AuthController.java @@ -13,7 +13,6 @@ import com.fullcar.member.presentation.auth.dto.response.AuthResponseDto; import com.fullcar.member.presentation.auth.dto.response.AuthTokenResponseDto; import com.fullcar.member.presentation.auth.dto.response.SocialInfoResponseDto; -import com.fullcar.member.presentation.auth.dto.request.WithdrawRequestDto; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.responses.ApiResponses; @@ -92,8 +91,8 @@ public ApiResponse socialLogout(@CurrentMember Member member) { @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "500", description = "서버 내부 오류", content = @Content) }) @DeleteMapping() - public ApiResponse withdrawMember(@CurrentMember Member member, @RequestBody WithdrawRequestDto withdrawRequestDto) throws IOException { - authService.withdrawMember(member, withdrawRequestDto); + public ApiResponse withdrawMember(@CurrentMember Member member) throws IOException { + authService.withdrawMember(member); return ApiResponse.success(SuccessCode.WITHDRAW_SUCCESS); } } diff --git a/src/main/java/com/fullcar/member/presentation/auth/dto/request/WithdrawRequestDto.java b/src/main/java/com/fullcar/member/presentation/auth/dto/request/WithdrawRequestDto.java deleted file mode 100644 index 81b2e99..0000000 --- a/src/main/java/com/fullcar/member/presentation/auth/dto/request/WithdrawRequestDto.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.fullcar.member.presentation.auth.dto.request; - -import com.fullcar.member.domain.member.MemberSocialType; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@AllArgsConstructor(access = AccessLevel.PROTECTED) -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class WithdrawRequestDto { - @Schema(description = "소셜 로그인 타입", example = "APPLE") - private MemberSocialType socialType; -} From 597f798aede25160fdac9f99239f3e1636cfb5e6 Mon Sep 17 00:00:00 2001 From: Seokyeong Date: Tue, 13 Feb 2024 21:00:02 +0900 Subject: [PATCH 4/6] feat: apple social login --- .../com/fullcar/core/response/ErrorCode.java | 4 ++-- .../application/auth/AppleAuthService.java | 21 ++++++------------- .../response/AppleAuthTokenResponseDto.java | 11 +++++----- 3 files changed, 14 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/fullcar/core/response/ErrorCode.java b/src/main/java/com/fullcar/core/response/ErrorCode.java index f7e83e3..9377ad6 100644 --- a/src/main/java/com/fullcar/core/response/ErrorCode.java +++ b/src/main/java/com/fullcar/core/response/ErrorCode.java @@ -13,7 +13,6 @@ public enum ErrorCode { /* 400 BAD REQUEST */ FAILED_TO_GENERATE_PUBLIC_KEY(BAD_REQUEST, "애플 공개키 생성 중 문제 발생"), - FAILED_TO_GENERATE_APPLE_TOKEN(BAD_REQUEST, "애플 access Token 생성 중 문제 발생"), EMAIL_ADDRESS_IN_BLACKLIST(BAD_REQUEST, "블랙리스트에 있는 이메일 주소입니다."), CANNOT_SEND_TO_OWN_CARPOOL(BAD_REQUEST, "자기자신의 카풀에는 신청할 수 없습니다."), DUPLICATED_FORM(BAD_REQUEST, "이미 요청을 보낸 카풀입니다."), @@ -32,7 +31,8 @@ public enum ErrorCode { INVALID_CLAIMS(UNAUTHORIZED, "올바르지 않은 Claim"), SIGNIN_REQUIRED(UNAUTHORIZED, "access, refreshToken 모두 만료되었습니다. 재로그인이 필요합니다."), INVALID_MEMBER(UNAUTHORIZED, "유효하지 않은 유저"), - INVALID_KAKAO_USER(UNAUTHORIZED, "이미 탈퇴되었거나 유효하지 않은 카카오 유저입니다."), + INVALID_KAKAO_USER(UNAUTHORIZED, "이미 탈퇴 처리되었거나 유효하지 않은 카카오 유저입니다."), + FAILED_TO_GENERATE_APPLE_REFRESH_TOKEN(UNAUTHORIZED, "애플 refresh Token 생성 중 문제 발생"), /* 404 NOT FOUND */ NOT_EXIST_USER(NOT_FOUND, "존재하지 않는 사용자입니다."), diff --git a/src/main/java/com/fullcar/member/application/auth/AppleAuthService.java b/src/main/java/com/fullcar/member/application/auth/AppleAuthService.java index 4273413..c0d01bd 100644 --- a/src/main/java/com/fullcar/member/application/auth/AppleAuthService.java +++ b/src/main/java/com/fullcar/member/application/auth/AppleAuthService.java @@ -4,7 +4,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fullcar.core.config.jwt.JwtTokenProvider; import com.fullcar.core.exception.BadRequestException; -import com.fullcar.core.exception.CustomException; import com.fullcar.core.exception.UnauthorizedException; import com.fullcar.core.response.ErrorCode; import com.fullcar.member.application.member.MemberMapper; @@ -19,14 +18,12 @@ import lombok.RequiredArgsConstructor; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; -import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.core.io.ClassPathResource; import org.springframework.http.*; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; -import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestTemplate; import org.springframework.beans.factory.annotation.Value; import org.bouncycastle.openssl.PEMParser; @@ -58,8 +55,8 @@ public class AppleAuthService { @Value("${apple.client-id}") private String clientId; - private static final String REQUEST_TOKEN_URL = "https://appleid.apple.com/auth/oauth2/v2/token"; - private static final String REVOKE_TOKEN_URL = "https://appleid.apple.com/auth/oauth2/v2/revoke"; + private static final String REQUEST_TOKEN_URL = "https://appleid.apple.com/auth/token"; + private static final String REVOKE_TOKEN_URL = "https://appleid.apple.com/auth/revoke"; private final ObjectMapper objectMapper; private final JwtTokenProvider jwtTokenProvider; @@ -192,7 +189,7 @@ private String createClientSecret() throws IOException { .setIssuedAt(new Date(System.currentTimeMillis())) .setExpiration(expirationDate) .setAudience("https://appleid.apple.com") - .setSubject("com.fullcar.app") + .setSubject(clientId) .signWith(SignatureAlgorithm.ES256, getPrivateKey()) .compact(); } @@ -208,10 +205,7 @@ private PrivateKey getPrivateKey() throws IOException { } public AppleAuthTokenResponseDto requestAppleAuthToken(String code) throws IOException { - String secret = createClientSecret(); - System.out.println(secret); - - RestTemplate restTemplate = new RestTemplateBuilder().build(); + RestTemplate restTemplate = new RestTemplate(); MultiValueMap params = new LinkedMultiValueMap<>(); params.add("code", code); params.add("client_id", clientId); @@ -225,18 +219,15 @@ public AppleAuthTokenResponseDto requestAppleAuthToken(String code) throws IOExc try { ResponseEntity response = restTemplate.postForEntity(REQUEST_TOKEN_URL, httpEntity, AppleAuthTokenResponseDto.class); - System.out.println(response.getBody()); return response.getBody(); } catch (Exception e) { - System.out.println(e); - throw new IllegalArgumentException("Apple token error"); - //throw new CustomException(ErrorCode.FAILED_TO_GENERATE_APPLE_TOKEN); + throw new UnauthorizedException(ErrorCode.FAILED_TO_GENERATE_APPLE_REFRESH_TOKEN); } } // 회원 탈퇴 public void revoke(Member member) throws IOException { - RestTemplate restTemplate = new RestTemplateBuilder().build(); + RestTemplate restTemplate = new RestTemplate(); MultiValueMap params = new LinkedMultiValueMap<>(); params.add("client_id", clientId); diff --git a/src/main/java/com/fullcar/member/presentation/auth/dto/response/AppleAuthTokenResponseDto.java b/src/main/java/com/fullcar/member/presentation/auth/dto/response/AppleAuthTokenResponseDto.java index 54323e9..75a9960 100644 --- a/src/main/java/com/fullcar/member/presentation/auth/dto/response/AppleAuthTokenResponseDto.java +++ b/src/main/java/com/fullcar/member/presentation/auth/dto/response/AppleAuthTokenResponseDto.java @@ -1,12 +1,13 @@ package com.fullcar.member.presentation.auth.dto.response; -import lombok.Getter; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.*; @Getter +@Builder +@AllArgsConstructor(access = AccessLevel.PROTECTED) +@NoArgsConstructor(access = AccessLevel.PROTECTED) public class AppleAuthTokenResponseDto { - private String accessToken; - private Integer expiresIn; - private String idToken; + @JsonProperty("refresh_token") private String refreshToken; - private String tokenType; } From 1a166cf460bb9a5ec284d0b136bc0f2942c2f867 Mon Sep 17 00:00:00 2001 From: Seokyeong Date: Tue, 13 Feb 2024 21:23:35 +0900 Subject: [PATCH 5/6] feat: withdraw member --- .../java/com/fullcar/member/domain/mail/MailRepository.java | 1 + src/main/java/com/fullcar/member/infra/MailClient.java | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/fullcar/member/domain/mail/MailRepository.java b/src/main/java/com/fullcar/member/domain/mail/MailRepository.java index be387c3..5531aea 100644 --- a/src/main/java/com/fullcar/member/domain/mail/MailRepository.java +++ b/src/main/java/com/fullcar/member/domain/mail/MailRepository.java @@ -7,4 +7,5 @@ @Repository public interface MailRepository extends JpaRepository { Mail findByMemberId(MemberId memberId); + boolean existsByMemberId(MemberId memberId); } diff --git a/src/main/java/com/fullcar/member/infra/MailClient.java b/src/main/java/com/fullcar/member/infra/MailClient.java index 9fa0a92..279bfc1 100644 --- a/src/main/java/com/fullcar/member/infra/MailClient.java +++ b/src/main/java/com/fullcar/member/infra/MailClient.java @@ -84,7 +84,9 @@ public void checkMailAuthenticationCode(Member member, CodeRequestDto codeReques @Transactional @Override public void deleteMail(MemberId memberId) { - Mail mail = mailRepository.findByMemberId(memberId); - mailRepository.delete(mail); + if (mailRepository.existsByMemberId(memberId)) { + Mail mail = mailRepository.findByMemberId(memberId); + mailRepository.delete(mail); + } } } From 2a01b36c86a845f440314b8d23638e6a8e1e3391 Mon Sep 17 00:00:00 2001 From: Seokyeong Date: Tue, 13 Feb 2024 21:42:34 +0900 Subject: [PATCH 6/6] add: error cases for swagger --- src/main/java/com/fullcar/core/response/ErrorCode.java | 1 - .../java/com/fullcar/member/application/auth/AuthService.java | 3 --- .../com/fullcar/member/presentation/auth/AuthController.java | 2 ++ 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/fullcar/core/response/ErrorCode.java b/src/main/java/com/fullcar/core/response/ErrorCode.java index 9377ad6..f10d5c4 100644 --- a/src/main/java/com/fullcar/core/response/ErrorCode.java +++ b/src/main/java/com/fullcar/core/response/ErrorCode.java @@ -22,7 +22,6 @@ public enum ErrorCode { INVALID_FORM_STATE(BAD_REQUEST, "유효하지 않은 신청서 상태입니다."), EXISTED_CODE_IN_MAIL(BAD_REQUEST, "이미 인증번호를 보냈습니다."), NOT_MATCHED_CODE(BAD_REQUEST, "인증번호가 일치하지 않습니다."), - INVALID_SOCIAL_TYPE(BAD_REQUEST, "유효하지 않은 소셜 로그인 타입 입니다."), /* 401 UNAUTHORIZED */ UNAUTHORIZED_KAKAO_TOKEN(UNAUTHORIZED, "유효하지 않은 카카오 토큰"), diff --git a/src/main/java/com/fullcar/member/application/auth/AuthService.java b/src/main/java/com/fullcar/member/application/auth/AuthService.java index 7db2a55..635d802 100644 --- a/src/main/java/com/fullcar/member/application/auth/AuthService.java +++ b/src/main/java/com/fullcar/member/application/auth/AuthService.java @@ -68,9 +68,6 @@ public void withdrawMember(Member member) throws IOException { else if (member.getSocialType() == SocialType.KAKAO) { kakaoAuthService.revoke(member); } - else { - throw new CustomException(ErrorCode.INVALID_SOCIAL_TYPE); - } carService.deleteCar(member.getCarId()); mailService.deleteMail(member.getId()); diff --git a/src/main/java/com/fullcar/member/presentation/auth/AuthController.java b/src/main/java/com/fullcar/member/presentation/auth/AuthController.java index f26fe01..3a6ccf2 100644 --- a/src/main/java/com/fullcar/member/presentation/auth/AuthController.java +++ b/src/main/java/com/fullcar/member/presentation/auth/AuthController.java @@ -37,6 +37,7 @@ public class AuthController { @ApiResponses(value = { @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "애플 소셜 로그인 성공"), @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "애플 공개키 생성 중 문제 발생", content = @Content), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "401", description = "애플 refresh Token 생성 중 문제 발생", content = @Content), @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "500", description = "서버 내부 오류", content = @Content) }) @PostMapping("/login/apple") @@ -88,6 +89,7 @@ public ApiResponse socialLogout(@CurrentMember Member member) { @Operation(summary = "회원 탈퇴 API") @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "탈퇴 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "401", description = "이미 탈퇴 처리되었거나 유효하지 않은 카카오 유저입니다.", content = @Content), @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "500", description = "서버 내부 오류", content = @Content) }) @DeleteMapping()