From e90d87fa0acd084c51d83144f39804cfe82120bc Mon Sep 17 00:00:00 2001 From: juns1s Date: Wed, 29 Nov 2023 21:41:02 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=EA=B5=AC=EA=B8=80=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20accessToken=EC=9D=B4=20=EC=95=84=EB=8B=8C=20credent?= =?UTF-8?q?ials=EB=A1=9C=20=EC=A0=91=EA=B7=BC=ED=95=98=EB=8F=84=EB=A1=9D?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 + .../tripai/member/dto/GoogleDataDto.java | 11 --- .../tripai/member/service/OAuth2Service.java | 80 +++++++++++-------- .../member/service/OAuth2ServiceTest.java | 4 +- 4 files changed, 50 insertions(+), 47 deletions(-) delete mode 100644 src/main/java/com/milkcow/tripai/member/dto/GoogleDataDto.java diff --git a/build.gradle b/build.gradle index da0fd60..0fd8a9b 100644 --- a/build.gradle +++ b/build.gradle @@ -49,6 +49,8 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-validation:2.7.5' implementation "com.querydsl:querydsl-jpa:${queryDslVersion}" annotationProcessor "com.querydsl:querydsl-apt:${queryDslVersion}" + + implementation 'com.google.api-client:google-api-client:1.30.10' } tasks.named('test') { diff --git a/src/main/java/com/milkcow/tripai/member/dto/GoogleDataDto.java b/src/main/java/com/milkcow/tripai/member/dto/GoogleDataDto.java deleted file mode 100644 index 63eec85..0000000 --- a/src/main/java/com/milkcow/tripai/member/dto/GoogleDataDto.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.milkcow.tripai.member.dto; - -import lombok.AllArgsConstructor; -import lombok.Data; - -@Data -@AllArgsConstructor -public class GoogleDataDto { - private String nickname; - private String email; -} diff --git a/src/main/java/com/milkcow/tripai/member/service/OAuth2Service.java b/src/main/java/com/milkcow/tripai/member/service/OAuth2Service.java index e131924..a6f9fa6 100644 --- a/src/main/java/com/milkcow/tripai/member/service/OAuth2Service.java +++ b/src/main/java/com/milkcow/tripai/member/service/OAuth2Service.java @@ -1,30 +1,32 @@ package com.milkcow.tripai.member.service; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken; +import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier; +import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier.Builder; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.jackson2.JacksonFactory; import com.milkcow.tripai.global.dto.ResponseDto; import com.milkcow.tripai.global.exception.GeneralException; import com.milkcow.tripai.global.result.ApiResult; import com.milkcow.tripai.jwt.JwtService; import com.milkcow.tripai.member.domain.Member; -import com.milkcow.tripai.member.dto.GoogleDataDto; import com.milkcow.tripai.member.dto.MemberSignupRequestDto; import com.milkcow.tripai.member.exception.OAuth2Exception; import com.milkcow.tripai.member.repository.MemberRepository; import com.milkcow.tripai.member.result.OAuth2Result; import com.milkcow.tripai.security.MemberAdapter; -import java.util.Objects; +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.util.Collections; import java.util.Optional; import java.util.UUID; import javax.servlet.http.HttpServletResponse; +import lombok.Data; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.http.ResponseEntity; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.client.RestClientException; -import org.springframework.web.client.RestTemplate; @Service @RequiredArgsConstructor @@ -34,6 +36,14 @@ public class OAuth2Service { private final MemberRepository memberRepository; private final JwtService jwtService; private final MemberService memberService; + private static final NetHttpTransport transport = new NetHttpTransport(); + private static final JacksonFactory jsonFactory = new JacksonFactory(); + @Value("${OAuth2.Google-Client-Id}") + private String clientId; + private final GoogleIdTokenVerifier verifier = + new Builder(transport, jsonFactory) + .setAudience(Collections.singletonList(clientId)) + .build(); /** * google OAuth2 로그인 진행 회원가입 되어있지 않은 경우 회원가입 진행 @@ -41,8 +51,9 @@ public class OAuth2Service { * @param token (String, accessToken) * @param response (ResponseDto) */ + @Transactional public ResponseDto oAuth2Login(String token, HttpServletResponse response) { - GoogleDataDto googleData = getGoogleData(token); + GoogleData googleData = getGoogleDataFromToken(token); String email = googleData.getEmail(); Optional optionalMember = memberRepository.findByEmail(email); @@ -78,38 +89,39 @@ private void sendAccessAndRefreshToken(HttpServletResponse response, MemberAdapt } /** - * getGoogleData

