# Session tokens use secure, HttpOnly, SameSite cookies

- **Pattern:** `ab-002216` (`saas-authentication.session-management.session-tokens-secure`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-002216
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-002216)

## Why it matters

Session cookies without the Secure, HttpOnly, and SameSite flags are the most common entry point for session hijacking. Dropping HttpOnly makes the cookie readable by any JavaScript on your page — a single XSS flaw anywhere on the domain hands an attacker every active session. Dropping Secure lets the cookie travel over unencrypted HTTP connections, where network attackers can intercept it. Missing SameSite exposes the session to CSRF attacks. Together these flags implement the three-sided defense OWASP A07 (Identification & Authentication Failures) and NIST 800-63B expect as a baseline for any session credential.

## Severity rationale

High because missing any one of these three flags creates a direct, exploitable path to session token theft and full account takeover.

## Remediation

Set all three flags explicitly in your auth library config rather than relying on defaults. In NextAuth, override the cookie options block:

```ts
// src/app/api/auth/[...nextauth]/route.ts
export const authOptions = {
  cookies: {
    sessionToken: {
      options: {
        httpOnly: true,
        secure: process.env.NODE_ENV === 'production',
        sameSite: 'lax',
        path: '/'
      }
    }
  }
}
```

For Supabase, use `@supabase/ssr` — it handles all three flags correctly. For any custom `Set-Cookie` header, append `; HttpOnly; Secure; SameSite=Lax` before every response.

## Detection

- **ID:** `session-tokens-secure`
- **Severity:** `high`
- **What to look for:** Examine auth/session configuration for cookie settings. Check auth library config (next-auth cookie options, Supabase cookie config, clerk config, lucia session config), middleware that sets cookies, and any manual `Set-Cookie` usage. Look for `secure: true`, `httpOnly: true`, and `sameSite: 'lax'` or `'strict'` flags on the session/auth token cookie specifically. Count every cookie set by the application and enumerate each with its flags (HttpOnly, Secure, SameSite, Path). Classify as correctly configured or misconfigured. Before evaluating, extract and quote the cookie configuration code — the Set-Cookie header or cookie options object — to verify flag settings.
- **Pass criteria:** Session and auth cookies are configured with `Secure`, `HttpOnly`, and an explicit `SameSite` value of `Lax` or `Strict`. Libraries that set these by default in production (e.g., NextAuth.js, Clerk) count as passing when no explicit override disables them. Managed auth libraries (`@supabase/ssr`, NextAuth.js, Clerk, Auth0 SDK) that handle session cookie configuration by default satisfy this check — result is PASS, not SKIP. At least 1 implementation must be confirmed.
- **Fail criteria:** Session cookies are set without `Secure`, without `HttpOnly`, or without a `SameSite` attribute; or an explicit override in config disables any of these flags. Do NOT pass if session tokens are stored in localStorage — HttpOnly cookies are the only acceptable storage mechanism for session credentials.
- **Skip (N/A) when:** No authentication library is detected in `package.json` AND no session/cookie-setting code is found in the codebase. The presence of a managed auth library such as `@supabase/ssr`, NextAuth.js, Clerk, or an Auth0 SDK means authentication is in use and this check must be evaluated, not skipped.
- **Cross-reference:** The `login-csrf` check verifies the complementary cross-site protection that works alongside secure cookie flags.
- **Detail on fail:** Identify which flags are missing and in what file. Example: `"NextAuth session cookie configured without httpOnly: true in auth options at src/app/api/auth/[...nextauth]/route.ts"` or `"Manual Set-Cookie in api/session missing Secure and SameSite flags"`.
- **Remediation:** The `Secure` flag ensures cookies are only sent over HTTPS, preventing interception on unencrypted connections. `HttpOnly` prevents JavaScript from reading the cookie, blocking XSS-based session theft. `SameSite=Lax` prevents most CSRF attacks. All three should be set together:

  ```ts
  // NextAuth example — explicit cookie config
  export const authOptions = {
    cookies: {
      sessionToken: {
        options: {
          httpOnly: true,
          secure: process.env.NODE_ENV === 'production',
          sameSite: 'lax',
          path: '/'
        }
      }
    }
  }
  ```

  For Supabase, configure the cookie via the SSR client helper — it handles these flags correctly when using `@supabase/ssr`. For manual cookie setting, always include all three flags.

## External references

- cwe CWE-614
- cwe CWE-1004
- owasp A07
- nist SC-8

Taxons: access-control, cryptography-and-secrets

HTML version: https://auditbuffet.com/patterns/ab-002216
