logout 수정정
This commit is contained in:
@@ -9,10 +9,31 @@ import {
|
||||
|
||||
export async function POST() {
|
||||
const cookieStore = await cookies();
|
||||
|
||||
// 백엔드에 로그아웃 알림 (토큰 블랙리스트 처리)
|
||||
const refreshToken = cookieStore.get(REFRESH_TOKEN)?.value;
|
||||
|
||||
if (refreshToken) {
|
||||
try {
|
||||
// ⭐ Spring Boot 백엔드에 로그아웃 요청
|
||||
await fetch(`${process.env.NEXT_PUBLIC_SERVER_API_URL}/api/auth/logout`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Cookie": `${REFRESH_TOKEN}=${refreshToken}`,
|
||||
},
|
||||
// credentials: "include", // fetch에서는 직접 쿠키 전달
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Backend logout failed:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Next.js 쿠키 삭제
|
||||
cookieStore.delete(ACCESS_TOKEN);
|
||||
cookieStore.delete(REFRESH_TOKEN);
|
||||
cookieStore.delete(AUTH_USER_ID);
|
||||
cookieStore.delete(CLAIM_NAME);
|
||||
return NextResponse.json({ message: "Logged out" }, { status: 200 });
|
||||
}
|
||||
|
||||
return NextResponse.json({ message: "Logged out" }, { status: 200 });
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AUTH_USER_ID, CLAIM_NAME } from "@/shared/config";
|
||||
import { ACCESS_TOKEN, AUTH_USER_ID, CLAIM_NAME, REFRESH_TOKEN } from "@/shared/config";
|
||||
import { getCookie, setCookie, removeCookie } from "@/shared/lib";
|
||||
|
||||
export class TokenManager {
|
||||
@@ -76,6 +76,8 @@ export class TokenManager {
|
||||
|
||||
this.removeToken(CLAIM_NAME);
|
||||
this.removeToken(AUTH_USER_ID);
|
||||
this.removeToken(REFRESH_TOKEN);
|
||||
this.removeToken(ACCESS_TOKEN);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,99 @@ export function Header({ viewOnly }: { viewOnly?: boolean }) {
|
||||
queryFn: () => getSiteList(),
|
||||
enabled: isLoggedIn && !viewOnly,
|
||||
});
|
||||
|
||||
const logout = async () => {
|
||||
try {
|
||||
// 1. 백엔드 API 로그아웃 호출
|
||||
const response = await fetch("/api/auth/logout", {
|
||||
method: "POST",
|
||||
credentials: "include", // ⭐ 쿠키 포함 중요!
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
console.error("Logout API failed");
|
||||
// API 실패해도 계속 진행
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Logout error:", error);
|
||||
// 에러가 나도 계속 진행
|
||||
} finally {
|
||||
// 2. 클라이언트 쿠키 삭제 (백업)
|
||||
clearClientCookies();
|
||||
|
||||
// 3. 로컬/세션 스토리지 정리
|
||||
if (typeof window !== "undefined") {
|
||||
localStorage.clear();
|
||||
sessionStorage.clear();
|
||||
}
|
||||
|
||||
// 4. 로그인 페이지로 리다이렉트
|
||||
window.location.href = "/auth/login";
|
||||
}
|
||||
};
|
||||
|
||||
// 쿠키 삭제 헬퍼 함수
|
||||
const clearClientCookies = () => {
|
||||
const actualHost = window.location.hostname;
|
||||
|
||||
// 루트 도메인 추출
|
||||
const getRootDomain = (hostname: string): string => {
|
||||
if (hostname === "localhost" || /^\d+\.\d+\.\d+\.\d+$/.test(hostname)) {
|
||||
return hostname;
|
||||
}
|
||||
|
||||
if (hostname.includes("hasuon.or.kr")) {
|
||||
return ".hasuon.or.kr";
|
||||
}
|
||||
|
||||
const parts = hostname.split(".");
|
||||
if (parts.length >= 2) {
|
||||
return `.${parts.slice(-2).join(".")}`;
|
||||
}
|
||||
|
||||
return hostname;
|
||||
};
|
||||
|
||||
const domain = getRootDomain(actualHost);
|
||||
|
||||
// 삭제할 쿠키 목록
|
||||
const cookiesToDelete = [
|
||||
appConfig.AUTH_USER_ID,
|
||||
appConfig.REFRESH_TOKEN,
|
||||
appConfig.ACCESS_TOKEN,
|
||||
appConfig.CLAIM_NAME,
|
||||
"site-id-key",
|
||||
"site-theme-key",
|
||||
].filter(Boolean); // undefined 제거
|
||||
|
||||
// 여러 방법으로 쿠키 삭제 시도
|
||||
cookiesToDelete.forEach((cookieName) => {
|
||||
if (!cookieName) return;
|
||||
|
||||
// 방법 1: removeCookie 함수 사용
|
||||
if (domain === "localhost") {
|
||||
removeCookie(cookieName, {});
|
||||
} else {
|
||||
removeCookie(cookieName, { domain });
|
||||
}
|
||||
|
||||
// 방법 2: 직접 document.cookie 설정 (도메인 포함)
|
||||
if (domain !== "localhost") {
|
||||
document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; domain=${domain}`;
|
||||
}
|
||||
|
||||
// 방법 3: 도메인 없이 삭제 (현재 도메인만)
|
||||
document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;
|
||||
|
||||
// 방법 4: Secure 속성 포함 삭제
|
||||
if (window.location.protocol === "https:") {
|
||||
if (domain !== "localhost") {
|
||||
document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; domain=${domain}; secure`;
|
||||
}
|
||||
document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; secure`;
|
||||
}
|
||||
});
|
||||
};
|
||||
/*
|
||||
const logout = async () => {
|
||||
try {
|
||||
const response = await fetch("/api/auth/logout", {
|
||||
@@ -123,7 +215,7 @@ export function Header({ viewOnly }: { viewOnly?: boolean }) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
*/
|
||||
const openPopup = useCallback(async (popup: Popup) => {
|
||||
try {
|
||||
const cookieName = `cs-popup-hide-for-day-${popup.popupSn}`;
|
||||
|
||||
Reference in New Issue
Block a user