How Session Management Works in TREK: 'Remember Me' and Session Duration

TREK uses a JWT stored in an HTTP-only trek_session cookie with configurable durations—7 days for normal sessions and 30 days when "Remember me" is enabled—controlled by the SESSION_DURATION and SESSION_DURATION_REMEMBER environment variables.

TREK implements stateless authentication using JSON Web Tokens (JWT) delivered via HTTP-only cookies. The session duration in TREK is dynamically determined by the optional "Remember me" flag passed during login, which selects between two configurable time-to-live values defined in the application's configuration.

Configuration-Driven Session Durations

Session longevity in TREK is governed by two environment variables parsed in server/src/config.ts (lines 151-176):

  • SESSION_DURATION – Defines the standard session length when "Remember me" is unchecked. Defaults to 7d (7 days).
  • SESSION_DURATION_REMEMBER – Defines the extended session length when "Remember me" is checked. Defaults to 30d (30 days).

These values are converted into both human-readable constants and millisecond/second representations for use across the application. If the environment variables cannot be parsed, the system falls back to the defaults.

The Authentication Flow

When a user authenticates, TREK coordinates between the login controller, authentication service, and cookie utility to establish the session with the correct duration.

Login Request Handling

The login controller in server/src/nest/auth/auth-public.controller.ts extracts the optional remember_me boolean from the request body. This flag is passed downstream to determine which session duration to apply.

// Controller receives the flag
const { email, password, remember_me } = body;
const remember = remember_me === true;

If omitted, the flag defaults to false, resulting in a session-only cookie that expires when the browser closes.

JWT Token Generation

In server/src/nest/auth/auth.service.ts, the generateToken() function creates the JWT with an expiration claim matching the selected duration:

export function generateToken(
  user: { id: number | bigint; password_version?: number }, 
  rememberMe = false
) {
  const expiresIn = rememberMe 
    ? SESSION_DURATION_REMEMBER_SECONDS 
    : SESSION_DURATION_SECONDS;
  
  return jwt.sign(
    { sub: user.id, pv: user.password_version ?? 0 }, 
    JWT_SECRET, 
    { expiresIn }
  );
}

The token's exp claim mirrors the configuration, ensuring the JWT expires simultaneously with the cookie.

The server/src/services/cookie.ts file contains the setAuthCookie() helper and resolveMaxAge() logic that maps the remember flag to cookie behavior:

function resolveMaxAge(remember: RememberOption): { maxAge: number } | Record<string, never> {
  if (remember === false) return {};                              // session cookie
  if (remember === true)  return { maxAge: SESSION_DURATION_REMEMBER_MS };
  return { maxAge: SESSION_DURATION_MS };                         // default persistent
}

The trek_session cookie is configured with the following security characteristics:

  • HTTP-only – Prevents JavaScript access to the cookie.
  • Secure flag – Determined by three conditions in cookieOptions() (lines 30-38):
    1. Disabled if COOKIE_SECURE=false (useful for LAN testing).
    2. Enabled if NODE_ENV=production or FORCE_HTTPS=true.
    3. Enabled if req.secure indicates HTTPS (respecting X-Forwarded-Proto when Express trusts the proxy).

If a Secure cookie would be sent over plain HTTP, the willDropSecureCookie() function (lines 58-67) detects this condition and surfaces a warning to the user, suggesting they either use HTTPS or set COOKIE_SECURE=false.

Practical Implementation Examples

Login with "Remember me" Enabled

// Client request
await fetch('/api/auth/login', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ email, password, remember_me: true })
});

// Server processing
const remember = remember_me === true;
const token = generateToken(user, remember);
setAuthCookie(res, token, req, remember); // Uses SESSION_DURATION_REMEMBER (30 days)
// Client request without remember_me flag
await fetch('/api/auth/login', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ email, password })
});

// Server processing
const remember = false; // Default when omitted
const token = generateToken(user, remember);
setAuthCookie(res, token, req, remember); // No maxAge set; cookie expires on browser close

Checking Configuration Values

import { SESSION_DURATION, SESSION_DURATION_REMEMBER } from '../config';

console.log(`Normal session: ${SESSION_DURATION}`);           // "7d"
console.log(`Remember-me session: ${SESSION_DURATION_REMEMBER}`); // "30d"

Summary

  • Dual duration system: TREK distinguishes between regular sessions (7d default) and "Remember me" sessions (30d default) via environment variables.
  • JWT-cookie synchronization: The JWT exp claim and cookie maxAge are always set to the same duration to prevent token-cookie mismatches.
  • Three-state logic: The remember parameter supports true (extended), false (session-only), and undefined (historic default persistent).
  • Security-first cookies: The Secure flag automatically enables in production or HTTPS environments, with detection for misconfigured HTTP deployments.
  • Key files: Configuration resides in server/src/config.ts, cookie logic in server/src/services/cookie.ts, and token generation in server/src/nest/auth/auth.service.ts.

Frequently Asked Questions

How do I change the default session duration in TREK?

Set the SESSION_DURATION environment variable to your desired duration string (e.g., 1d, 12h, 60s). For "Remember me" durations, use SESSION_DURATION_REMEMBER. These values are parsed in server/src/config.ts and converted to milliseconds for cookies and seconds for JWTs.

What happens if I check "Remember me" on a public computer?

The browser receives a persistent cookie with a maxAge of 30 days (or your configured SESSION_DURATION_REMEMBER). The cookie remains valid across browser restarts. To invalidate the session, you must either log out through the application or clear the browser's cookies for the domain.

If the server is configured with COOKIE_SECURE enabled (the default in production) but you are accessing it over HTTP, the browser silently drops the Secure cookie. Check the server logs for warnings from willDropSecureCookie(), or explicitly set COOKIE_SECURE=false for local development. Alternatively, ensure you are serving the application over HTTPS.

How does TREK validate sessions on subsequent requests?

TREK extracts the JWT from the trek_session cookie and verifies its signature and expiration using the JWT_SECRET. The password_version claim in the token allows for immediate invalidation of all sessions if the user's password is changed, as implemented in the authentication middleware.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →