diff --git a/src/main/java/org/hansung/zigma/global/oauth/CookieOAuth2AuthorizationRequestRepository.java b/src/main/java/org/hansung/zigma/global/oauth/CookieOAuth2AuthorizationRequestRepository.java index 8a3b25c..0d54cd9 100644 --- a/src/main/java/org/hansung/zigma/global/oauth/CookieOAuth2AuthorizationRequestRepository.java +++ b/src/main/java/org/hansung/zigma/global/oauth/CookieOAuth2AuthorizationRequestRepository.java @@ -12,6 +12,9 @@ public class CookieOAuth2AuthorizationRequestRepository implements AuthorizationRequestRepository { private static final String COOKIE_NAME = "oauth2_auth_request"; + public static final String REDIRECT_TARGET_COOKIE = "redirect_target"; + public static final String TARGET_LOCAL = "local"; + public static final String TARGET_DEPLOY = "deploy"; private static final int COOKIE_EXPIRE_SECONDS = 180; // 3분 // 쿠키에서 Authorization Request 조회 @@ -30,10 +33,19 @@ public void saveAuthorizationRequest( HttpServletResponse response) { if (authorizationRequest == null) { CookieUtils.deleteCookie(request, response, COOKIE_NAME); + CookieUtils.deleteCookie(request, response, REDIRECT_TARGET_COOKIE); return; } CookieUtils.addCookie(response, COOKIE_NAME, CookieUtils.serialize(authorizationRequest), COOKIE_EXPIRE_SECONDS); + + // Referer 헤더로 출발지(local/deploy) 판단 후 쿠키 저장 + // contains 대신 startsWith로 호스트 부분만 검사 (http://attacker.com/localhost 같은 케이스 차단) + String referer = request.getHeader("Referer"); + boolean isLocal = referer != null + && (referer.startsWith("http://localhost") || referer.startsWith("https://localhost")); + String target = isLocal ? TARGET_LOCAL : TARGET_DEPLOY; + CookieUtils.addCookie(response, REDIRECT_TARGET_COOKIE, target, COOKIE_EXPIRE_SECONDS); } // 쿠키에서 Authorization Request 꺼내고 삭제 @@ -43,6 +55,7 @@ public OAuth2AuthorizationRequest removeAuthorizationRequest( HttpServletResponse response) { OAuth2AuthorizationRequest authorizationRequest = loadAuthorizationRequest(request); CookieUtils.deleteCookie(request, response, COOKIE_NAME); + // REDIRECT_TARGET_COOKIE는 SuccessHandler에서 사용 후 삭제 return authorizationRequest; } } diff --git a/src/main/java/org/hansung/zigma/global/oauth/OAuth2LoginSuccessHandler.java b/src/main/java/org/hansung/zigma/global/oauth/OAuth2LoginSuccessHandler.java index 940a230..6880d66 100644 --- a/src/main/java/org/hansung/zigma/global/oauth/OAuth2LoginSuccessHandler.java +++ b/src/main/java/org/hansung/zigma/global/oauth/OAuth2LoginSuccessHandler.java @@ -1,10 +1,12 @@ package org.hansung.zigma.global.oauth; +import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import org.hansung.zigma.global.jwt.CustomUserDetails; import org.hansung.zigma.global.jwt.JwtTokenProvider; +import org.hansung.zigma.global.util.CookieUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; @@ -20,8 +22,11 @@ public class OAuth2LoginSuccessHandler extends SimpleUrlAuthenticationSuccessHan private final JwtTokenProvider jwtTokenProvider; - @Value("${app.oauth2.front-redirect-uri}") - private String redirectUri; + @Value("${app.oauth2.front-redirect-uri.local}") + private String localRedirectUri; + + @Value("${app.oauth2.front-redirect-uri.deploy}") + private String deployRedirectUri; @Override public void onAuthenticationSuccess( @@ -34,6 +39,17 @@ public void onAuthenticationSuccess( userDetails.getUser().getId().toString() ); + // 출발지(local/deploy) 쿠키 보고 리다이렉트 URI 선택, 누락 시 deploy 폴백 + String target = CookieUtils.getCookie(request, + CookieOAuth2AuthorizationRequestRepository.REDIRECT_TARGET_COOKIE) + .map(Cookie::getValue) + .orElse(CookieOAuth2AuthorizationRequestRepository.TARGET_DEPLOY); + String redirectUri = CookieOAuth2AuthorizationRequestRepository.TARGET_LOCAL.equals(target) + ? localRedirectUri : deployRedirectUri; + + CookieUtils.deleteCookie(request, response, + CookieOAuth2AuthorizationRequestRepository.REDIRECT_TARGET_COOKIE); + String targetUrl = UriComponentsBuilder.fromUriString(redirectUri) .queryParam("accessToken", accessToken) .build().toUriString(); diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index e50f234..a6946ea 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -20,7 +20,8 @@ jwt.access.expiration = ${JWT_ACCESS_EXPIRATION} jwt.refresh.expiration = ${JWT_REFRESH_EXPIRATION} # Frontend -app.oauth2.front-redirect-uri=https://z-igma.vercel.app//oauth/callback +app.oauth2.front-redirect-uri.local=http://localhost:5173/oauth/callback +app.oauth2.front-redirect-uri.deploy=https://z-igma.vercel.app/oauth/callback # Web Push web-push.vapid-public-key=${WEB_PUSH_VAPID_PUBLIC_KEY:}