From 2a66772bfa28544635ff07ccc99d0dc73ea08ceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=B5=9C=EC=A7=80=EC=B2=A0?= Date: Tue, 6 Jan 2026 09:46:27 +0900 Subject: [PATCH] =?UTF-8?q?=EC=BF=A0=ED=82=A4=20=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/cs/app/api/proxy/[...url]/route.ts | 9 +++- .../common/components/src/ui/header/index.tsx | 43 ++++++++++++++++--- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/apps/cs/app/api/proxy/[...url]/route.ts b/apps/cs/app/api/proxy/[...url]/route.ts index 7442c702f..abd3ae007 100644 --- a/apps/cs/app/api/proxy/[...url]/route.ts +++ b/apps/cs/app/api/proxy/[...url]/route.ts @@ -60,13 +60,18 @@ async function handler( [AUTH_USER_ID]: userId, }); + const forwardedHost = request.headers.get("x-forwarded-host"); + const host = request.headers.get("host"); + const actualHost = forwardedHost || host || new URL(request.url).hostname.toString(); + // 운영 환경에서 domain 설정 + const domain = actualHost.includes("hasuon.or.kr") ? ".hasuon.or.kr" : actualHost; if (refreshToken) { cookieStore.set(REFRESH_TOKEN, refreshToken, { httpOnly: true, - sameSite: "lax", -// domain: domain, + sameSite: "strict", + domain: domain, path: "/", }); } diff --git a/packages/common/components/src/ui/header/index.tsx b/packages/common/components/src/ui/header/index.tsx index 97ed4c151..15b431b6a 100644 --- a/packages/common/components/src/ui/header/index.tsx +++ b/packages/common/components/src/ui/header/index.tsx @@ -72,22 +72,51 @@ export function Header({ viewOnly }: { viewOnly?: boolean }) { }); if (!response.ok) throw new Error("Failed to logout"); - // 쿠키 삭제 + const actualHost = window.location.hostname; + + // 서브도메인 쿠키 삭제를 위한 루트 도메인 추출 + const getRootDomain = (hostname: string): string => { + // localhost나 IP 주소인 경우 + if (hostname === "localhost" || /^\d+\.\d+\.\d+\.\d+$/.test(hostname)) { + return hostname; + } + + // hasuon.or.kr 도메인인 경우 + if (hostname.includes("hasuon.or.kr")) { + return ".hasuon.or.kr"; + } + + // 일반적인 도메인의 경우 루트 도메인 추출 (예: sub.example.com → .example.com) + const parts = hostname.split("."); + if (parts.length >= 2) { + // 마지막 두 부분을 사용 (예: example.com) + return `.${parts.slice(-2).join(".")}`; + } + + return hostname; + }; + + const domain = getRootDomain(actualHost); + const cookieOptions = domain.startsWith(".") || domain === "localhost" + ? { domain } + : {}; + + // 쿠키 삭제 (서브도메인 포함) if (appConfig.AUTH_USER_ID) { - removeCookie(appConfig.AUTH_USER_ID); + removeCookie(appConfig.AUTH_USER_ID, cookieOptions); } if (appConfig.REFRESH_TOKEN) { - removeCookie(appConfig.REFRESH_TOKEN); + removeCookie(appConfig.REFRESH_TOKEN, cookieOptions); } if (appConfig.ACCESS_TOKEN) { - removeCookie(appConfig.ACCESS_TOKEN); + removeCookie(appConfig.ACCESS_TOKEN, cookieOptions); } if (appConfig.CLAIM_NAME) { - removeCookie(appConfig.CLAIM_NAME); + removeCookie(appConfig.CLAIM_NAME, cookieOptions); } - removeCookie("site-id-key"); - removeCookie("site-theme-key"); + removeCookie("site-id-key", cookieOptions); + removeCookie("site-theme-key", cookieOptions); window.location.href = "/auth/login"; } catch (error) {