From bff422df80cd6082f4ad4f026579bf974574fc42 Mon Sep 17 00:00:00 2001 From: Juhyeon Lee Date: Mon, 9 Feb 2026 17:06:18 +0900 Subject: [PATCH 1/2] =?UTF-8?q?[FIX]=20=EB=A1=9C=EC=BB=AC/=EB=B0=B0?= =?UTF-8?q?=ED=8F=AC=20=ED=99=98=EA=B2=BD=20=EB=8C=80=EC=9D=91=EC=9D=84=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20OAuth2=20=EB=A6=AC=EB=8B=A4=EC=9D=B4?= =?UTF-8?q?=EB=A0=89=ED=8A=B8=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/member/controller/MemberController.java | 4 ++-- .../backend/api/member/dto/LoginRequestDTO.java | 1 + .../api/member/service/GoogleOAuthService.java | 10 +++++++--- .../backend/api/member/service/KakaoOAuthService.java | 10 +++++++--- .../backend/api/member/service/MemberService.java | 11 +++++------ 5 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/moongeul/backend/api/member/controller/MemberController.java b/src/main/java/com/moongeul/backend/api/member/controller/MemberController.java index 827a738..95ef895 100644 --- a/src/main/java/com/moongeul/backend/api/member/controller/MemberController.java +++ b/src/main/java/com/moongeul/backend/api/member/controller/MemberController.java @@ -47,7 +47,7 @@ public class MemberController { @PostMapping("/google/login") public ResponseEntity> loginWithGoogle(@Valid @RequestBody LoginRequestDTO loginRequestDTO) { - LoginResponseDTO response = memberService.loginWithGoogle(loginRequestDTO.getCode()); + LoginResponseDTO response = memberService.loginWithGoogle(loginRequestDTO.getCode(), loginRequestDTO.getRedirectUri()); return ApiResponse.success(SuccessStatus.SEND_LOGIN_SUCCESS, response); } @@ -64,7 +64,7 @@ public ResponseEntity> loginWithGoogle(@Valid @Req @PostMapping("/kakao/login") public ResponseEntity> loginWithKakao(@Valid @RequestBody LoginRequestDTO loginRequestDTO) { - LoginResponseDTO response = memberService.loginWithKakao(loginRequestDTO.getCode()); + LoginResponseDTO response = memberService.loginWithKakao(loginRequestDTO.getCode(), loginRequestDTO.getRedirectUri()); return ApiResponse.success(SuccessStatus.SEND_LOGIN_SUCCESS, response); } diff --git a/src/main/java/com/moongeul/backend/api/member/dto/LoginRequestDTO.java b/src/main/java/com/moongeul/backend/api/member/dto/LoginRequestDTO.java index fee1a86..9a6f437 100644 --- a/src/main/java/com/moongeul/backend/api/member/dto/LoginRequestDTO.java +++ b/src/main/java/com/moongeul/backend/api/member/dto/LoginRequestDTO.java @@ -8,4 +8,5 @@ public class LoginRequestDTO { @NotBlank(message = "인가코드가 입력되지 않았습니다.") private String code; // 인가코드 + private String redirectUri; // 리다이렉트 uri } diff --git a/src/main/java/com/moongeul/backend/api/member/service/GoogleOAuthService.java b/src/main/java/com/moongeul/backend/api/member/service/GoogleOAuthService.java index 5319b6a..018796e 100644 --- a/src/main/java/com/moongeul/backend/api/member/service/GoogleOAuthService.java +++ b/src/main/java/com/moongeul/backend/api/member/service/GoogleOAuthService.java @@ -33,10 +33,10 @@ public class GoogleOAuthService { @Value("${spring.security.oauth2.client.registration.google.client-secret}") private String clientSecret; @Value("${spring.security.oauth2.client.registration.google.redirect-uri}") - private String redirectUri; + private String defaultRedirectUri; // Google 토큰 획득 로직 (WebClient 방식으로 수정 - 비동기 방식 구현) - public AccessTokenResponseDTO getGoogleToken(String code) { + public AccessTokenResponseDTO getGoogleToken(String code, String redirectUri) { String decodedCode; try { @@ -54,7 +54,11 @@ public AccessTokenResponseDTO getGoogleToken(String code) { params.add("code", decodedCode); params.add("client_id", clientId); params.add("client_secret", clientSecret); - params.add("redirect_uri", redirectUri); + + // 프론트에서 보낸 redirectUri가 있으면 그것을 사용하고, 없으면 설정 파일의 기본값을 사용 + String finalRedirectUri = (redirectUri != null && !redirectUri.isBlank()) ? redirectUri : defaultRedirectUri; + + params.add("redirect_uri", finalRedirectUri); params.add("grant_type", "authorization_code"); // 인가 코드를 토큰으로 교환함을 명시 return webClient.post() diff --git a/src/main/java/com/moongeul/backend/api/member/service/KakaoOAuthService.java b/src/main/java/com/moongeul/backend/api/member/service/KakaoOAuthService.java index 2b4d761..46599eb 100644 --- a/src/main/java/com/moongeul/backend/api/member/service/KakaoOAuthService.java +++ b/src/main/java/com/moongeul/backend/api/member/service/KakaoOAuthService.java @@ -30,17 +30,21 @@ public class KakaoOAuthService { @Value("${spring.security.oauth2.client.registration.kakao.client-secret}") private String clientSecret; @Value("${spring.security.oauth2.client.registration.kakao.redirect-uri}") - private String redirectUri; + private String defaultRedirectUri; // Kakao 토큰 획득 로직 - public AccessTokenResponseDTO getKakaoToken(String code){ + public AccessTokenResponseDTO getKakaoToken(String code, String redirectUri){ // HTTP Body 생성 MultiValueMap params = new LinkedMultiValueMap<>(); params.add("grant_type", "authorization_code"); params.add("client_id", clientId); params.add("client_secret", clientSecret); - params.add("redirect_uri", redirectUri); + + // 프론트에서 보낸 redirectUri가 있으면 그것을 사용하고, 없으면 설정 파일의 기본값을 사용 + String finalRedirectUri = (redirectUri != null && !redirectUri.isBlank()) ? redirectUri : defaultRedirectUri; + + params.add("redirect_uri", finalRedirectUri); params.add("code", code); return webClient.post() diff --git a/src/main/java/com/moongeul/backend/api/member/service/MemberService.java b/src/main/java/com/moongeul/backend/api/member/service/MemberService.java index cc5b655..33ed739 100644 --- a/src/main/java/com/moongeul/backend/api/member/service/MemberService.java +++ b/src/main/java/com/moongeul/backend/api/member/service/MemberService.java @@ -55,10 +55,10 @@ public class MemberService { // 인가코드 받아 JWT로 교환 및 회원가입/로그인 처리 @Transactional - public LoginResponseDTO loginWithGoogle(String code){ + public LoginResponseDTO loginWithGoogle(String code, String redirectUri){ // 1. 인가 코드로 Google Access Token 및 사용자 정보 획득 - AccessTokenResponseDTO tokenDTO = googleOAuthService.getGoogleToken(code); + AccessTokenResponseDTO tokenDTO = googleOAuthService.getGoogleToken(code, redirectUri); GoogleInfoResponseDTO userInfo = googleOAuthService.getGoogleUserInfo(tokenDTO.getAccessToken()); // 2. 사용자 정보 추출 @@ -89,9 +89,9 @@ public LoginResponseDTO loginWithGoogle(String code){ } @Transactional - public LoginResponseDTO loginWithKakao(String code){ + public LoginResponseDTO loginWithKakao(String code, String redirectUri){ - AccessTokenResponseDTO tokenDTO = kakaoOAuthService.getKakaoToken(code); + AccessTokenResponseDTO tokenDTO = kakaoOAuthService.getKakaoToken(code, redirectUri); KakaoInfoResponseDTO userInfo = kakaoOAuthService.getKakaoUserInfo(tokenDTO.getAccessToken()); // 2. 사용자 정보 추출 @@ -138,9 +138,8 @@ private Member signUp(String socialId, String email, String name, String picture .socialType(socialType) .role(Role.GUEST) // 이후 필요 정보 모두 입력 시 USER 로 승격 .build(); - Member savedMember = memberRepository.save(newUser); - return savedMember; + return memberRepository.save(newUser); } // 사용자 정보 조회 From 9d0a7315a8ec39988721682bccfbdab1dd6257d1 Mon Sep 17 00:00:00 2001 From: Juhyeon Lee Date: Wed, 11 Feb 2026 15:14:21 +0900 Subject: [PATCH 2/2] =?UTF-8?q?[FIX]=20=EB=A1=9C=EC=BB=AC/=EB=B0=B0?= =?UTF-8?q?=ED=8F=AC=20=ED=99=98=EA=B2=BD=20=EB=8C=80=EC=9D=91=EC=9D=84=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20OAuth2=20=EB=A6=AC=EB=8B=A4=EC=9D=B4?= =?UTF-8?q?=EB=A0=89=ED=8A=B8=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?(=ED=95=84=EB=93=9C=20type=EC=9C=BC=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/member/controller/MemberController.java | 11 +++++++---- .../backend/api/member/dto/LoginRequestDTO.java | 2 +- .../api/member/service/GoogleOAuthService.java | 17 +++++++++-------- .../api/member/service/KakaoOAuthService.java | 14 ++++++++------ .../api/member/service/MemberService.java | 8 ++++---- 5 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/moongeul/backend/api/member/controller/MemberController.java b/src/main/java/com/moongeul/backend/api/member/controller/MemberController.java index 95ef895..186e95c 100644 --- a/src/main/java/com/moongeul/backend/api/member/controller/MemberController.java +++ b/src/main/java/com/moongeul/backend/api/member/controller/MemberController.java @@ -36,7 +36,8 @@ public class MemberController { @Operation( summary = "구글 로그인 API", description = "구글 인가코드을 통해 사용자의 정보를 등록 및 토큰 + 역할을 발급합니다. " + - "

[enum]ROLE -> 처음사용자 : GUEST, 일반사용자 : USER, 관리자 : ADMIN" + "
- type: 환경에 따라 local 또는 deploy를 보내주세요" + + "
- [enum]ROLE -> 처음사용자 : GUEST, 일반사용자 : USER, 관리자 : ADMIN" ) @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "로그인 성공"), @@ -47,13 +48,15 @@ public class MemberController { @PostMapping("/google/login") public ResponseEntity> loginWithGoogle(@Valid @RequestBody LoginRequestDTO loginRequestDTO) { - LoginResponseDTO response = memberService.loginWithGoogle(loginRequestDTO.getCode(), loginRequestDTO.getRedirectUri()); + LoginResponseDTO response = memberService.loginWithGoogle(loginRequestDTO.getCode(), loginRequestDTO.getType()); return ApiResponse.success(SuccessStatus.SEND_LOGIN_SUCCESS, response); } @Operation( summary = "카카오 로그인 API", - description = "카카오 인가코드을 통해 사용자의 정보를 등록 및 토큰 + 역할을 발급합니다. (ROLE -> 처음사용자 : GUEST, 일반사용자 : USER, 관리자 : ADMIN)" + description = "카카오 인가코드을 통해 사용자의 정보를 등록 및 토큰 + 역할을 발급합니다." + + "
- type: 환경에 따라 local 또는 deploy를 보내주세요" + + "
- [enum]ROLE -> 처음사용자 : GUEST, 일반사용자 : USER, 관리자 : ADMIN" ) @ApiResponses({ @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "로그인 성공"), @@ -64,7 +67,7 @@ public ResponseEntity> loginWithGoogle(@Valid @Req @PostMapping("/kakao/login") public ResponseEntity> loginWithKakao(@Valid @RequestBody LoginRequestDTO loginRequestDTO) { - LoginResponseDTO response = memberService.loginWithKakao(loginRequestDTO.getCode(), loginRequestDTO.getRedirectUri()); + LoginResponseDTO response = memberService.loginWithKakao(loginRequestDTO.getCode(), loginRequestDTO.getType()); return ApiResponse.success(SuccessStatus.SEND_LOGIN_SUCCESS, response); } diff --git a/src/main/java/com/moongeul/backend/api/member/dto/LoginRequestDTO.java b/src/main/java/com/moongeul/backend/api/member/dto/LoginRequestDTO.java index 9a6f437..a59ce24 100644 --- a/src/main/java/com/moongeul/backend/api/member/dto/LoginRequestDTO.java +++ b/src/main/java/com/moongeul/backend/api/member/dto/LoginRequestDTO.java @@ -8,5 +8,5 @@ public class LoginRequestDTO { @NotBlank(message = "인가코드가 입력되지 않았습니다.") private String code; // 인가코드 - private String redirectUri; // 리다이렉트 uri + private String type; // local, deploy } diff --git a/src/main/java/com/moongeul/backend/api/member/service/GoogleOAuthService.java b/src/main/java/com/moongeul/backend/api/member/service/GoogleOAuthService.java index 018796e..c6475f3 100644 --- a/src/main/java/com/moongeul/backend/api/member/service/GoogleOAuthService.java +++ b/src/main/java/com/moongeul/backend/api/member/service/GoogleOAuthService.java @@ -32,11 +32,14 @@ public class GoogleOAuthService { private String clientId; @Value("${spring.security.oauth2.client.registration.google.client-secret}") private String clientSecret; - @Value("${spring.security.oauth2.client.registration.google.redirect-uri}") - private String defaultRedirectUri; + + @Value("${oauth-config.google.local}") + private String localRedirectUri; + @Value("${oauth-config.google.deploy}") + private String deployRedirectUri; // Google 토큰 획득 로직 (WebClient 방식으로 수정 - 비동기 방식 구현) - public AccessTokenResponseDTO getGoogleToken(String code, String redirectUri) { + public AccessTokenResponseDTO getGoogleToken(String code, String type) { String decodedCode; try { @@ -48,17 +51,15 @@ public AccessTokenResponseDTO getGoogleToken(String code, String redirectUri) { decodedCode = code; } + String redirectUri = "deploy".equalsIgnoreCase(type) ? deployRedirectUri : localRedirectUri; + // ... (실제 Google OAuth 2.0 /token 엔드포인트 통신 로직 구현 필요) // HTTP Body에 전송할 파라미터 담기 MultiValueMap params = new LinkedMultiValueMap<>(); params.add("code", decodedCode); params.add("client_id", clientId); params.add("client_secret", clientSecret); - - // 프론트에서 보낸 redirectUri가 있으면 그것을 사용하고, 없으면 설정 파일의 기본값을 사용 - String finalRedirectUri = (redirectUri != null && !redirectUri.isBlank()) ? redirectUri : defaultRedirectUri; - - params.add("redirect_uri", finalRedirectUri); + params.add("redirect_uri", redirectUri); params.add("grant_type", "authorization_code"); // 인가 코드를 토큰으로 교환함을 명시 return webClient.post() diff --git a/src/main/java/com/moongeul/backend/api/member/service/KakaoOAuthService.java b/src/main/java/com/moongeul/backend/api/member/service/KakaoOAuthService.java index 46599eb..93a02c6 100644 --- a/src/main/java/com/moongeul/backend/api/member/service/KakaoOAuthService.java +++ b/src/main/java/com/moongeul/backend/api/member/service/KakaoOAuthService.java @@ -29,11 +29,14 @@ public class KakaoOAuthService { private String clientId; @Value("${spring.security.oauth2.client.registration.kakao.client-secret}") private String clientSecret; - @Value("${spring.security.oauth2.client.registration.kakao.redirect-uri}") - private String defaultRedirectUri; + + @Value("${oauth-config.google.local}") + private String localRedirectUri; + @Value("${oauth-config.google.deploy}") + private String deployRedirectUri; // Kakao 토큰 획득 로직 - public AccessTokenResponseDTO getKakaoToken(String code, String redirectUri){ + public AccessTokenResponseDTO getKakaoToken(String code, String type){ // HTTP Body 생성 MultiValueMap params = new LinkedMultiValueMap<>(); @@ -41,10 +44,9 @@ public AccessTokenResponseDTO getKakaoToken(String code, String redirectUri){ params.add("client_id", clientId); params.add("client_secret", clientSecret); - // 프론트에서 보낸 redirectUri가 있으면 그것을 사용하고, 없으면 설정 파일의 기본값을 사용 - String finalRedirectUri = (redirectUri != null && !redirectUri.isBlank()) ? redirectUri : defaultRedirectUri; + String redirectUri = "deploy".equalsIgnoreCase(type) ? deployRedirectUri : localRedirectUri; - params.add("redirect_uri", finalRedirectUri); + params.add("redirect_uri", redirectUri); params.add("code", code); return webClient.post() diff --git a/src/main/java/com/moongeul/backend/api/member/service/MemberService.java b/src/main/java/com/moongeul/backend/api/member/service/MemberService.java index 33ed739..94d0e8a 100644 --- a/src/main/java/com/moongeul/backend/api/member/service/MemberService.java +++ b/src/main/java/com/moongeul/backend/api/member/service/MemberService.java @@ -55,10 +55,10 @@ public class MemberService { // 인가코드 받아 JWT로 교환 및 회원가입/로그인 처리 @Transactional - public LoginResponseDTO loginWithGoogle(String code, String redirectUri){ + public LoginResponseDTO loginWithGoogle(String code, String type){ // 1. 인가 코드로 Google Access Token 및 사용자 정보 획득 - AccessTokenResponseDTO tokenDTO = googleOAuthService.getGoogleToken(code, redirectUri); + AccessTokenResponseDTO tokenDTO = googleOAuthService.getGoogleToken(code, type); GoogleInfoResponseDTO userInfo = googleOAuthService.getGoogleUserInfo(tokenDTO.getAccessToken()); // 2. 사용자 정보 추출 @@ -89,9 +89,9 @@ public LoginResponseDTO loginWithGoogle(String code, String redirectUri){ } @Transactional - public LoginResponseDTO loginWithKakao(String code, String redirectUri){ + public LoginResponseDTO loginWithKakao(String code, String type){ - AccessTokenResponseDTO tokenDTO = kakaoOAuthService.getKakaoToken(code, redirectUri); + AccessTokenResponseDTO tokenDTO = kakaoOAuthService.getKakaoToken(code, type); KakaoInfoResponseDTO userInfo = kakaoOAuthService.getKakaoUserInfo(tokenDTO.getAccessToken()); // 2. 사용자 정보 추출