v0.14 is out: a mobile auth pack for Swift/iOS and Android, catching insecure token storage, cleartext traffic, and OAuth in embedded WebViews. Read more →
LOW AI PREVALENCE: MEDIUM auth.cookie.long-lived

An auth-looking cookie is being set with a maxAge greater than 30 days.

Why AI tools produce this: AI coding tools produce this regularly, typically when prompted for a shortcut or a quick fix.

Why this matters

The threshold is 30 × 24 × 60 × 60 × 1000 = 2_592_000_000 milliseconds. Long-lived session cookies expand the blast radius of any single token theft and bypass server-side revocation if the application doesn't validate freshness on every request.

Prefer short-lived access cookies (15-60 min) paired with a separate refresh token rotation flow. If you really need a "remember me" cookie, scope it tightly (SameSite=Strict, dedicated path) and back it with a server-side allowlist you can revoke.

VULNERABLE
vulnerable.ts
import type { Response } from 'express';

export function loginBad(res: Response, token: string) {
  // ruleid: auth.cookie.long-lived
  res.cookie('session', token, {
    httpOnly: true,
    secure: true,
    sameSite: 'strict',
    maxAge: 31_536_000_000, // 1 year
  });
}

export function loginBad2(res: Response, jwt: string) {
  // ruleid: auth.cookie.long-lived
  res.cookie('refresh_token', jwt, {
    httpOnly: true,
    secure: true,
    sameSite: 'strict',
    maxAge: 7776000000,
  });
}
SAFE
safe.ts
import type { Response } from 'express';

const FIFTEEN_MIN_MS = 15 * 60 * 1000;
const ONE_WEEK_MS = 7 * 24 * 60 * 60 * 1000;

// ok: auth.cookie.long-lived
export function loginGood(res: Response, token: string) {
  res.cookie('session', token, {
    httpOnly: true,
    secure: true,
    sameSite: 'strict',
    maxAge: FIFTEEN_MIN_MS,
  });
}

// ok: auth.cookie.long-lived -- still under 30 days
export function rememberMeOk(res: Response, refresh: string) {
  res.cookie('refresh_token', refresh, {
    httpOnly: true,
    secure: true,
    sameSite: 'strict',
    maxAge: ONE_WEEK_MS,
  });
}

Suppressing this rule

If a finding is a genuine false positive, scope the suppression to the exact line and leave a reason, never disable the rule project-wide. Disable directives are line-scoped by design.

// oauthlint-disable-next-line auth.cookie.long-lived -- <reason>

References

https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html ↗