Repository navigation
Safer sessions with overlapping requests and encrypted redis/database stores
·
3 commits
to 8.x
since this release
Immutable
release. Only release title and notes can be modified.
8.2.0 (2026-10-17)
This release makes sessions more robust when requests from the same browser overlap: a logout, a regenerate() or a SessionCollection.destroy() that occurs while another request runs. Before, the late request could bring an ended session back.
With the default config, no behavior that apps rely on changes. The new protections that change visible behavior are opt-in.
What changes for everyone
- The redis, database, file and dynamodb stores do not write back a session that another request destroyed during the request.
- On redis and database, the write of a newly tagged session adds it to the user's sessions in the same operation (
MULTIon standalone Redis, one query in SQL). A concurrenttagged()call can no longer drop it. On Redis Cluster, the store writes the data and then the tag, outside a transaction. - The database store
tag()no longer creates an empty row for a session that has no data. - The japa api and browser client plugins write test sessions to the configured store, instead of always using the memory store. The cookie store still uses memory.
New options
refreshCookie(defaulttrue): withfalse, the session cookie is sent only when the session id changes. A late response can then not put back an id the browser left. The cookieMax-Ageis no longer refreshed, so use it withclearWithBrowser.renewMissingSessionId(defaultfalse): when the cookie names a session that the store does not have, the session gets a new id. The id of an ended session is never used again. A session without data then gets a new id on each request.encryptonstores.redis()andstores.database()(defaultfalse): encrypts the session data with the encryption service, instead of only signing it. Existing sessions cannot be read after you enable it.
export default defineConfig({
age: '2h',
clearWithBrowser: true,
refreshCookie: false,
renewMissingSessionId: true,
store: 'redis',
stores: {
redis: stores.redis({ connection: 'main', encrypt: true }),
},
})Features
- add refreshCookie option to send the cookie on id change (dd50662)
- add encrypt option to the redis and database stores (bd90cc4)
- make the new id for a missing session opt-in (088965c)
Bug Fixes
- do not write back a session destroyed during a request (952e4ba)
- start a new id when the cookie names an ended session (af3ffa7)
- tag a session atomically with its write (470a6b5)
- do not use a cross-slot MULTI on redis cluster (22e6c84)
- do not replay the tag of a session read by the store (8acfa72)
- report partial writes of a read session in the file store (0ceb6cd)
- write japa test sessions to the configured store (22482f4)
- read the response session when refreshCookie is false (e8fedf5)
- give each test client call its own store (60d3e81)
- destroy the browser test session before close resolves (fc0a5ae)
Full Changelog: v8.1.0...v8.2.0