112 lines
3.2 KiB
TypeScript
112 lines
3.2 KiB
TypeScript
import {
|
|
ACCESS_TOKEN,
|
|
AUTH_USER_ID,
|
|
CLAIM_NAME,
|
|
ENDPOINT,
|
|
} from "@/shared/config";
|
|
import { getCookie } from "@/shared/lib";
|
|
import { type AuthPayload, type AuthService } from "@common/auth";
|
|
|
|
import { clearDeviceId, getOrCreateDeviceId } from "../lib/device-id";
|
|
import {
|
|
clearRefreshTimer,
|
|
setToken,
|
|
tokenManager,
|
|
} from "../lib/token-manager";
|
|
|
|
import { clearTabStorePersist } from "@/store/tab-store";
|
|
|
|
async function login(payload: AuthPayload): Promise<void> {
|
|
const response = await fetch(`/api/proxy${ENDPOINT.USER_SERVICE.LOGIN}`, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
"X-Device-Id": getOrCreateDeviceId(),
|
|
},
|
|
body: JSON.stringify(payload),
|
|
});
|
|
|
|
const data = await response.json();
|
|
|
|
const accessToken = data[ACCESS_TOKEN];
|
|
const tokenId = data[AUTH_USER_ID];
|
|
|
|
if (!accessToken || !tokenId) {
|
|
throw new Error("인증 토큰을 받지 못했습니다.");
|
|
}
|
|
|
|
const prevTokenId = getCookie(AUTH_USER_ID);
|
|
if (prevTokenId !== undefined && prevTokenId !== tokenId) {
|
|
clearTabStorePersist();
|
|
}
|
|
|
|
setToken(CLAIM_NAME, accessToken);
|
|
setToken(AUTH_USER_ID, tokenId);
|
|
|
|
// const remainingMs = getRemainingMs(accessToken);
|
|
// if (remainingMs > 0) {
|
|
// setupRefreshTimer(silentRefresh, remainingMs);
|
|
// }
|
|
}
|
|
|
|
async function silentRefresh(): Promise<void> {
|
|
console.log(`[silentRefresh] Called at ${new Date().toISOString()}`);
|
|
try {
|
|
const response = await fetch(
|
|
`/api/proxy${ENDPOINT.USER_SERVICE.SILENT_REFRESH}`,
|
|
{
|
|
method: "PUT",
|
|
headers: {
|
|
"X-Device-Id": getOrCreateDeviceId(),
|
|
},
|
|
},
|
|
);
|
|
|
|
const data = await response.json();
|
|
|
|
if (!response.ok) {
|
|
throw new Error(data?.message ?? "토큰 갱신에 실패했습니다.");
|
|
}
|
|
|
|
const accessToken = data[ACCESS_TOKEN];
|
|
const tokenId = data[AUTH_USER_ID];
|
|
|
|
if (!accessToken || !tokenId) {
|
|
throw new Error("갱신된 인증 토큰을 받지 못했습니다.");
|
|
}
|
|
|
|
setToken(CLAIM_NAME, accessToken);
|
|
setToken(AUTH_USER_ID, tokenId);
|
|
|
|
// const remainingMs = getRemainingMs(accessToken);
|
|
// if (remainingMs > 0) {
|
|
// setupRefreshTimer(silentRefresh, remainingMs);
|
|
// }
|
|
} catch (error) {
|
|
console.error(
|
|
`[silentRefresh] Failed at ${new Date().toISOString()}`,
|
|
error,
|
|
);
|
|
tokenManager.clearAuthToken();
|
|
if (typeof window !== "undefined") {
|
|
window.dispatchEvent(new CustomEvent("auth:logout"));
|
|
}
|
|
}
|
|
}
|
|
|
|
export async function logout(): Promise<void> {
|
|
tokenManager.clearAuthToken();
|
|
clearDeviceId();
|
|
|
|
if (typeof window !== "undefined") {
|
|
window.dispatchEvent(new CustomEvent("auth:logout"));
|
|
}
|
|
}
|
|
|
|
export const authService: AuthService = {
|
|
login,
|
|
silentRefresh,
|
|
declineSessionExtend: clearRefreshTimer,
|
|
logout,
|
|
};
|