From a4a6096823f8529fe3131b72ab0c0a8da65a4a6e Mon Sep 17 00:00:00 2001 From: Hyunseok Ko Date: Thu, 2 May 2024 00:01:51 +0900 Subject: [PATCH 1/4] =?UTF-8?q?Chore=20|=20#4=20|=20@lcomment=20|=20client?= =?UTF-8?q?=20=EB=AA=A8=EB=93=88=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cakk-client/build.gradle | 16 ++++++++++++++++ settings.gradle | 7 ++++--- 2 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 cakk-client/build.gradle diff --git a/cakk-client/build.gradle b/cakk-client/build.gradle new file mode 100644 index 00000000..eaf7fb1c --- /dev/null +++ b/cakk-client/build.gradle @@ -0,0 +1,16 @@ +description = 'client module' + +dependencies { + implementation project(':cakk-common') + + implementation('org.springframework.boot:spring-boot-starter-webflux:3.1.2') + implementation('com.google.api-client:google-api-client-jackson2:2.2.0') + implementation('com.google.api-client:google-api-client:2.2.0') +} + +bootJar { + enabled = false +} +jar { + enabled = true +} diff --git a/settings.gradle b/settings.gradle index 91302cbc..8f49223a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,7 +1,8 @@ rootProject.name = 'cakk' include( - 'cakk-api', - 'cakk-domain', - 'cakk-common' + 'cakk-api', + 'cakk-client', + 'cakk-domain', + 'cakk-common' ) From de2ccdfd6611e3b7310e668309354ca3de8db05e Mon Sep 17 00:00:00 2001 From: Hyunseok Ko Date: Thu, 2 May 2024 00:02:21 +0900 Subject: [PATCH 2/4] =?UTF-8?q?Refactor=20|=20#4=20|=20@lcomment=20|=20?= =?UTF-8?q?=EB=AA=A8=EB=93=88=20=EC=A3=BC=EC=9E=85=20=EC=96=91=EC=8B=9D=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cakk-api/build.gradle | 4 ++-- cakk-domain/build.gradle | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cakk-api/build.gradle b/cakk-api/build.gradle index ab8bfb49..3fe68ea5 100644 --- a/cakk-api/build.gradle +++ b/cakk-api/build.gradle @@ -1,8 +1,8 @@ description = "api module" dependencies { - implementation(project(':cakk-common')) - implementation(project(':cakk-domain')) + implementation project(':cakk-common') + implementation project(':cakk-domain') // basic implementation('org.springframework.boot:spring-boot-starter-web') diff --git a/cakk-domain/build.gradle b/cakk-domain/build.gradle index e8cd537a..d5320fe4 100644 --- a/cakk-domain/build.gradle +++ b/cakk-domain/build.gradle @@ -1,7 +1,7 @@ description = "domain module" dependencies { - implementation(project(':cakk-common')) + implementation project(':cakk-common') // jpa implementation 'org.springframework.boot:spring-boot-starter-data-jpa' From 5d6040c6f5e9a18728691b3b01e760e919becdb9 Mon Sep 17 00:00:00 2001 From: Hyunseok Ko Date: Thu, 2 May 2024 00:02:43 +0900 Subject: [PATCH 3/4] =?UTF-8?q?feature=20|=20#4=20|=20@lcomment=20|=20OAut?= =?UTF-8?q?h=20=EA=B4=80=EB=A0=A8=20HttpClient=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cakk/client/config/WebClientConfig.java | 30 +++++++++++++++++++ .../com/cakk/client/vo/OidcPublicKey.java | 11 +++++++ .../com/cakk/client/vo/OidcPublicKeyList.java | 19 ++++++++++++ .../com/cakk/client/web/AppleAuthClient.java | 29 ++++++++++++++++++ .../client/web/GoogleAuthConfiguration.java | 29 ++++++++++++++++++ .../com/cakk/client/web/KakaoAuthClient.java | 29 ++++++++++++++++++ .../src/main/resources/client-local.yml | 7 +++++ .../com/cakk/common/enums/ReturnCode.java | 6 +++- 8 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 cakk-client/src/main/java/com/cakk/client/config/WebClientConfig.java create mode 100644 cakk-client/src/main/java/com/cakk/client/vo/OidcPublicKey.java create mode 100644 cakk-client/src/main/java/com/cakk/client/vo/OidcPublicKeyList.java create mode 100644 cakk-client/src/main/java/com/cakk/client/web/AppleAuthClient.java create mode 100644 cakk-client/src/main/java/com/cakk/client/web/GoogleAuthConfiguration.java create mode 100644 cakk-client/src/main/java/com/cakk/client/web/KakaoAuthClient.java create mode 100644 cakk-client/src/main/resources/client-local.yml diff --git a/cakk-client/src/main/java/com/cakk/client/config/WebClientConfig.java b/cakk-client/src/main/java/com/cakk/client/config/WebClientConfig.java new file mode 100644 index 00000000..596376fd --- /dev/null +++ b/cakk-client/src/main/java/com/cakk/client/config/WebClientConfig.java @@ -0,0 +1,30 @@ +package com.cakk.client.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.reactive.ReactorClientHttpConnector; +import org.springframework.web.reactive.function.client.WebClient; + +import reactor.netty.http.client.HttpClient; + +import io.netty.channel.ChannelOption; +import io.netty.handler.timeout.ReadTimeoutHandler; +import io.netty.handler.timeout.WriteTimeoutHandler; + +@Configuration +public class WebClientConfig { + + @Bean + public WebClient webClient() { + HttpClient httpClient = HttpClient.create() + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 30000) + .doOnConnected(connection -> { + connection.addHandlerLast(new ReadTimeoutHandler(10)); + connection.addHandlerLast(new WriteTimeoutHandler(10)); + }); + + return WebClient.builder() + .clientConnector(new ReactorClientHttpConnector(httpClient)) + .build(); + } +} diff --git a/cakk-client/src/main/java/com/cakk/client/vo/OidcPublicKey.java b/cakk-client/src/main/java/com/cakk/client/vo/OidcPublicKey.java new file mode 100644 index 00000000..982af548 --- /dev/null +++ b/cakk-client/src/main/java/com/cakk/client/vo/OidcPublicKey.java @@ -0,0 +1,11 @@ +package com.cakk.client.vo; + +public record OidcPublicKey( + String kid, + String kty, + String alg, + String use, + String n, + String e +) { +} diff --git a/cakk-client/src/main/java/com/cakk/client/vo/OidcPublicKeyList.java b/cakk-client/src/main/java/com/cakk/client/vo/OidcPublicKeyList.java new file mode 100644 index 00000000..cc2fd7b3 --- /dev/null +++ b/cakk-client/src/main/java/com/cakk/client/vo/OidcPublicKeyList.java @@ -0,0 +1,19 @@ +package com.cakk.client.vo; + +import static com.cakk.common.enums.ReturnCode.*; + +import java.util.List; + +import com.cakk.common.exception.CakkException; + +public record OidcPublicKeyList( + List keys +) { + + public OidcPublicKey getMatchedKey(String kid, String alg) { + return keys.stream() + .filter(key -> key.kid().equals(kid) && key.alg().equals(alg)) + .findAny() + .orElseThrow(() -> new CakkException(EXTERNAL_SERVER_ERROR)); + } +} diff --git a/cakk-client/src/main/java/com/cakk/client/web/AppleAuthClient.java b/cakk-client/src/main/java/com/cakk/client/web/AppleAuthClient.java new file mode 100644 index 00000000..ab012324 --- /dev/null +++ b/cakk-client/src/main/java/com/cakk/client/web/AppleAuthClient.java @@ -0,0 +1,29 @@ +package com.cakk.client.web; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.client.WebClient; + +import lombok.RequiredArgsConstructor; + +import com.cakk.client.vo.OidcPublicKeyList; + +@Component +@RequiredArgsConstructor +public class AppleAuthClient { + + private final WebClient webClient; + + @Value("${oauth.apple.public-key-url}") + private final String publicKeyUrl; + + public OidcPublicKeyList getPublicKeys() { + return webClient.mutate() + .baseUrl(publicKeyUrl) + .build() + .get() + .retrieve() + .bodyToMono(OidcPublicKeyList.class) + .block(); + } +} diff --git a/cakk-client/src/main/java/com/cakk/client/web/GoogleAuthConfiguration.java b/cakk-client/src/main/java/com/cakk/client/web/GoogleAuthConfiguration.java new file mode 100644 index 00000000..71494ad1 --- /dev/null +++ b/cakk-client/src/main/java/com/cakk/client/web/GoogleAuthConfiguration.java @@ -0,0 +1,29 @@ +package com.cakk.client.web; + +import java.util.Collections; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.gson.GsonFactory; + +import lombok.RequiredArgsConstructor; + +@Configuration +@RequiredArgsConstructor +public class GoogleAuthConfiguration { + + @Value("${oauth.google.client-id}") + private String googleClientId; + + @Bean + public GoogleIdTokenVerifier googleIdTokenVerifier() { + return new GoogleIdTokenVerifier + .Builder(new NetHttpTransport(), new GsonFactory()) + .setAudience(Collections.singletonList(googleClientId)) + .build(); + } +} diff --git a/cakk-client/src/main/java/com/cakk/client/web/KakaoAuthClient.java b/cakk-client/src/main/java/com/cakk/client/web/KakaoAuthClient.java new file mode 100644 index 00000000..b160aa90 --- /dev/null +++ b/cakk-client/src/main/java/com/cakk/client/web/KakaoAuthClient.java @@ -0,0 +1,29 @@ +package com.cakk.client.web; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.client.WebClient; + +import lombok.RequiredArgsConstructor; + +import com.cakk.client.vo.OidcPublicKeyList; + +@Component +@RequiredArgsConstructor +public class KakaoAuthClient { + + private final WebClient webClient; + + @Value("${oauth.kakao.public-key-url}") + private final String publicKeyUrl; + + public OidcPublicKeyList getPublicKeys() { + return webClient.mutate() + .baseUrl(publicKeyUrl) + .build() + .get() + .retrieve() + .bodyToMono(OidcPublicKeyList.class) + .block(); + } +} diff --git a/cakk-client/src/main/resources/client-local.yml b/cakk-client/src/main/resources/client-local.yml new file mode 100644 index 00000000..9bb8694a --- /dev/null +++ b/cakk-client/src/main/resources/client-local.yml @@ -0,0 +1,7 @@ +oauth: + kakao: + public-key-info: https://kauth.kakao.com/.well-known/jwks.json + apple: + public-key-url: https://appleid.apple.com/auth/keys + google: + client-id: ${GOOGLE_CLIENT_ID} diff --git a/cakk-common/src/main/java/com/cakk/common/enums/ReturnCode.java b/cakk-common/src/main/java/com/cakk/common/enums/ReturnCode.java index 42963837..989ef3bd 100644 --- a/cakk-common/src/main/java/com/cakk/common/enums/ReturnCode.java +++ b/cakk-common/src/main/java/com/cakk/common/enums/ReturnCode.java @@ -7,7 +7,11 @@ @RequiredArgsConstructor public enum ReturnCode { - SUCCESS("1000", "요청에 성공하셨습니다."); + SUCCESS("1000", "요청에 성공하셨습니다."), + + // 서버 에러 (9998, 9999) + INTERNAL_SERVER_ERROR("9998", "내부 서버 에러 입니다."), + EXTERNAL_SERVER_ERROR("9999", "외부 서버 에러 입니다."); private final String code; private final String message; From 83c2f124cf57575bf8da335839cdd2c3fdb8a338 Mon Sep 17 00:00:00 2001 From: Hyunseok Ko Date: Thu, 2 May 2024 11:55:34 +0900 Subject: [PATCH 4/4] =?UTF-8?q?Fix=20|=20#4=20|=20@lcomment=20|=20OAuth=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20RestClient=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cakk-client/build.gradle | 2 +- .../cakk/client/config/RestClientConfig.java | 23 ++++++++++++++ .../cakk/client/config/WebClientConfig.java | 30 ------------------- .../com/cakk/client/web/AppleAuthClient.java | 13 ++++---- .../com/cakk/client/web/KakaoAuthClient.java | 13 ++++---- .../com/cakk/domain/entity/user/User.java | 7 ++++- 6 files changed, 40 insertions(+), 48 deletions(-) create mode 100644 cakk-client/src/main/java/com/cakk/client/config/RestClientConfig.java delete mode 100644 cakk-client/src/main/java/com/cakk/client/config/WebClientConfig.java diff --git a/cakk-client/build.gradle b/cakk-client/build.gradle index eaf7fb1c..6b1098b8 100644 --- a/cakk-client/build.gradle +++ b/cakk-client/build.gradle @@ -3,7 +3,7 @@ description = 'client module' dependencies { implementation project(':cakk-common') - implementation('org.springframework.boot:spring-boot-starter-webflux:3.1.2') + implementation('org.springframework.boot:spring-boot-starter-web') implementation('com.google.api-client:google-api-client-jackson2:2.2.0') implementation('com.google.api-client:google-api-client:2.2.0') } diff --git a/cakk-client/src/main/java/com/cakk/client/config/RestClientConfig.java b/cakk-client/src/main/java/com/cakk/client/config/RestClientConfig.java new file mode 100644 index 00000000..88f397b4 --- /dev/null +++ b/cakk-client/src/main/java/com/cakk/client/config/RestClientConfig.java @@ -0,0 +1,23 @@ +package com.cakk.client.config; + +import java.time.Duration; + +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestClient; +import org.springframework.web.client.RestTemplate; + +@Configuration +public class RestClientConfig { + + @Bean + public RestClient restClient() { + RestTemplate restTemplate = new RestTemplateBuilder() + .setConnectTimeout(Duration.ofSeconds(10)) + .setReadTimeout(Duration.ofSeconds(5)) + .build(); + + return RestClient.create(restTemplate); + } +} diff --git a/cakk-client/src/main/java/com/cakk/client/config/WebClientConfig.java b/cakk-client/src/main/java/com/cakk/client/config/WebClientConfig.java deleted file mode 100644 index 596376fd..00000000 --- a/cakk-client/src/main/java/com/cakk/client/config/WebClientConfig.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.cakk.client.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.client.reactive.ReactorClientHttpConnector; -import org.springframework.web.reactive.function.client.WebClient; - -import reactor.netty.http.client.HttpClient; - -import io.netty.channel.ChannelOption; -import io.netty.handler.timeout.ReadTimeoutHandler; -import io.netty.handler.timeout.WriteTimeoutHandler; - -@Configuration -public class WebClientConfig { - - @Bean - public WebClient webClient() { - HttpClient httpClient = HttpClient.create() - .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 30000) - .doOnConnected(connection -> { - connection.addHandlerLast(new ReadTimeoutHandler(10)); - connection.addHandlerLast(new WriteTimeoutHandler(10)); - }); - - return WebClient.builder() - .clientConnector(new ReactorClientHttpConnector(httpClient)) - .build(); - } -} diff --git a/cakk-client/src/main/java/com/cakk/client/web/AppleAuthClient.java b/cakk-client/src/main/java/com/cakk/client/web/AppleAuthClient.java index ab012324..d1c0f17b 100644 --- a/cakk-client/src/main/java/com/cakk/client/web/AppleAuthClient.java +++ b/cakk-client/src/main/java/com/cakk/client/web/AppleAuthClient.java @@ -2,7 +2,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; -import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.client.RestClient; import lombok.RequiredArgsConstructor; @@ -12,18 +12,15 @@ @RequiredArgsConstructor public class AppleAuthClient { - private final WebClient webClient; + private final RestClient restClient; @Value("${oauth.apple.public-key-url}") private final String publicKeyUrl; public OidcPublicKeyList getPublicKeys() { - return webClient.mutate() - .baseUrl(publicKeyUrl) - .build() - .get() + return restClient.get() + .uri(publicKeyUrl) .retrieve() - .bodyToMono(OidcPublicKeyList.class) - .block(); + .body(OidcPublicKeyList.class); } } diff --git a/cakk-client/src/main/java/com/cakk/client/web/KakaoAuthClient.java b/cakk-client/src/main/java/com/cakk/client/web/KakaoAuthClient.java index b160aa90..3ae11372 100644 --- a/cakk-client/src/main/java/com/cakk/client/web/KakaoAuthClient.java +++ b/cakk-client/src/main/java/com/cakk/client/web/KakaoAuthClient.java @@ -2,7 +2,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; -import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.client.RestClient; import lombok.RequiredArgsConstructor; @@ -12,18 +12,15 @@ @RequiredArgsConstructor public class KakaoAuthClient { - private final WebClient webClient; + private final RestClient restClient; @Value("${oauth.kakao.public-key-url}") private final String publicKeyUrl; public OidcPublicKeyList getPublicKeys() { - return webClient.mutate() - .baseUrl(publicKeyUrl) - .build() - .get() + return restClient.get() + .uri(publicKeyUrl) .retrieve() - .bodyToMono(OidcPublicKeyList.class) - .block(); + .body(OidcPublicKeyList.class); } } diff --git a/cakk-domain/src/main/java/com/cakk/domain/entity/user/User.java b/cakk-domain/src/main/java/com/cakk/domain/entity/user/User.java index 8f8bba91..560c5060 100644 --- a/cakk-domain/src/main/java/com/cakk/domain/entity/user/User.java +++ b/cakk-domain/src/main/java/com/cakk/domain/entity/user/User.java @@ -45,7 +45,10 @@ public class User extends AuditEntity { @Column(name = "nickname", length = 20, nullable = false) private String nickname; - @Column(name = "email", length = 20, nullable = false) + @Column(name = "profile_image_url", length = 200) + private String profileImageUrl; + + @Column(name = "email", length = 50, nullable = false) private String email; @Enumerated(value = EnumType.STRING) @@ -68,6 +71,7 @@ public User( Provider provider, String providerId, String nickname, + String profileImageUrl, String email, Gender gender, LocalDate birthday, @@ -76,6 +80,7 @@ public User( this.provider = provider; this.providerId = providerId; this.nickname = nickname; + this.profileImageUrl = profileImageUrl; this.email = email; this.gender = gender; this.birthday = birthday;