diff --git a/src/main/java/com/universe/uni/controller/AuthController.java b/src/main/java/com/universe/uni/controller/AuthController.java index 77e3b37..604da5f 100644 --- a/src/main/java/com/universe/uni/controller/AuthController.java +++ b/src/main/java/com/universe/uni/controller/AuthController.java @@ -35,10 +35,15 @@ public AuthTokenDto authByGoogle(@RequestBody AuthRequestDto request) { return authService.authWithGoogle(request.code()); } - @GetMapping("kakao/callback") - public AuthRequestDto redirectKakaoAuth(@RequestParam(name = "code") String authenticationCode) { - return new AuthRequestDto(authenticationCode); - } + @PostMapping("apple") + public AuthTokenDto authByApple(@RequestBody AuthRequestDto request) { + return authService.authWithAppleUser(request.code()); + } + + @GetMapping("kakao/callback") + public AuthRequestDto redirectKakaoAuth(@RequestParam(name = "code") String authenticationCode) { + return new AuthRequestDto(authenticationCode); + } @GetMapping("google/callback") public AuthRequestDto redirectGoogleAuth(@RequestParam(name = "code") String authenticationCode) { diff --git a/src/main/java/com/universe/uni/domain/ApplePayload.java b/src/main/java/com/universe/uni/domain/ApplePayload.java new file mode 100644 index 0000000..a08ccbf --- /dev/null +++ b/src/main/java/com/universe/uni/domain/ApplePayload.java @@ -0,0 +1,29 @@ +package com.universe.uni.domain; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public record ApplePayload( + @JsonProperty("aud") + String aud, + @JsonProperty("auth_time") + Long authTime, + @JsonProperty("c_hash") + String cHash, + @JsonProperty("email") + String email, + @JsonProperty("email_verified") + String emailVerified, + @JsonProperty("exp") + Long exp, + @JsonProperty("iat") + Long iat, + @JsonProperty("is_private_email") + String isPrivateEmail, + @JsonProperty("iss") + String iss, + @JsonProperty("nonce_supported") + Boolean nonceSupported, + @JsonProperty("sub") + String sub +) { +} diff --git a/src/main/java/com/universe/uni/domain/AppleTokenDecodeManager.java b/src/main/java/com/universe/uni/domain/AppleTokenDecodeManager.java new file mode 100644 index 0000000..68113a9 --- /dev/null +++ b/src/main/java/com/universe/uni/domain/AppleTokenDecodeManager.java @@ -0,0 +1,31 @@ +package com.universe.uni.domain; + +import java.util.Base64; + +import org.springframework.stereotype.Component; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.universe.uni.exception.UnauthorizedException; +import com.universe.uni.exception.dto.ErrorType; + +@Component +public class AppleTokenDecodeManager implements AppleTokenManager { + + @Override + public String decodeEmail(String token) { + String[] encodedToken = token.split("\\."); + String encodedPayload = encodedToken[1]; + Base64.Decoder decoder = Base64.getDecoder(); + String payLoad = new String(decoder.decode(encodedPayload)); + + ObjectMapper mapper = new ObjectMapper(); + ApplePayload applePayload = null; + try { + applePayload = mapper.readValue(payLoad, ApplePayload.class); + } catch (JsonProcessingException e) { + throw new UnauthorizedException(ErrorType.UNSUPPORTED_TOKEN); + } + return applePayload.email(); + } +} diff --git a/src/main/java/com/universe/uni/domain/AppleTokenManager.java b/src/main/java/com/universe/uni/domain/AppleTokenManager.java new file mode 100644 index 0000000..365c8e1 --- /dev/null +++ b/src/main/java/com/universe/uni/domain/AppleTokenManager.java @@ -0,0 +1,8 @@ +package com.universe.uni.domain; + +import com.fasterxml.jackson.core.JsonProcessingException; + +public interface AppleTokenManager { + + String decodeEmail(String token); +} diff --git a/src/main/java/com/universe/uni/service/AuthService.java b/src/main/java/com/universe/uni/service/AuthService.java index bbd7979..d25a529 100644 --- a/src/main/java/com/universe/uni/service/AuthService.java +++ b/src/main/java/com/universe/uni/service/AuthService.java @@ -4,12 +4,14 @@ import org.springframework.stereotype.Service; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.universe.uni.domain.AppleTokenManager; import com.universe.uni.domain.SnsType; import com.universe.uni.domain.entity.User; import com.universe.uni.dto.AuthTokenDto; -import com.universe.uni.external.response.GoogleAccessTokenResponse; +import com.universe.uni.exception.ApiException; +import com.universe.uni.exception.dto.ErrorType; import com.universe.uni.external.response.GoogleUserInfoResponse; -import com.universe.uni.external.response.KakaoAuthResponse; import com.universe.uni.external.response.KakaoUserResponse; import com.universe.uni.repository.GoogleRepository; import com.universe.uni.repository.KakaoRepository; @@ -25,6 +27,7 @@ public class AuthService implements AuthServiceContract { private final KakaoRepository kakaoRepository; private final GoogleRepository googleRepository; private final UserRepository userRepository; + private final AppleTokenManager appleTokenManager; @Override @Transactional @@ -58,6 +61,22 @@ private User registerGoogleUser(GoogleUserInfoResponse googleUser) { .build(); } + @Override + @Transactional + public AuthTokenDto authWithAppleUser(String identityToken) { + final String userEmail = appleTokenManager.decodeEmail(identityToken); + final User user = userRepository.findBySnsAuthCode(userEmail) + .orElseGet(() -> userRepository.save(registerAppleUser(userEmail))); + return beIssuedAuthToken(user.getId()); + } + + private User registerAppleUser(String email) { + return User.builder() + .snsType(SnsType.APPLE) + .snsAuthCode(email) + .build(); + } + private AuthTokenDto beIssuedAuthToken(long userId) { return jwtManager.issueToken(userId); } diff --git a/src/main/java/com/universe/uni/service/AuthServiceContract.java b/src/main/java/com/universe/uni/service/AuthServiceContract.java index 0345002..094ff5c 100644 --- a/src/main/java/com/universe/uni/service/AuthServiceContract.java +++ b/src/main/java/com/universe/uni/service/AuthServiceContract.java @@ -10,4 +10,7 @@ public interface AuthServiceContract { @Transactional AuthTokenDto authWithGoogle(String accessToken); + + @Transactional + AuthTokenDto authWithAppleUser(String identityToken); }