프론트엔드로 부터 받은 Google OAuth2 access_token을 바탕으로 회원 정보 조회. + * 프론트엔드로 부터 받은 Google OAuth2 credential 바탕으로 회원 정보 추출 * - * @param token (프론트엔드로 부터 받은 Google OAuth2 access_token) + * @param token (프론트엔드로 부터 받은 Google OAuth2 credential) * @return GoogleDataDto */ - private GoogleDataDto getGoogleData(String token) { - try { - RestTemplate restTemplate = new RestTemplate(); - //구글에 정보 요청 - ResponseEntity responseEntity = restTemplate.getForEntity( - "https://www.googleapis.com/oauth2/v1/userinfo?access_token=" - + token, - String.class - ); + private GoogleData getGoogleDataFromToken(String token) { + try{ +// GoogleIdToken idToken = verifier.verify(token); + GoogleIdToken idToken = GoogleIdToken.parse(new JacksonFactory(), token); - String responseBody = responseEntity.getBody(); - ObjectMapper objectMapper = new ObjectMapper(); - JsonNode jsonNode = objectMapper.readTree(responseBody); - - //response body로 부터 정보 추출 - String nickname = jsonNode.get("name").asText(); - String email = jsonNode.get("email").asText(); - return new GoogleDataDto(nickname, email); - } catch (RestClientException e) { - //유효하지 않은 토큰의 경우 - if (Objects.requireNonNull(e.getMessage()).startsWith("401")) { + if(idToken == null){ throw new OAuth2Exception(OAuth2Result.INVALID_ACCESS_TOKEN); - } else { - throw new OAuth2Exception(OAuth2Result.FAIL_TO_ACCESS_GOOGLE_API); } - } catch (JsonProcessingException e) { + GoogleIdToken.Payload payload = idToken.getPayload(); + String nickname = (String) payload.get("name"); + String email = payload.getEmail(); + + return new GoogleData(email, nickname); + } catch (IOException e) { throw new GeneralException(ApiResult.INTERNAL_SERVER_ERROR); + } catch (IllegalArgumentException e){ + throw new OAuth2Exception(OAuth2Result.INVALID_ACCESS_TOKEN); + } + } + + @Data + private class GoogleData { + public String email; + public String nickname; + + public GoogleData(String email, String nickname) { + this.email = email; + this.nickname = nickname; } } } diff --git a/src/test/java/com/milkcow/tripai/member/service/OAuth2ServiceTest.java b/src/test/java/com/milkcow/tripai/member/service/OAuth2ServiceTest.java index 5d5284f..79f5193 100644 --- a/src/test/java/com/milkcow/tripai/member/service/OAuth2ServiceTest.java +++ b/src/test/java/com/milkcow/tripai/member/service/OAuth2ServiceTest.java @@ -28,9 +28,9 @@ class OAuth2ServiceTest { //when oAuth2Service.oAuth2Login(token, response); //then - Member member = memberRepository.findByEmail("junjuns1s1s@gmail.com").get(); + Member member = memberRepository.findByEmail("0902hdy@gmail.com").get(); System.out.println("member.getNickname() = " + member.getNickname()); - assertThat(member.getEmail()).isEqualTo("junjuns1s1s@gmail.com"); + assertThat(member.getEmail()).isEqualTo("0902hdy@gmail.com"); } @Test public void 구글_로그인() throws Exception{