// =============================== // AUTH.JS — Login + Token + Redirect + Sessione browser // =============================== // parseJwt DEVE essere globale function parseJwt(token) { try { const base64Url = token.split(".")[1]; const base64 = base64Url .replace(/-/g, "+") .replace(/_/g, "/"); const jsonPayload = decodeURIComponent( atob(base64) .split("") .map( (c) => "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2), ) .join(""), ); return JSON.parse(jsonPayload); } catch (e) { console.error("Errore parseJwt:", e); return null; } } (() => { const LOGIN_ENDPOINT = "/auth/login"; const TOKEN_KEY = "token"; // ------------------------------- // TOKEN STORAGE // ------------------------------- function saveToken(token) { try { localStorage.setItem(TOKEN_KEY, token); } catch (err) { console.error("Errore salvataggio token:", err); } } function getToken() { try { return localStorage.getItem(TOKEN_KEY) || ""; } catch { return ""; } } function clearToken() { try { localStorage.removeItem(TOKEN_KEY); sessionStorage.removeItem("app_open"); } catch {} } // ------------------------------- // LOGIN // ------------------------------- async function login(email, password) { try { const res = await fetch(LOGIN_ENDPOINT, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ email, password, }), }); if (!res.ok) { const msg = await res.text(); throw new Error( msg || "Credenziali non valide" ); } const data = await res.json(); if (!data?.token) { throw new Error( "Token mancante nella risposta" ); } saveToken(data.token); // segna apertura applicazione sessionStorage.setItem( "app_open", "1" ); window.dispatchEvent( new CustomEvent( "login:success", { detail: data, } ) ); scheduleAutoLogout(); return data; } catch(err) { console.error( "Errore login:", err ); throw err; } } // ------------------------------- // CHECK LOGIN // ------------------------------- function isLoggedIn() { // nuova apertura browser/tab if ( !sessionStorage.getItem("app_open") ) { console.log( "[AUTH] nuova apertura browser" ); return false; } const token = getToken(); if (!token) { console.log( "[AUTH] token assente" ); return false; } const payload = parseJwt(token); if (!payload?.exp) { console.log( "[AUTH] token senza 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; } // ------------------------------- // USER INFO // ------------------------------- function getUser() { const token = getToken(); if (!token) { return null; } return parseJwt(token); } // ------------------------------- // REQUIRE AUTH // ------------------------------- function requireAuth( redirectUrl = "/login" ) { 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 JWT // ------------------------------- let autoLogoutTimer = null; function scheduleAutoLogout() { clearTimeout( autoLogoutTimer ); const token = getToken(); if (!token) { return; } const payload = parseJwt(token); const expSec = payload?.exp; if (!expSec) { return; } const timeout = expSec * 1000 - Date.now(); if (timeout <= 0) { window.AppAuth.logout?.({ redirect:true }); return; } autoLogoutTimer = setTimeout(() => { window.AppAuth.logout?.({ redirect:true }); }, timeout); } // ------------------------------- // EXPORT // ------------------------------- window.AppAuth = Object.freeze({ login, logout:(opts)=> window.AppAuthLogout?.logout(opts), isLoggedIn, getUser, requireAuth, scheduleAutoLogout, }); // ------------------------------- // INIT // ------------------------------- function init() { // marca questa apertura browser sessionStorage.setItem( "app_open", "1" ); if (isLoggedIn()) { scheduleAutoLogout(); } } if ( document.readyState === "loading" ) { document.addEventListener( "DOMContentLoaded", init ); } else { init(); } // chiusura pagina/tab window.addEventListener( "pagehide", () => { sessionStorage.removeItem( "app_open" ); } ); })();