Skip to content

feat(auth0-express): support session secret rotation - #36

Merged
frederikprijck merged 3 commits into
mainfrom
feat/session-secret-rotation
Aug 3, 2026
Merged

feat(auth0-express): support session secret rotation#36
frederikprijck merged 3 commits into
mainfrom
feat/session-secret-rotation

Conversation

@frederikprijck

@frederikprijck frederikprijck commented Jul 20, 2026

Copy link
Copy Markdown
Member

Summary

Adds session secret rotation to @auth0/auth0-express, so you can roll the session secret without logging existing users out.

  • sessionSecret now accepts string | string[]. The first secret encrypts new cookies; all secrets are tried, in order, when decrypting.
  • Via env vars, a comma-separated AUTH0_SESSION_SECRET (or legacy SECRET) is parsed into an array in the same order — matching how APP_BASE_URL already handles comma-separated values.

Rotation flow

  1. Deploy with sessionSecret: [newSecret, oldSecret] — new cookies encrypt under newSecret, existing oldSecret cookies still decrypt.
  2. Once every session has been re-encrypted under the new secret (i.e. after your session TTL window), drop oldSecret.

Tests

  • config.spec.ts — explicit array, comma-separated AUTH0_SESSION_SECRET, comma-separated legacy SECRET, single value stays a string, trailing-comma collapse, empty-array throws.
  • session-secret-rotation.spec.ts (new) — end-to-end via createServerClientInstance: a cookie encrypted under the old secret is still readable after rotating to [new, old], and becomes unreadable once the old secret is dropped.

All 186 tests pass; lint, typecheck, and build are clean.

Docs

  • sessionSecret JSDoc in types.ts documents rotation.
  • README note on rotating the secret.

Widen `sessionSecret` to `string | string[]`. The first secret encrypts
new cookies; all secrets are tried, in order, when decrypting — letting
you roll the secret without logging existing users out. A comma-separated
`AUTH0_SESSION_SECRET` / `SECRET` env var is parsed into an array in the
same order.

The underlying @auth0/auth0-server-js stores already accept an array
secret, so this is a type widening plus env parsing; the required-secret
guard now also rejects an empty array.
Comment thread packages/auth0-express/src/config.ts
…itly

A programmatically-passed sessionSecret string bypassed comma-separated
parsing since the spread of `config` happened after the env-based parse.
Mirrors the existing appBaseUrl re-parse.
…n type

sessionSecret is a required string | string[] field, so assigning the
helper's string | string[] | undefined return type failed to compile.
Add an overload so a definite string input is typed to never return
undefined.
@frederikprijck
frederikprijck merged commit 8aa3ba3 into main Aug 3, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants