diff --git a/server/web/index.html b/server/web/index.html
index 2a14902..62eeb99 100644
--- a/server/web/index.html
+++ b/server/web/index.html
@@ -1743,8 +1743,8 @@
if (!data || !data.token) return false;
token = data.token;
currentUserRole = data.role || 'viewer';
- sessionStorage.setItem('token', token);
- sessionStorage.setItem('role', currentUserRole);
+ localStorage.setItem('token', token);
+ localStorage.setItem('role', currentUserRole);
return true;
} catch (e) {
return false;
@@ -1818,8 +1818,8 @@
if (msg.ok) {
token = msg.token;
currentUserRole = msg.role || 'viewer';
- sessionStorage.setItem('token', token);
- sessionStorage.setItem('role', currentUserRole);
+ localStorage.setItem('token', token);
+ localStorage.setItem('role', currentUserRole);
document.getElementById('login-error').textContent = '';
// Show Users button for admin only
const usersBtn = document.getElementById('users-btn');
@@ -1838,7 +1838,7 @@
if (msg.ok === false) {
// Token invalid (e.g., server restarted), go back to login
token = null;
- sessionStorage.removeItem('token');
+ localStorage.removeItem('token');
showPage('login-page');
break;
}
@@ -2691,7 +2691,7 @@
challengeNonce = '';
connectWebSocket(); // Reconnect immediately
token = null;
- sessionStorage.removeItem('token');
+ localStorage.removeItem('token');
devices = [];
showPage('login-page');
// Hide users button
@@ -4791,9 +4791,9 @@
bindKeyboardBtnEvents(document.getElementById('qc-keyboard'));
bindKeyboardBtnEvents(document.getElementById('btn-keyboard'));
bindKeyboardBtnEvents(document.getElementById('btn-keyboard-bar'));
- // Restore token and role from sessionStorage (local-login fallback).
- token = sessionStorage.getItem('token');
- currentUserRole = sessionStorage.getItem('role') || 'viewer';
+ // Restore token and role from localStorage (local-login fallback).
+ token = localStorage.getItem('token');
+ currentUserRole = localStorage.getItem('role') || 'viewer';
// Attempt portal SSO first: if the user is already logged into the
// parent domain, the server bridges the portal session cookie into
// a YAMA session token so the login form is skipped. On failure