11package com .pinback .application .google .service ;
22
3+ import java .util .List ;
4+
35import org .springframework .beans .factory .annotation .Qualifier ;
46import org .springframework .http .MediaType ;
57import org .springframework .stereotype .Service ;
1012import com .pinback .application .common .exception .GoogleNameMissingException ;
1113import com .pinback .application .common .exception .GoogleProfileImageMissingException ;
1214import com .pinback .application .common .exception .GoogleTokenMissingException ;
15+ import com .pinback .application .common .exception .InvalidGoogleUriException ;
1316import com .pinback .application .google .dto .response .GoogleApiResponse ;
1417import com .pinback .application .google .dto .response .GoogleTokenResponse ;
1518import com .pinback .application .google .dto .response .GoogleUserInfoResponse ;
@@ -24,21 +27,21 @@ public class GoogleOAuthClient implements GoogleOAuthPort {
2427 private final WebClient googleWebClient ;
2528 private final String googleClientId ;
2629 private final String googleClientSecret ;
27- private final String googleRedirectUri ;
30+ private final List < String > googleRedirectUris ;
2831 private final String googleTokenUri ;
2932 private final String googleUserInfoUri ;
3033
3134 public GoogleOAuthClient (
3235 WebClient googleWebClient ,
3336 @ Qualifier ("googleClientId" ) String googleClientId ,
3437 @ Qualifier ("googleClientSecret" ) String googleClientSecret ,
35- @ Qualifier ("googleRedirectUri " ) String googleRedirectUri ,
38+ @ Qualifier ("googleRedirectUris " ) List < String > googleRedirectUris ,
3639 @ Qualifier ("googleTokenUri" ) String googleTokenUri ,
3740 @ Qualifier ("googleUserInfoUri" ) String googleUserInfoUri ) {
3841 this .googleWebClient = googleWebClient ;
3942 this .googleClientId = googleClientId ;
4043 this .googleClientSecret = googleClientSecret ;
41- this .googleRedirectUri = googleRedirectUri ;
44+ this .googleRedirectUris = googleRedirectUris ;
4245 this .googleTokenUri = googleTokenUri ;
4346 this .googleUserInfoUri = googleUserInfoUri ;
4447 }
@@ -61,12 +64,65 @@ public Mono<GoogleUserInfoResponse> fetchUserInfo(String code) {
6164 });
6265 }
6366
67+ @ Override
68+ public Mono <GoogleUserInfoResponse > fetchUserInfoV3 (String code , String uri ) {
69+
70+ return requestAccessTokenV3 (code , uri )
71+ // 토큰 응답을 UserInfo 요청으로 변환하여 연결
72+ .flatMap (tokenResponse -> {
73+
74+ // Access Token 유효성 검증
75+ if (tokenResponse == null || tokenResponse .accessToken () == null ) {
76+ log .info ("tokenResponse: {}" , tokenResponse );
77+ log .error ("Google Access Token 획득 실패: 응답 본문에 토큰이 없습니다. Code: {}" , code );
78+ return Mono .error (new GoogleTokenMissingException ());
79+ }
80+ // Access Token으로 사용자 정보 요청
81+ return getUserInfo (tokenResponse .accessToken ());
82+ });
83+ }
84+
6485 private Mono <GoogleTokenResponse > requestAccessToken (String code ) {
65- log .info ("redirect: {}" , googleRedirectUri );
86+ String firstRedirectUri = googleRedirectUris .getFirst ();
87+ log .info ("redirect: {}" , firstRedirectUri );
88+ String requestBody = "code=" + code +
89+ "&client_id=" + googleClientId +
90+ "&client_secret=" + googleClientSecret +
91+ "&redirect_uri=" + firstRedirectUri +
92+ "&grant_type=authorization_code" ;
93+
94+ return googleWebClient .post ()
95+ .uri (googleTokenUri )
96+ .contentType (MediaType .APPLICATION_FORM_URLENCODED )
97+ .bodyValue (requestBody )
98+ .retrieve ()
99+ // HTTP 오류 발생 시
100+ .onStatus (status -> status .isError (), clientResponse ->
101+ clientResponse .bodyToMono (String .class )
102+ .flatMap (body -> {
103+ String errorLog = String .format (
104+ "[GoogleOAuth API 에러] HTTP Status: %s, Detail: %s" ,
105+ clientResponse .statusCode (), body
106+ );
107+ log .error (errorLog );
108+ return Mono .error (new GoogleApiException ());
109+ })
110+ )
111+ .bodyToMono (GoogleTokenResponse .class );
112+ }
113+
114+ private Mono <GoogleTokenResponse > requestAccessTokenV3 (String code , String uri ) {
115+ if (!googleRedirectUris .contains (uri )) {
116+ log .error ("허용되지 않은 Redirect URI 요청: {}" , uri );
117+
118+ return Mono .error (new InvalidGoogleUriException ());
119+ }
120+
121+ log .info ("redirect: {}" , uri );
66122 String requestBody = "code=" + code +
67123 "&client_id=" + googleClientId +
68124 "&client_secret=" + googleClientSecret +
69- "&redirect_uri=" + googleRedirectUri +
125+ "&redirect_uri=" + uri +
70126 "&grant_type=authorization_code" ;
71127
72128 return googleWebClient .post ()
0 commit comments