// =============================== // AUTH.JS // Login, JWT, redirect e auto logout // =============================== // Deve rimanere globale se viene usata da altri file function parseJwt(token) { try { const payload = token.split(".")[1]; if (!payload) return null; const base64 = payload .replace(/-/g, "+") .replace(/_/g, "/") .padEnd(Math.ceil(payload.length / 4) * 4, "="); const json = decodeURIComponent( atob(base64) .split("") .map((char) => `%${char.charCodeAt(0).toString(16).padStart(2, "0")}` ) .join("") ); return JSON.parse(json); } catch (error) { console.error("[AUTH] JWT non valido:", error); return null; } } (() => { "use strict"; const LOGIN_ENDPOINT = "/auth/login"; const LOGIN_PAGE = "/login"; const TOKEN_KEY = "token"; let autoLogoutTimer = null; // ------------------------------- // TOKEN // ------------------------------- function saveToken(token) { try { localStorage.setItem(TOKEN_KEY, token); } catch (error) { console.error("[AUTH] Errore salvataggio token:", error); } } function getToken() { try { return localStorage.getItem(TOKEN_KEY) || ""; } catch { return ""; } } function clearToken() { clearTimeout(autoLogoutTimer); autoLogoutTimer = null; try { localStorage.removeItem(TOKEN_KEY); } catch (error) { console.error("[AUTH] Errore rimozione token:", error); } } // ------------------------------- // LOGIN // ------------------------------- async function login(email, password) { const response = await fetch(LOGIN_ENDPOINT, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ email, password }), }); if (!response.ok) { const message = await response.text(); throw new Error(message || "Credenziali non valide"); } const data = await response.json(); if (!data?.token) { throw new Error("Token mancante nella risposta"); } saveToken(data.token); scheduleAutoLogout(); window.dispatchEvent( new CustomEvent("login:success", { detail: data, }) ); return data; } // ------------------------------- // VERIFICA AUTENTICAZIONE // ------------------------------- function isLoggedIn() { const token = getToken(); const payload = token ? parseJwt(token) : null; if (!payload?.exp) { return false; } const valid = payload.exp * 1000 > Date.now(); console.log("[AUTH CHECK]", { valid, user: payload.name, exp: new Date(payload.exp * 1000).toISOString(), }); return valid; } function getUser() { const token = getToken(); return token ? parseJwt(token) : null; } function requireAuth(redirectUrl = LOGIN_PAGE) { if (isLoggedIn()) { return true; } clearToken(); const currentPath = window.location.pathname + window.location.search + window.location.hash; const separator = redirectUrl.includes("?") ? "&" : "?"; window.location.replace( `${redirectUrl}${separator}redirect=${encodeURIComponent(currentPath)}` ); return false; } // ------------------------------- // AUTO LOGOUT // ------------------------------- function scheduleAutoLogout() { clearTimeout(autoLogoutTimer); autoLogoutTimer = null; const payload = getUser(); const expiresAt = payload?.exp ? payload.exp * 1000 : 0; const timeout = expiresAt - Date.now(); if (!expiresAt) { return; } if (timeout <= 0) { logout({ redirect: true }); return; } autoLogoutTimer = setTimeout(() => { logout({ redirect: true }); }, timeout); } function logout(options = {}) { clearToken(); if (window.AppAuthLogout?.logout) { return window.AppAuthLogout.logout(options); } if (options.redirect !== false) { window.location.replace(LOGIN_PAGE); } } // ------------------------------- // INIT // ------------------------------- function init() { if (isLoggedIn()) { scheduleAutoLogout(); } } // ------------------------------- // API GLOBALE // ------------------------------- window.AppAuth = Object.freeze({ login, logout, isLoggedIn, getUser, requireAuth, scheduleAutoLogout, }); if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", init, { once: true }); } else { init(); } })();