Skip to content

feat(*): revoke cookie sessions by subject and sid - #215

Open
Baoyuantop wants to merge 8 commits into
bungle:masterfrom
Baoyuantop:codex/oidc-session-revocation
Open

Baoyuantop wants to merge 8 commits into
bungle:masterfrom
Baoyuantop:codex/oidc-session-revocation

Conversation

@Baoyuantop

Copy link
Copy Markdown

Cookie sessions need to be revoked by an identity provider's session ID or subject when the browser's cookie is unavailable, for example when processing an OIDC back-channel logout notification. This change adds session.revoke_subject and session.revoke_sid; affected cookies are rejected on their next revocation check while sessions created after the revocation remain usable.

Continues and supersedes #212 by @janiussyafiq, preserving all seven original commits. Fixes #211. The OIDC notification receiver is tracked separately in zmartzone/lua-resty-openidc#572.

Changes

  • Store an optional identity provider session ID through session:set_sid / session:get_sid, alongside the existing subject.
  • Write timestamp revocation marks through the configured revocation backend without an open browser session. Keep subject: and sid: key namespaces distinct and apply the existing hashing options.
  • Check regular and remember cookies, including the missing-audience restoration path. Report revocation write errors even when session reads use the open failure policy.
  • Integrate with the worker-local cache added in perf(*): Cache revocation lookups in a worker-local LRU #213: cache revocation timestamps rather than a result tied to one session's creation time, and update the local entry after a successful write. Isolate cached entries by revocation storage instance.
  • Document cache propagation, issuer-qualified identifiers, and the required mark lifetime. sid is kept in the encrypted payload; this change does not add a store_metadata index or enumerate/delete server-side sessions.

Validation

Validated in Docker using OpenResty 1.27.1.2, real Redis and Memcached, and the file/shared-memory backends:

  • make unit: 211 tests passed (the repository's default CI suite, excluding noci cases).
  • make prove: 28 HTTP integration assertions passed. Test::Nginx reported child-process shutdown timeouts during teardown; the assertions and command still passed.
  • make lint: 0 warnings and 0 errors across 14 files.

New regression coverage includes replacing a cached miss on local revocation, comparing cached timestamps with both old and new sessions, external revocation after cache expiry, and isolation between revocation stores.

janiussyafiq and others added 8 commits September 9, 2026 09:29
Sessions can carry revocation keys in the encrypted payload via
session:set_revocation_keys. On open, a key whose revocation mark is at
or after the session creation time rejects the session with
"session revoked". Marks are unix timestamps; the 4.2.0 mark "1" still
means revoked regardless of time.
Writes a unix timestamp mark for an application supplied key through
the configured revocation storage, so sessions carrying that key and
created at or before the mark are rejected on open. Intended for
identity provider initiated logout, where no cookie is available.
Check every audience's revocation keys when opening a remember cookie,
since restoration mints a fresh session cookie carrying all of them.
Reset the rejected cookie's meta on revocation so a re-login does not
inherit the revoked creation time.
Run the key check before a remember cookie's data is kept for an absent
audience, and leave a rejected remember cookie with empty metadata so
save, logout and destroy do not reload its creation time.
Replace set_revocation_keys/get_revocation_keys and session.revoke with
structured fields: the existing subject plus a new sid (identity provider
session id) set with session:set_sid, revoked with session.revoke_subject
and session.revoke_sid. Revocation marks are stored under a "subject:" or
"sid:" prefix, subject goes through hash_subject, so app supplied values
cannot collide with session id marks.
@Baoyuantop

Copy link
Copy Markdown
Author

Hi @bungle, I've picked up #212 and continued it in this PR, preserving the original commits. It now integrates with #213's revocation cache, checks cached revocation timestamps against each session's creation time, and isolates cache entries between revocation stores.

Local validation passed: 211 unit tests, 28 HTTP integration assertions, and lint. Could you take a look when you have time? I'd appreciate your feedback on the subject/sid APIs and cache behavior. Thanks!

@Hockenba

Hockenba commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

Cookie sessions need to be revoked by an identity provider's session ID or subject when the browser's cookie is unavailable, for example when processing an OIDC back-channel logout notification. This change adds session.revoke_subject and session.revoke_sid; affected cookies are rejected on their next revocation check while sessions created after the revocation remain usable.

Continues and supersedes #212 by @janiussyafiq, preserving all seven original commits. Fixes #211. The OIDC notification receiver is tracked separately in zmartzone/lua-resty-openidc#572.

Changes

  • Store an optional identity provider session ID through session:set_sid / session:get_sid, alongside the existing subject.
  • Write timestamp revocation marks through the configured revocation backend without an open browser session. Keep subject: and sid: key namespaces distinct and apply the existing hashing options.
  • Check regular and remember cookies, including the missing-audience restoration path. Report revocation write errors even when session reads use the open failure policy.
  • Integrate with the worker-local cache added in perf(*): Cache revocation lookups in a worker-local LRU #213: cache revocation timestamps rather than a result tied to one session's creation time, and update the local entry after a successful write. Isolate cached entries by revocation storage instance.
  • Document cache propagation, issuer-qualified identifiers, and the required mark lifetime. sid is kept in the encrypted payload; this change does not add a store_metadata index or enumerate/delete server-side sessions.

Validation

Validated in Docker using OpenResty 1.27.1.2, real Redis and Memcached, and the file/shared-memory backends:

  • make unit: 211 tests passed (the repository's default CI suite, excluding noci cases).
  • make prove: 28 HTTP integration assertions passed. Test::Nginx reported child-process shutdown timeouts during teardown; the assertions and command still passed.
  • make lint: 0 warnings and 0 errors across 14 files.

New regression coverage includes replacing a cached miss on local revocation, comparing cached timestamps with both old and new sessions, external revocation after cache expiry, and isolation between revocation stores.

@janiussyafiq should close #212 to remove the old PR.

@bungle

bungle commented Nov 9, 2026

Copy link
Copy Markdown
Owner

@janiussyafiq now that @Hockenba PRs are finally merged I might have some time to get this in. Could you rebase this to latest?

This branch has not been deployed

No deployments
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.

Revoke cookie sessions by application-supplied key

4 participants