option to disable the session timeout

This commit is contained in:
Jarek Krochmalski committed 2026-08-27 07:34:37 +02:00
1 parent ef390e94ec
commit b04bc504f9
5 files changed
+109 -17

No files matched your search

+5 -9
View File
@@ -42,6 +42,7 @@ import {
type OidcConfig
} from './db';
import { Client as LdapClient } from 'ldapts';
import { resolveSessionTimeout, cookieMaxAge } from '$lib/utils/session-timeout';
import { escapeLdapFilterValue } from './ldap-filter';
import { isEnterprise } from './license';
import { secureRandomBytes } from './crypto-fallback';
@@ -205,21 +206,16 @@ export async function createUserSession(
// Generate secure token
const sessionId = generateSessionToken();
// Get session timeout from settings
// Get session timeout from settings (0 = never expire, see resolveSessionTimeout).
const settings = await getAuthSettings();
// Safety: ensure sessionTimeout is valid (1 second to 30 days), default to 24h if invalid
const MAX_SESSION_TIMEOUT = 2592000; // 30 days in seconds
const DEFAULT_SESSION_TIMEOUT = 86400; // 24 hours in seconds
const sessionTimeout = (settings?.sessionTimeout > 0 && settings?.sessionTimeout <= MAX_SESSION_TIMEOUT)
? settings.sessionTimeout
: DEFAULT_SESSION_TIMEOUT;
const sessionTimeout = resolveSessionTimeout(settings?.sessionTimeout);
const expiresAt = new Date(Date.now() + sessionTimeout * 1000).toISOString();
// Create session in database
const session = await dbCreateSession(sessionId, userId, provider, expiresAt);
// Set secure cookie
setSessionCookie(cookies, sessionId, sessionTimeout, request);
// Cookie max-age is capped at the browser's ~400-day limit; the DB session outlives it.
setSessionCookie(cookies, sessionId, cookieMaxAge(sessionTimeout), request);
// Update user's last login time
await updateUser(userId, { lastLogin: new Date().toISOString() });
+31
View File
@@ -0,0 +1,31 @@
/**
* Resolve the effective session lifetime (seconds) from the configured value.
* 0 is the "never expire" sentinel (#1302): the session still lives in the DB
* (logout, password change and deactivation delete it) but is dated ~10 years out
* so time never ends it. Any invalid value falls back to the 24h default. Pure so
* it can be unit-tested without the DB.
*/
export const MAX_SESSION_TIMEOUT = 2592000; // 30 days in seconds
export const DEFAULT_SESSION_TIMEOUT = 86400; // 24 hours in seconds
export const NEVER_EXPIRE_TIMEOUT = 315360000; // 10 years in seconds
// Browsers (Chrome 104+, Firefox) clamp Set-Cookie max-age to ~400 days (RFC 6265bis),
// so a longer cookie is pointless. The DB session can outlive this; the cookie caps here.
export const MAX_COOKIE_MAX_AGE = 34560000; // 400 days in seconds
export function resolveSessionTimeout(configured: number | null | undefined): number {
if (configured === 0) return NEVER_EXPIRE_TIMEOUT;
if (typeof configured === 'number' && configured > 0 && configured <= MAX_SESSION_TIMEOUT) {
return configured;
}
return DEFAULT_SESSION_TIMEOUT;
}
/**
* The cookie max-age to use for a given server-side session lifetime. Capped at the
* browser's ~400-day limit so cookie and DB lifetimes don't silently diverge for a
* never-expire session (the DB row still lives its full lifetime).
*/
export function cookieMaxAge(sessionTimeout: number): number {
return Math.min(sessionTimeout, MAX_COOKIE_MAX_AGE);
}