From 3a95e19d83bf5ffb50157d9880b84feefc5df809 Mon Sep 17 00:00:00 2001 From: min-0 Date: Fri, 25 Oct 2024 19:29:57 +0900 Subject: [PATCH] =?UTF-8?q?:rewind:=20=EC=95=A0=ED=94=8C=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20=EB=90=98=EB=8F=8C=EB=A6=AC=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/controller/AuthController.java | 4 +- .../auth/service/AppleOAuthService.java | 59 +++++++++++-------- 2 files changed, 35 insertions(+), 28 deletions(-) diff --git a/src/main/java/com/dnd/dndtravel/auth/controller/AuthController.java b/src/main/java/com/dnd/dndtravel/auth/controller/AuthController.java index f886432..b41e3df 100644 --- a/src/main/java/com/dnd/dndtravel/auth/controller/AuthController.java +++ b/src/main/java/com/dnd/dndtravel/auth/controller/AuthController.java @@ -32,7 +32,7 @@ public class AuthController implements AuthControllerSwagger { public ResponseEntity appleOAuthLogin(@Valid @RequestBody AppleLoginRequest appleLoginRequest) { // 클라이언트에서 준 code 값으로 apple의 IdToken Payload를 얻어온다 AppleSocialTokenInfoResponse tokenInfo = appleOAuthService.getTokenInfo(appleLoginRequest.appleToken()); - AppleIdTokenPayload tokenPayload = TokenDecoder.decodePayload(tokenInfo.idToken(), AppleIdTokenPayload.class); + AppleIdTokenPayload tokenPayload = appleOAuthService.get(appleLoginRequest.appleToken()); // apple에서 가져온 유저정보를 DB에 저장 Member member = memberService.saveMember(tokenPayload.email(), appleLoginRequest.selectedColor()); @@ -53,7 +53,7 @@ public ReissueTokenResponse reissueToken(@Valid @RequestBody ReIssueTokenRequest return jwtTokenService.reIssue(reissueTokenRequest.refreshToken()); } - @DeleteMapping("/withdraw") + @PostMapping("/withdraw") public void withdraw(@Valid @RequestBody AppleWithdrawRequest withdrawRequest, AuthenticationMember authenticationMember) { // 애플 서버에 탈퇴 요청 appleOAuthService.revoke(withdrawRequest.appleRefreshToken()); diff --git a/src/main/java/com/dnd/dndtravel/auth/service/AppleOAuthService.java b/src/main/java/com/dnd/dndtravel/auth/service/AppleOAuthService.java index 9cd4c19..8c0098a 100644 --- a/src/main/java/com/dnd/dndtravel/auth/service/AppleOAuthService.java +++ b/src/main/java/com/dnd/dndtravel/auth/service/AppleOAuthService.java @@ -1,9 +1,13 @@ package com.dnd.dndtravel.auth.service; +import com.dnd.dndtravel.auth.controller.request.AppleRevokeRequest; import com.dnd.dndtravel.auth.exception.AppleTokenRevokeException; import com.dnd.dndtravel.auth.service.dto.response.AppleSocialTokenInfoResponse; import io.jsonwebtoken.JwsHeader; import io.jsonwebtoken.Jwts; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -20,46 +24,49 @@ import com.dnd.dndtravel.auth.service.dto.response.AppleIdTokenPayload; import com.dnd.dndtravel.auth.config.AppleProperties; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; /** - * private key와 기타 설정값들로 client secret을 생성한다 - * client_secret: 개발자가 생성한 Secret JWT 토큰, 개발자 계정과 연결된 Apple로 로그인 개인 키를 사용, authorization code와 refresh token 검증 요청에 해당 파라미터 필요 - * client_secret을 만드는 관련 docs - * - https://developer.apple.com/documentation/accountorganizationaldatasharing/creating-a-client-secret - * - * clinet_secret jwt 토큰 디코딩 예시 형식 - * { - * //JWT 헤더 - * "alg": "ES256", // 토큰에 서명된 알고리즘 - * "kid": "ABC123DEFG" // 개발자 계정과 연결된 계정 + private key 로 만들어진 식별자 - * } - * { - * "iss": "DEF123GHIJ",// 팀ID - * "iat": 1437179036, // - * "exp": 1493298100, // 만료시간 - * "aud": "https://appleid.apple.com", - * "sub": "com.mytest.app" - * } + * private key와 기타 설정값들로 client secret을 생성한다 client_secret: 개발자가 생성한 Secret JWT 토큰, 개발자 계정과 연결된 Apple로 로그인 개인 키를 사용, + * authorization code와 refresh token 검증 요청에 해당 파라미터 필요 client_secret을 만드는 관련 docs - + * https://developer.apple.com/documentation/accountorganizationaldatasharing/creating-a-client-secret + *

+ * clinet_secret jwt 토큰 디코딩 예시 형식 { //JWT 헤더 "alg": "ES256", // 토큰에 서명된 알고리즘 "kid": "ABC123DEFG" // 개발자 계정과 연결된 계정 + + * private key 로 만들어진 식별자 } { "iss": "DEF123GHIJ",// 팀ID "iat": 1437179036, // "exp": 1493298100, // 만료시간 "aud": + * "https://appleid.apple.com", "sub": "com.mytest.app" } */ @RequiredArgsConstructor @Component +@Slf4j public class AppleOAuthService { private final AppleClient appleClient; private final AppleProperties appleProperties; + public AppleIdTokenPayload get(String authorizationCode) { + String idToken = appleClient.getIdToken( + appleProperties.getClientId(), + generateClientSecret(), + appleProperties.getGrantType(), + authorizationCode + ).idToken(); + + return TokenDecoder.decodePayload(idToken, AppleIdTokenPayload.class); + } + private String generateClientSecret() { LocalDateTime expiration = LocalDateTime.now().plusMinutes(5); return Jwts.builder() - .header().add(JwsHeader.KEY_ID, appleProperties.getKeyId()).and() - .issuer(appleProperties.getTeamId()) - .audience().add(appleProperties.getAudience()).and() - .subject(appleProperties.getClientId()) - .expiration(Date.from(expiration.atZone(ZoneId.systemDefault()).toInstant())) - .issuedAt(new Date()) - .signWith(getPrivateKey()) - .compact(); + .header().add(JwsHeader.KEY_ID, appleProperties.getKeyId()).and() + .issuer(appleProperties.getTeamId()) + .audience().add(appleProperties.getAudience()).and() + .subject(appleProperties.getClientId()) + .expiration(Date.from(expiration.atZone(ZoneId.systemDefault()).toInstant())) + .issuedAt(new Date()) + .signWith(getPrivateKey()) + .compact(); } private PrivateKey getPrivateKey() {