From e83afde5ef7dfd88512808897aa3d808af0d7fe7 Mon Sep 17 00:00:00 2001 From: Gronod Date: Sat, 16 May 2026 17:15:28 +0100 Subject: [PATCH] feat: add 'Keep me logged in' checkbox to login form - index.html: checkbox between password field and login button - app.js: reads #remember-me and passes rememberMe in POST body - auth.js: rememberMe=true sets 30-day maxAge; false = session cookie (expires when browser closes) - style.css: .form-group--checkbox and .checkbox-label styles --- public/app.js | 3 ++- public/index.html | 6 ++++++ public/style.css | 26 ++++++++++++++++++++++++++ server/routes/auth.js | 15 ++++++++++----- 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/public/app.js b/public/app.js index 28e9b9c..fb5e607 100644 --- a/public/app.js +++ b/public/app.js @@ -136,6 +136,7 @@ async function handleLogin(e) { const username = document.getElementById('username').value; const password = document.getElementById('password').value; + const rememberMe = document.getElementById('remember-me').checked; try { const response = await fetch('/api/auth/login', { @@ -143,7 +144,7 @@ async function handleLogin(e) { headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ username, password }) + body: JSON.stringify({ username, password, rememberMe }) }); const data = await response.json(); diff --git a/public/index.html b/public/index.html index 6f5a0fc..5c23feb 100644 --- a/public/index.html +++ b/public/index.html @@ -31,6 +31,12 @@ +
+ +
diff --git a/public/style.css b/public/style.css index a8a04b1..8e8220b 100644 --- a/public/style.css +++ b/public/style.css @@ -612,6 +612,32 @@ body { border-color: var(--accent); } +.form-group--checkbox { + margin-bottom: 20px; +} + +.checkbox-label { + display: flex; + align-items: center; + gap: 8px; + cursor: pointer; + font-size: 0.9rem; + color: var(--text-secondary); + user-select: none; +} + +.checkbox-label input[type="checkbox"] { + width: 16px; + height: 16px; + accent-color: var(--accent); + cursor: pointer; + flex-shrink: 0; +} + +.checkbox-label span { + line-height: 1; +} + .login-btn { width: 100%; padding: 10px; diff --git a/server/routes/auth.js b/server/routes/auth.js index 1e446ad..1b82a21 100644 --- a/server/routes/auth.js +++ b/server/routes/auth.js @@ -34,7 +34,7 @@ const loginLimiter = rateLimit({ // Authenticate user with Emby router.post('/login', loginLimiter, async (req, res) => { try { - const { username, password } = req.body; + const { username, password, rememberMe } = req.body; console.log(`[Auth] Attempting login for user: ${username}`); @@ -68,15 +68,20 @@ router.post('/login', loginLimiter, async (req, res) => { storeToken(user.Id, authData.AccessToken); // Set authentication cookie (signed when COOKIE_SECRET is set). + // rememberMe=true → persistent cookie, expires in 30 days + // rememberMe=false → session cookie, expires when browser closes const cookiePayload = JSON.stringify({ id: user.Id, name: user.Name, isAdmin }); const signed = !!process.env.COOKIE_SECRET; - res.cookie('emby_user', cookiePayload, { + const cookieOptions = { httpOnly: true, secure: process.env.NODE_ENV === 'production', sameSite: 'strict', - signed, - maxAge: 24 * 60 * 60 * 1000 // 24 hours - }); + signed + }; + if (rememberMe) { + cookieOptions.maxAge = 30 * 24 * 60 * 60 * 1000; // 30 days + } + res.cookie('emby_user', cookiePayload, cookieOptions); res.json({ success: true,