diff --git a/apps/cs/app/api/proxy/[...url]/route.ts b/apps/cs/app/api/proxy/[...url]/route.ts index 0929ca57c..4385956d3 100644 --- a/apps/cs/app/api/proxy/[...url]/route.ts +++ b/apps/cs/app/api/proxy/[...url]/route.ts @@ -1,3 +1,6 @@ +import { cookies } from "next/headers"; +import { NextResponse } from "next/server"; + import { ACCESS_TOKEN, AUTH_USER_ID, @@ -7,8 +10,6 @@ import { SERVER_API_URL, SITE_ID, } from "@/shared/config"; -import { cookies } from "next/headers"; -import { NextResponse } from "next/server"; async function handler( request: Request, @@ -20,6 +21,10 @@ async function handler( "Content-Type": "application/json", "X-Site-Id": SITE_ID, }; + const deviceId = request.headers.get("X-Device-Id"); + if (deviceId) { + headers["X-Device-Id"] = deviceId; + } let body = {}; const isRefreshHandler = params.url.includes("refresh"); diff --git a/apps/cs/package.json b/apps/cs/package.json index d362d1178..710032627 100644 --- a/apps/cs/package.json +++ b/apps/cs/package.json @@ -45,6 +45,7 @@ "sonner": "^2.0.1", "tailwindcss-animate": "^1.0.7", "tus-js-client": "^4.3.1", + "uuid": "^14.0.1", "zod": "^3.24.2", "zustand": "^5.0.3" }, diff --git a/apps/cs/src/entities/auth/api/auth-service.ts b/apps/cs/src/entities/auth/api/auth-service.ts index 3efb1bf85..a8312e46c 100644 --- a/apps/cs/src/entities/auth/api/auth-service.ts +++ b/apps/cs/src/entities/auth/api/auth-service.ts @@ -10,6 +10,7 @@ import { getRemainingMs, } from "@common/auth"; +import { clearDeviceId, getOrCreateDeviceId } from "../lib/device-id"; import { clearRefreshTimer, removeToken, @@ -36,7 +37,10 @@ function resolveLoginError(message: string | undefined): string { async function login(payload: AuthPayload): Promise { const response = await fetch(`/api/proxy${ENDPOINT.USER_SERVICE.LOGIN}`, { method: "POST", - headers: { "Content-Type": "application/json" }, + headers: { + "Content-Type": "application/json", + "X-Device-Id": getOrCreateDeviceId(), + }, body: JSON.stringify(payload), }); @@ -67,7 +71,12 @@ async function silentRefresh(): Promise { try { const response = await fetch( `/api/proxy${ENDPOINT.USER_SERVICE.SILENT_REFRESH}`, - { method: "PUT" }, + { + method: "PUT", + headers: { + "X-Device-Id": getOrCreateDeviceId(), + }, + }, ); const data = await response.json(); @@ -105,6 +114,7 @@ async function silentRefresh(): Promise { async function logout(): Promise { tokenManager.clearAuthToken(); + clearDeviceId(); removeToken("site-id-key"); removeToken("site-theme-key"); diff --git a/apps/cs/src/entities/auth/lib/device-id.ts b/apps/cs/src/entities/auth/lib/device-id.ts new file mode 100644 index 000000000..3683c7189 --- /dev/null +++ b/apps/cs/src/entities/auth/lib/device-id.ts @@ -0,0 +1,20 @@ +import { v4 as uuidv4 } from "uuid"; + +const DEVICE_ID_KEY = "x-device-id"; + +export function getOrCreateDeviceId(): string { + if (typeof window === "undefined") return ""; + + const existing = localStorage.getItem(DEVICE_ID_KEY); + if (existing) return existing; + + const id = uuidv4(); + localStorage.setItem(DEVICE_ID_KEY, id); + return id; +} + +export function clearDeviceId(): void { + if (typeof window === "undefined") return; + + localStorage.removeItem(DEVICE_ID_KEY); +}