From db1fcc8ee0828197d0e5fbf77beb2843e44f9c4e Mon Sep 17 00:00:00 2001 From: choiboa Date: Fri, 2 Jan 2026 02:14:21 +0900 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=A8=20Fix=20:=20=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=EC=9E=90=EB=8F=99=20=EA=B0=B1=EC=8B=A0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/api/auth/refresh/route.ts | 2 +- src/app/api/proxy/[...path]/route.ts | 54 ++++++++++++++++------------ 2 files changed, 33 insertions(+), 23 deletions(-) diff --git a/src/app/api/auth/refresh/route.ts b/src/app/api/auth/refresh/route.ts index 8451c2c..7195030 100644 --- a/src/app/api/auth/refresh/route.ts +++ b/src/app/api/auth/refresh/route.ts @@ -8,7 +8,7 @@ export async function POST() { try { const refreshToken = await requireRefreshToken(); - const data = await backendFetch("/auth/refresh", { + const data = await backendFetch("/auth/tokens", { method: "POST", body: JSON.stringify({ refreshToken }), auth: "none", diff --git a/src/app/api/proxy/[...path]/route.ts b/src/app/api/proxy/[...path]/route.ts index f27381d..ccad58c 100644 --- a/src/app/api/proxy/[...path]/route.ts +++ b/src/app/api/proxy/[...path]/route.ts @@ -1,13 +1,9 @@ -import { backendFetch } from "@/lib/backend"; import { - clearAuthCookies, getAccessTokenFromCookies, getRefreshTokenFromCookies, - setAuthCookies, } from "@/lib/cookies"; import { NextResponse } from "next/server"; - const BASE = process.env.NEXT_PUBLIC_BASE_URL; if (!BASE) throw new Error("🚨 NEXT_PUBLIC_BASE_URL을 찾을 수 μ—†μŠ΅λ‹ˆλ‹€"); @@ -33,14 +29,13 @@ function buildBackendUrl(req: Request, pathArr: string[]) { return `${base}${path}${search}`; } -function buildForwardHeaders(req: Request, accessToken: string | null) { +function buildForwardHeaders(req: Request) { const headers = new Headers(req.headers); headers.delete("host"); headers.delete("connection"); headers.delete("content-length"); headers.delete("authorization"); - if (accessToken) headers.set("authorization", `Bearer ${accessToken}`); return headers; } @@ -54,7 +49,9 @@ async function callBackend( const method = req.method.toUpperCase(); const hasBody = !["GET", "HEAD"].includes(method); - const headers = buildForwardHeaders(req, accessToken); + const headers = buildForwardHeaders(req); + + if (accessToken) headers.set("authorization", `Bearer ${accessToken}`); return fetch(url, { method, @@ -84,8 +81,28 @@ function attachClearAuthCookies(res: NextResponse) { return res; } +async function refreshTokensByHeader(req: Request): Promise { + const refreshToken = await getRefreshTokenFromCookies(); + if (!refreshToken) throw new Error("no refresh token"); + + const refreshUrl = `${BASE}${"/auth/tokens"}`; + + const headers = buildForwardHeaders(req); + headers.set("accept", "application/json"); + headers.set("authorization", `Bearer ${refreshToken}`); + + const res = await fetch(refreshUrl, { + method: "POST", + headers, + cache: "no-store", + }); + + if (!res.ok) throw new Error("refresh failed"); + + return (await res.json()) as RefreshResponse; +} + async function handler(req: Request, ctx: Ctx) { - const { path } = await ctx.params; const backendUrl = buildBackendUrl(req, path); @@ -96,28 +113,21 @@ async function handler(req: Request, ctx: Ctx) { const access1 = await getAccessTokenFromCookies(); let res = await callBackend(req, backendUrl, access1, bodyBuf); - if (res.status !== 401 && res.status !== 403) return passThrough(res); - - const refreshToken = await getRefreshTokenFromCookies(); - if (!refreshToken) { - return attachClearAuthCookies( - NextResponse.json({ ok: false, message: "Unauthenticated" }, { status: 401 }), - ); + if (res.status !== 401 && res.status !== 403) { + return passThrough(res); } let refreshed: RefreshResponse; try { - refreshed = await backendFetch("/auth/refresh", { - method: "POST", - body: JSON.stringify({ refreshToken }), - auth: "none", - }); + refreshed = await refreshTokensByHeader(req); } catch { return attachClearAuthCookies( - NextResponse.json({ ok: false, message: "Unauthenticated" }, { status: 401 }), + NextResponse.json( + { ok: false, message: "Unauthenticated" }, + { status: 401 }, + ), ); } - res = await callBackend(req, backendUrl, refreshed.accessToken, bodyBuf); const next = passThrough(res);