Stolen sessions  / field guide
Practitioner field guide · 2026-09-30 · Security & Identity

A copied session is a valid session

When an attacker holds your session cookie, the server cannot tell their request from yours, because possession is the entire proof. This guide reconstructs, from the Okta, Cloudflare, GitHub, Meta and Microsoft records, why the controls teams reach for after a theft leave that fact untouched, and what it actually costs to bind a credential to a holder who cannot be copied.

28 primary sources 7 incident records 5 standards / design docs Evidence through Sep 2026 Read: 20 min
01

The territory

The problem, stated without the word "token": how do you let a request prove it comes from someone who already logged in, without letting anyone who copies that proof become them.

Every logged-in request carries a small piece of evidence that a login already happened: a cookie, a bearer token, an API key. The server checks that the evidence is well-formed and unexpired, and if it is, the request is treated as the user. This is the bearer model, and it is nearly universal because it is cheap. The evidence travels in one header, it can be checked without a database lookup if it is a signed token, and it survives across the dozens of services a single page touches. The property that makes it cheap is the same property that makes it dangerous: the evidence is portable. Anyone holding a copy presents the same proof as the person it was issued to, and nothing downstream can tell the two apart.

That is not a hypothetical. It is the exact mechanism behind the incident that put this topic on every architect's desk. In October 2023, attackers who had accessed Okta's support case system found HTTP Archive (HAR) files that customers had uploaded for troubleshooting, and those files contained live session cookies. Okta's own root-cause analysis states it plainly: HAR files "can contain sensitive data, including cookies and session tokens, that malicious actors can use to impersonate valid users" [1]. The attackers did not crack a password or defeat multi-factor authentication. They copied a proof of a login that had already cleared both, and replayed it. 1Password described the same thing happening in its tenant: "an unknown actor used the same Okta session from that HAR file to access the Okta administrative portal" [6].

~90M
Facebook accounts forced to re-login after a single access-token bug in 2018
90 min
Residual validity of a stolen Entra access token after the account is disabled and refresh tokens revoked
9 of 13
Top web frameworks with session-integrity flaws before any token is even stolen
~60%
Windows users whose device can back a non-exportable session key today
The surprise, up front

The reflexes after a session-theft incident, add MFA, cut the token lifetime, rotate the credential, do not change the one fact that made the theft work: the server still cannot tell the thief's copy from the owner's, because possession is the whole proof. Those controls shrink the window. Only binding the credential to something the thief cannot copy, a device key, a proof-of-possession key, a network context, changes the answer to "does this work for someone who is not you". And even binding, as the DBSC authors say themselves, has a documented ceiling.

What this guide covers: the session and access credentials that authenticate a request after login, for both human browser sessions and machine-to-machine calls, and the three families of response to theft: shrink the window, bind the credential, and cut the detection-to-revocation time. What it deliberately does not cover: the login itself (password strength, MFA factor choice, phishing-resistant enrolment), authorization logic once identity is established (covered in the sibling guide on deciding who may do what), and secret management for issuing credentials (see when the secret leaks).

Figure 1 · Where the copy enters

yes = you

copies

Login

Proof
issued

Client
holds it

Sent per
request

Verifies?

Granted

Malware /
HAR / bug

yes = you

copies

Login

Proof
issued

Client
holds it

Sent per
request

Verifies?

Granted

Malware /
HAR / bug

The bearer flow: a login produces a portable proof, and the server's only question on every later request is whether that proof verifies. Malware, an uploaded HAR file, or a backend routing bug can put a copy on the attacker's side of the line, and the server answers "yes = you" to both holders. Reconstructed from the Okta root-cause analysis.
Diagram source
02

How it is actually built

The reference shape shared by every serious answer to session theft: issue the credential bound to a holder, check the binding on use, and keep a channel that can revoke it before it expires.

The systems that take this seriously all converge on the same three places to intervene, even though they use different words and different cryptography. The clearest single statement of the problem comes not from a vendor blog but from a Kubernetes design document, KEP-1205, which set out to fix exactly this for machine identity. It names two of the three bindings directly: "JWTs are not audience bound. Any recipient of a JWT can masquerade as the presenter to anyone else," and "JWTs are not time bound. A JWT compromised via 1 or 2, is valid for as long as the service account exists" [12]. Audience, time, and, the third that KEP-1205 calls object binding, are the levers. Every design below is some combination of them.

The three intervention points

At issuance: bind to a holder

The credential is minted with a link to something the legitimate holder has and a thief does not: a private key the client proves possession of (DPoP, mTLS), a device key sealed in a TPM (DBSC), or an audience so a token for service A is useless at service B (KEP-1205). The link is the whole point; a bearer token has no such link.

Bound this way at: Kubernetes, Chrome DBSC, DPoP (RFC 9449)

On use: check the binding, not just the token

Each request re-proves the link. DPoP attaches a fresh signed proof per request; DBSC holds the request while it refreshes a short-lived cookie against a key challenge; Okta's post-breach control re-checks the network context and forces re-auth "if we detect a network change" [2]. The resource server's question changes from "is this token valid" to "is this token valid and presented by its holder".

Enforced this way at: Okta, Microsoft Entra

Off the request path: a revocation channel

Binding buys detection and a short residual window, not immunity, so a channel is needed to kill a session on a critical event before its lifetime ends. CAEP standardises this as a push event, session-revoked, sent from the identity provider to cooperating resources [16]. Without it, a self-validating token cannot be recalled; with it, revocation becomes an event rather than a wait.

Built this way at: OpenID Shared Signals (CAEP), Slack

Figure 2 · Reference architecture of a bound session

Change path

Every request

Sign-in / issuance

no

yes

revoke

Auth server

Bind to holder key
or device / audience

Resource server

Valid AND
proof of possession?

401 challenge

Serve

Critical event
disable, logout, risk

Revocation channel
CAEP push

Change path

Every request

Sign-in / issuance

no

yes

revoke

Auth server

Bind to holder key
or device / audience

Resource server

Valid AND
proof of possession?

401 challenge

Serve

Critical event
disable, logout, risk

Revocation channel
CAEP push

The common shape across DBSC, DPoP and CAEP deployments. The dashed revocation channel is the part most bearer designs omit, and the part that turns "the token is still valid" into "the token was killed at 14:02". Reconstructed from the DBSC explainer and the CAEP 1.0 spec.
Diagram source

The divergence points are worth naming because they are where an architect actually chooses. Browser sessions bind to a device key because a browser cannot be trusted to hold a per-site secret safely against local malware, so Chrome seals the key in a TPM and refreshes cookies behind it. API and service clients bind with proof-of-possession because they can hold a private key directly, which is what DPoP and mTLS assume. Machine workloads inside a cluster bind by audience and time, because KEP-1205's threat is a token leaking to the wrong in-cluster component, not a stolen laptop. The reference architecture is one shape; the cryptography under each box is chosen by what the holder can be trusted to keep.

03

The decisions that matter

Four forks, each with the option that won in the published record, the one that lost, and the condition under which the loser is the right call.

Decision 1: bearer token, or sender-constrained token?

Chosen
  • Sender-constrained: bind the token to a client key (mTLS or DPoP)
  • RFC 9700 makes it a SHOULD for access tokens and a MUST-or-rotate for refresh tokens [17]
Rejected
  • Plain bearer token, no binding
  • Stolen and leaked tokens are directly replayable, which is the whole failure class in section 4
Flips when
  • The token is low-value and very short-lived, and the binding infrastructure (key handling on both ends, mTLS at every proxy) costs more than the theft risk. DPoP's own adoption record shows this friction is real

Decision 2: self-validating JWT, or server-side session lookup?

Chosen
  • Opaque session id with a server-side store, when revocability matters
  • Lets logout and "sign out everywhere" actually invalidate
Rejected
  • Long-lived stateless JWT validated with no issuer contact
  • Cannot be revoked before expiry; the node-jsonwebtoken library has no destroy method for exactly this reason [10]
Flips when
  • Read scale makes a per-request lookup too expensive, so you accept a stateless token but pin the lifetime short and add a revocation channel (CAEP) to cover the gap

Decision 3: which binding, device / proof-of-possession / network context?

Chosen
  • Device key (DBSC) for browsers; proof-of-possession key (DPoP or mTLS) for API clients; network-context binding where the plane allows it (Okta)
Rejected
  • A single binding for everything
  • Network binding alone was bypassed at BeyondTrust when the attacker pivoted from console to API [5]
Flips when
  • The holder cannot keep a key (no TPM on ~40% of Windows devices [14], a legacy client with no mTLS): fall back to short lifetime plus a revocation channel rather than a binding the device cannot honour

Decision 4: prevent the copy, shrink the window, or cut the response time?

Chosen
  • All three, layered, because each has a ceiling the others cover
  • Slack automates response to minutes [22]; DBSC prevents the off-device copy; short lifetimes shrink the window
Rejected
  • Any one alone as "the fix"
  • Cloudflare's Thanksgiving breach was a shrink-only posture that failed on the credential nobody rotated [4]
Flips when
  • You cannot instrument detection (no anomaly signal, no revocation channel reaches the resource): then prevention (binding) carries more of the load, because you have no fast way to respond to a theft you cannot see
DecisionChosenRejectedBecauseEvidence
Token bindingSender-constrainedPlain bearerStolen tokens replay directlyRFC 9700, 2025
RevocabilityServer session or short JWT + channelLong-lived stateless JWTNo in-token way to recall itjsonwebtoken #113
Binding typeDevice / PoP / context by holderOne binding for allNetwork binding bypassed via APIBeyondTrust, 2023
Response strategyPrevent + shrink + detectAny one aloneEach control has a ceilingCloudflare, 2024

Figure 3 · Which binding for which holder

No (legacy, no TPM)

Yes

Browser

API / service

Can the client hold
a non-exportable key?

Short lifetime +
revocation channel
(CAEP)

Browser session
or API client?

Device-bind
(DBSC)

Proof-of-possession
(DPoP or mTLS)

Add context binding
where the plane allows

No (legacy, no TPM)

Yes

Browser

API / service

Can the client hold
a non-exportable key?

Short lifetime +
revocation channel
(CAEP)

Browser session
or API client?

Device-bind
(DBSC)

Proof-of-possession
(DPoP or mTLS)

Add context binding
where the plane allows

A decision tree whose leaves are actions, not "it depends". The first question is the one that decides everything downstream: can the client be trusted to hold a private key. Derived from the threat models stated in the DBSC and DPoP specs.
Diagram source
04

What broke in production

Seven public incidents, grouped by the class of failure. The design rule at the bottom of each card is the part to carry into a review.

Class A · The artefact leaked the live credential

Postmortem

Okta support HAR files, Oct 2023

AssumptionA troubleshooting file is diagnostic data, not a credential.
What happenedHAR files uploaded to support captured live session cookies; an attacker with access to the support system read them and replayed the sessions against customer tenants.
Blast radius134 customers had files accessed; five customer sessions were hijacked, including at Cloudflare and 1Password.
FixOkta shipped session token binding to network location, forcing re-auth on a network change [2].
Design ruleAny format that captures a request captures its credentials. Sanitise at capture, and treat a bearer session as spilled the moment it leaves the browser.
Postmortem

BeyondTrust console-to-API pivot, Oct 2023

AssumptionA policy that constrains admin-console sessions constrains the identity.
What happenedA custom console policy blocked the stolen session, so the attacker used the same cookie to drive admin API actions instead, which policy could not gate.
Blast radiusContained: detected and responded to within 30 minutes, no customer impact.
FixBeyondTrust reported the gap to Okta; binding must sit on the credential, not one front door.
Design ruleBind the credential, not a single interface. A control on the console that the API ignores is not a control on the session.

Class B · Shrinking was mistaken for binding

Postmortem

Cloudflare Thanksgiving breach, Nov 2023

AssumptionThe credentials stolen in the Okta breach were unused, so they did not need rotating.
What happenedOne service token and three service accounts, unrotated because "mistakenly it was believed they were unused", were used to reach Cloudflare's Atlassian systems weeks later.
Blast radiusResponse rotated 5,000 credentials and triaged thousands of systems; no customer data affected.
FixRotate every exposed credential regardless of believed use; a bearer credential you did not kill is a bearer credential still working.
Design rule"Probably unused" is not a revocation state. If you cannot prove a leaked credential is dead, it is alive.
Postmortem

Storm-0558 forged tokens, 2023

AssumptionA signing key can be long-lived if it is well protected, and its misuse would be detected.
What happenedA 2016 MSA consumer signing key that "should have been revoked" was used to forge access tokens for Exchange Online; Microsoft still "does not know how or when" the key was obtained.
Blast radiusForged tokens for 22 enterprise organisations and 503 personal accounts; detected by a customer, not the vendor.
FixThe CSRB called for an overhaul of key lifecycle and detection; a token factory needs revocation and misuse detection as first-class controls.
Design ruleA signing key is the ultimate bearer credential: whoever holds it mints identities. Its lifetime and its revocation path matter more than any single token's.

Class C · The container failed with no attacker at all

Postmortem

GitHub session misrouting, Mar 2021

AssumptionA session cookie only ever reaches the browser it was issued to.
What happenedA backend race condition "could have misrouted a user's session to the browser of another authenticated user, giving them the valid and authenticated session cookie for another user".
Blast radiusFewer than 0.001% of sessions, but the only safe response was to invalidate every session created before the patch window.
FixPatched the race and population-invalidated sessions; a bearer cookie in the wrong hands is indistinguishable from theft.
Design ruleBecause a bearer session is portable, the blast radius of any bug that moves one is "everyone", so revocation must be population-scale and fast.
Postmortem

Facebook "View As" access tokens, Sep 2018

AssumptionAn access token is exposed only to the account it belongs to.
What happenedA bug in the "View As" feature emitted access tokens for the account being viewed, letting an attacker collect tokens that were full bearer credentials.
Blast radius~50M accounts known affected; ~40M more reset precautionarily; about 90M forced re-logins.
FixReset the exposed and possibly-exposed tokens; the precautionary 40M shows the true blast radius of a bearer leak is everything that might have been exposed.
Design ruleYou cannot scope the response to known-stolen bearer tokens, because you cannot tell which copies exist. Plan revocation for the superset.

Class D · Binding and revocation have a ceiling

Reported gap

Entra CAE 90-minute window, 2026

AssumptionRevoking refresh tokens and disabling an account stops an attacker immediately.
What happenedA locally validated access token "remains fully usable for its entire lifetime even if security-critical events occur"; disabling the user still leaves "a gap of up to 90 minutes", and only first-party Microsoft apps are CAE-capable.
Blast radiusEvery non-CAE resource; the revocation channel does not reach third-party apps in the estate.
FixShorten access-token lifetime and widen CAE coverage; a revocation channel only helps the resources that subscribe to it.
Design ruleMeasure the residual window (time from revoke to enforced) as a real number per resource, not as "near real time". Uncovered resources have the full token lifetime as their window.

Three failure classes, one root

Classes A through C are the same bug wearing different clothes: a portable proof reached a holder who was not the user, whether by theft, by pivot, or by a routing race, and the server had no way to notice. Class D is the honest limit of the answer: even after you bind and add a channel, there is a residual window and a coverage map. Naming that window, per credential and per resource, is the number the reader should leave with.

A note on evidence: the containment successes (BeyondTrust's 30 minutes, GitHub's population invalidation) are as instructive as the losses. They are what a fast revocation channel plus a short window actually buys.

Figure 4 · The failure path: Okta HAR to session hijack

Okta admin planeAttackerOkta support portalAdmin (victim)Okta admin planeAttackerOkta support portalAdmin (victim)HAR captured a livesession cookiepossession is theonly checkUpload HAR to troubleshootRead stored HAR viacompromised accountPresent the copied sessioncookie200 OK, you are the admin
Okta admin planeAttackerOkta support portalAdmin (victim)Okta admin planeAttackerOkta support portalAdmin (victim)HAR captured a livesession cookiepossession is theonly checkUpload HAR to troubleshootRead stored HAR viacompromised accountPresent the copied sessioncookie200 OK, you are the admin
A sequence diagram of the mechanism, showing where the copy crosses to the attacker and why the admin plane cannot object: possession is the only check it performs. Reconstructed from the 1Password and Okta accounts.
Diagram source
05

Numbers you can plan against

Blast radius, residual windows, binding coverage and cost, each with its source and date. Vendor claims are labelled as claims.

MetricValueAtContextAs ofSource
Re-logins from one token bug~90MMetaMeasured blast radius of a bearer-token leak, incl. precautionary resets2018[8]
Sessions misrouted by a backend race<0.001%GitHubMeasured; still required population invalidation2021[7]
Residual validity after revoke (non-CAE)up to 90 minMicrosoft EntraReported; access token keeps working post-event2026[24]
CAE access-token lifetimeup to 28 hMicrosoft EntraVendor: lifetime traded up for a revocation channel2026[26]
Detection-to-session-killdays/hrs → minutesSlackReported outcome of automated response (AER)2025[22]
Windows devices able to back a key~60%Chrome / GoogleMeasured TPM availability, growing2025[13]
TPM signing latency on request pathP50 200ms / P95 600msChrome / GoogleMeasured; error rate ~0.001%2025[14]
Frameworks with session-integrity flaws9 of 13USENIX studyMeasured across top web frameworks2023[19]
Recaptured identity records (yearly)43.7B → 53.3BSpyCloudVendor claim; scale of the stolen-credential economy2025[28]
Unrotated creds behind Cloudflare breach1 token + 3 acctsCloudflareMeasured; response rotated 5,0002023[4]

Figure 5 · The states an operator actually sees

issued

request, proof checked

critical event

channel reaches resource

lifetime ends

Active

Revoked

Enforced

Expired

Residual window: the token
still works until Enforced
or Expired, whichever comes first

issued

request, proof checked

critical event

channel reaches resource

lifetime ends

Active

Revoked

Enforced

Expired

Residual window: the token
still works until Enforced
or Expired, whichever comes first

The residual window is the gap between Revoked and Enforced. A resource with a revocation channel closes it in seconds; a resource without one waits for Expired, so its window is the whole token lifetime. This is the number to measure per resource, framed by the Entra CAE analysis.
Diagram source
Read these carefully

The 28-hour CAE lifetime and the SpyCloud identity-record count are vendor figures; treat the first as a design choice Microsoft made (longer lifetime in exchange for a channel) and the second as a directional claim, not an independent measurement. The 90-minute gap is the number to internalise: it is the residual window on a resource that has a revocation channel. A resource without one has the full token lifetime as its window, which is why "shorten the lifetime" is still load-bearing even after you add CAEP. The TPM latency figures matter because binding puts a signing operation on the refresh path; budget for the P95, not the P50.

06

The evidence wall

Every source behind this page, graded and filterable. The full ledger with one row per claim and the copied supporting quote ships beside this file as sources.md.

How these were fetched

This session's network egress proxy resolved raw.githubusercontent.com and answered github.com with 403 for every path, so the specs and design docs (KEP-1205, the DBSC explainer, the CAEP spec, the OAuth security BCP) were read directly from source. Every other host below (Okta, Cloudflare, BeyondTrust, 1Password, GitHub's blog, Meta, CISA, USENIX, IETF, Microsoft, Slack) was refused by the proxy at fetch time; their text and quotes were retrieved through this session's web-search retrieval, which returns page content, not from memory. The link checker reports those hosts as unreachable rather than broken. That is an evidence limit worth stating: the quotes are real and dated, but a reader with open network access should re-verify the ones on blocked hosts against the primary page.

PostmortemOkta2023-11

Support case system root-cause analysis

HAR files uploaded for troubleshooting carried live session tokens usable to impersonate valid users; 134 customers affected.

Carry forwardAny capture format captures credentials; a bearer session is spilled the moment it leaves the browser.
sec.okta.com/articles/2023/11/…root-cause
PostmortemOkta2023-11

October incident, recommended actions

Okta's durable fix binds admin sessions to network location and forces re-auth on a network change.

Carry forwardBinding the session to context is the shipped answer, not just shorter lifetimes.
sec.okta.com/articles/october-…actions
PostmortemCloudflare2023-10

How Cloudflare mitigated yet another Okta compromise

The stolen support token was used against Cloudflare; the first lesson drawn is that the session token itself is the crown jewel.

Carry forward"Protect your session tokens" and short-lived admin sessions, stated as the top lesson by a target.
blog.cloudflare.com/how-cloudflare-mitigated-yet-another-okta-compromise
PostmortemCloudflare2024-02

Thanksgiving 2023 security incident

One service token and three service accounts, unrotated because believed unused, were replayed weeks later; response rotated 5,000 credentials.

Carry forward"Probably unused" is not a revocation state; an un-killed leaked credential is a working one.
blog.cloudflare.com/thanksgiving-2023-security-incident
PostmortemBeyondTrust2023-10

Discovers breach of Okta support unit

A console policy blocked the stolen session, so the attacker pivoted to admin API actions the same cookie authorised; detected within 30 minutes.

Carry forwardBind the credential, not one interface; a control the API ignores is no control.
beyondtrust.com/blog/entry/okta-support-unit-breach
Postmortem1Password2023-10

Okta Support System incident and 1Password

An actor used the session from an uploaded HAR file to reach the Okta admin portal minutes after upload.

Carry forwardSecond independent account of the same replay mechanism; corroboration, not a one-off.
1password.com/blog/okta-incident
PostmortemGitHub2021-03

A bug in handling of authenticated sessions

A backend race could misroute a valid session cookie to another authenticated user's browser; all prior sessions were invalidated.

Carry forwardA portable session means any bug that moves one has a blast radius of everyone; revocation must be population-scale.
github.blog/2021-03-08-github-security-update…
PostmortemMeta2018-09

Security Update (View As access tokens)

A feature bug emitted other accounts' access tokens; ~50M reset plus ~40M precautionary, ~90M re-logins.

Carry forwardYou cannot scope the response to known-stolen bearer tokens; plan revocation for the superset.
about.fb.com/news/2018/09/security-update
PostmortemCISA / CSRB2024-04

Review of the Summer 2023 MEO Intrusion

Storm-0558 forged Exchange Online tokens with a 2016 signing key that should have been revoked; Microsoft still cannot say how it was stolen.

Carry forwardA signing key is a token factory; its lifetime, revocation and misuse detection outrank any single token's.
cisa.gov/…/CSRBReviewOfTheSummer2023MEOIntrusion508.pdf
Sourceauth0 / community2015+

node-jsonwebtoken issue #113, "Destroy token"

A decade-long request for a token-destroy method; there is none, because a self-validating token has no revocation channel.

Carry forwardStateless revocability requires added server state; the library will not save you from the design choice.
github.com/auth0/node-jsonwebtoken/issues/113
Sourceauth0 / community2017+

node-jsonwebtoken issue #375, invalidate on logout

Recurring "how do I log out" thread with the same answer: rotate the secret (revokes everyone) or keep a per-token record.

Carry forwardLogout is not free for a stateless token; "sign out everywhere" needs the state you tried to avoid.
github.com/auth0/node-jsonwebtoken/issues/375
Decision recordKubernetes SIG-AuthGA 2021

KEP-1205, Bound Service Account Tokens

Names the bearer problem for machine identity and its three bindings: audience, time, object. The clearest statement in the corpus.

Carry forward"A JWT compromised is valid for as long as the service account exists" unless you bind and time-limit it.
github.com/kubernetes/enhancements/…/1205-bound-service-account-tokens
Decision recordW3C / Google2025-26

Device Bound Session Credentials explainer

Binds a browser session to a non-exportable device key so a copied cookie fails off-device; states its own non-goals and ceiling.

Carry forwardBinding stops the off-device copy but not an attacker with ongoing local access; the refresh interval sets the residual window.
github.com/w3c/webappsec-dbsc
Decision recordOpenID / Shared Signals2025-08

Continuous Access Evaluation Profile 1.0

Standardises the push channel a resource needs to learn a session was revoked before token expiry, including the session-revoked event.

Carry forwardRevocation becomes an event, not a poll, but only for resources that subscribe.
github.com/openid/sharedsignals/blob/main/openid-caep-1_0.md
Decision recordIETF OAuth WG2025-01

RFC 9700, OAuth 2.0 Security BCP

The standard's answer to token theft: sender-constrain access tokens, and rotate refresh tokens with replay detection or sender-constrain them.

Carry forwardRotation with reuse detection revokes on replay; sender-constraint makes the copy inert without the key.
rfc-editor.org/rfc/rfc9700.html
Decision recordIETF OAuth WG2023-09

RFC 9449, DPoP

Application-layer sender-constraint: the client proves possession of a key per request, so a copied token without the key is inert.

Carry forwardThe API-client equivalent of device binding; the friction is key handling on both ends.
rfc-editor.org/rfc/rfc9449.html
PaperUSENIX / TU Wien2023-08

Cookie Crumbles: Breaking and Fixing Web Session Integrity

Cross-browser and framework study finding session-integrity flaws in 9 of 13 top frameworks; contributed to 12 CVEs.

Carry forwardThe session container is fragile before any theft; fixation and forgery are live even with good token hygiene.
usenix.org/…/usenixsecurity23-squarcina.pdf
PaperUSENIX ;login: / Google2014-12

BeyondCorp: A New Approach to Enterprise Security

The strategic answer: stop trusting network position, re-decide every request from device and user state.

Carry forwardAccess "regardless of network location" reframes a stolen credential as one signal among many, not a master key.
usenix.org/…/login_dec14_02_ward.pdf
TalkIdentiverse2023-06

CAEP Deep Dive: Session Revocation and Authorization

The engineers building the revocation standard frame it as closing the gap between "access changed" and "the token stops working".

Carry forwardThe people who wrote CAEP treat the residual window as the metric to drive down.
identiverse.com/video/caep-deep-dive-…
Eng blogSlack2025-09

Building Slack's Anomaly Event Response

Automated detection terminates sessions on high-confidence anomalies, cutting response from days/hours to minutes; a stale cookie is a signal.

Carry forwardIf you cannot stop the copy, drive detection-to-kill down; automation makes it a minutes problem.
slack.engineering/building-slacks-anomaly-event-response
Eng blogtextslashplain2023-10

Protecting Auth Tokens

A stolen post-login token can be worth more than a password, because it already represents completion of the full login including MFA.

Carry forwardDo not treat a session credential as lower-value than a password; it is proof MFA already passed.
textslashplain.com/2023/10/23/protecting-auth-tokens
Eng blogERNW / insinuator2026-09

Token Theft in Entra ID, Part 2: CAE

Even with CAE, a locally validated access token stays usable up to 90 minutes after a critical event, and only first-party apps are CAE-capable.

Carry forwardMeasure the residual window per resource; uncovered resources have the full lifetime as their window.
insinuator.net/2026/09/token-theft…part-2…
Eng blogLydia Graslie2026

Where Continuous Access Evaluation Stops Being Continuous

CAE's coverage is uneven and licence-gated: the critical-event half is broad, the policy and risk halves need P1 and P2.

Carry forward"Near real time" has a coverage map and a price tag; verify what your tier actually enforces.
lydiagraslie.substack.com/p/where-continuous-access-evaluation
VendorMicrosoft2026

Continuous access evaluation in Microsoft Entra

Documents the trade: token lifetime up to 28 hours in exchange for a revocation channel keyed on critical events.

Carry forwardA longer lifetime is only safe if the channel actually reaches the resource; check both halves.
learn.microsoft.com/…/concept-continuous-access-evaluation
VendorGoogle2026-04

Protecting Cookies with Device Bound Session Credentials

DBSC shipped to Chrome 146 on Windows, keys TPM-backed; the binding approach reached a consumer browser at scale.

Carry forwardDevice binding is now shippable, but default-off until the site opts in and the device can hold a key.
security.googleblog.com/2026/04/protecting-cookies-with-device-bound.html
Case studySpyCloud2025

2025 Annual Identity Exposure Report

Recaptured identity records grew from 43.7B to 53.3B in a year (vendor figure), sizing the stolen-credential economy.

Carry forwardDirectional only, but the economy is large enough that "make the copy useless" beats "hope it is not stolen".
spycloud.com/blog/2025-annual-identity-exposure-report
07

Build a miniature, then productionise it

Seven rungs from a revocable session to a bound one with a measured residual window. The line from toy to real is crossed at rung 4.

Opaque session id with a server store

Issue a random session id, keep session state server-side, and make logout delete the record. Do not start with a stateless JWT.

Done when: logging out in one tab makes the other tab's next request 401.  Teaches: revocability is a property of where the truth lives, not of the token format.

Short lifetime plus refresh rotation with reuse detection

Give access tokens a short life and rotate refresh tokens on every use; if an old refresh token reappears, revoke the whole chain, as RFC 9700 requires.

Done when: replaying a used refresh token kills the session instead of minting a new one.  Teaches: rotation turns a stolen refresh token into a detectable event.

"Sign out everywhere" and a revocation list

Add a per-user revocation record and a way to invalidate all of a user's sessions at once, the control GitHub and Meta both had to exercise at population scale.

Done when: one admin action invalidates every session for a user across devices.  Teaches: the blast radius of a bearer leak is the population, so revocation must be too.

Sender-constrain the token (proof-of-possession)

Cross into production shape: bind the token to a client key with DPoP, so a request must carry a fresh signed proof and a copied token alone is inert.

Done when: replaying a captured token from a different client (no key) is rejected.  Teaches: binding changes the server's question from "valid?" to "valid and yours?".

Device-bind a browser session

Adopt a DBSC-style flow: a device key seals the session, cookies are short-lived and refreshed behind a key challenge. Handle the device that has no TPM.

Done when: exporting the cookie to another machine and replaying it fails.  Teaches: the ~40% without a key is a design case, not an edge case.

Add a revocation channel to the resources

Wire a CAEP-style push so a critical event (disable, password reset, risk) reaches resource servers, not just the issuer, and measure which resources subscribe.

Done when: disabling a user enforces at a resource before the token expires.  Teaches: a channel only helps subscribers; the rest have the full lifetime as their window.

Instrument the residual window and red-team it

Emit a metric for time-from-revoke-to-enforced per resource, and run the attack yourself: steal your own cookie, prove it is inert off-device and dies fast on revoke.

Done when: you can quote the residual window as a number per resource, like Entra's 90 minutes.  Teaches: the ceiling is a measurement, not a feeling.

08

Keep hunting

The queries that surfaced this material. The page goes stale in a year; the method does not.

Incidents and replay mechanics

  • okta HAR file session token root cause 2023
  • cloudflare thanksgiving 2023 incident "failed to rotate" service token
  • github "authenticated sessions" race condition invalidated all sessions
  • facebook "view as" access tokens 90 million reset security update
  • CSRB Storm-0558 forged tokens signing key "should have been revoked"

Bindings and revocation standards

  • KEP-1205 bound service account tokens "not time bound"
  • device bound session credentials explainer TPM non-goals
  • CAEP session-revoked openid shared signals spec
  • RFC 9700 refresh token rotation reuse detection sender-constrained
  • continuous access evaluation "up to 90 minutes" gap first-party

The design argument, in the open

  • node-jsonwebtoken issue destroy token invalidate logout
  • DPoP RFC 9449 adoption production who supports
  • "cookie crumbles" usenix session integrity frameworks
  • token binding chrome "intent to remove" why low adoption

Operational response

  • slack anomaly event response automatic session termination minutes
  • beyondcorp usenix login access "regardless of network location"
  • infostealer stolen session cookies statistics annual report
  • okta session token binding network location admin console
09

References

  1. Okta, Unauthorized Access to Okta's Support Case Management System: Root Cause Okta Security, 2023-11. Checked 2026-09-30 (host unreachable from this session; retrieved via search).
  2. Okta, October Customer Support Security Incident: Recommended Actions Okta Security, 2023-11. Checked 2026-09-30 (retrieved via search).
  3. Cloudflare, How Cloudflare mitigated yet another Okta compromise Cloudflare, 2023-10-20. Checked 2026-09-30 (retrieved via search).
  4. Cloudflare, Thanksgiving 2023 security incident Cloudflare, 2024-02-01. Checked 2026-09-30 (retrieved via search).
  5. BeyondTrust, BeyondTrust Discovers Breach of Okta Support Unit BeyondTrust, 2023-10-20. Checked 2026-09-30 (retrieved via search).
  6. 1Password, Okta Support System incident and 1Password 1Password, 2023-10-23. Checked 2026-09-30 (retrieved via search).
  7. GitHub, GitHub security update: a bug related to handling of authenticated sessions GitHub, 2021-03-08. Checked 2026-09-30 (retrieved via search).
  8. Meta, Security Update Meta (Facebook), 2018-09-28. Checked 2026-09-30 (retrieved via search).
  9. CISA / Cyber Safety Review Board, Review of the Summer 2023 Microsoft Exchange Online Intrusion CISA, 2024-04-02. Checked 2026-09-30 (retrieved via search).
  10. auth0/node-jsonwebtoken, Issue #113: Destroy token GitHub, opened 2015-07-23. Checked 2026-09-30 (host returns 403 for all paths).
  11. auth0/node-jsonwebtoken, Issue #375: invalidate on logout GitHub, opened 2017. Checked 2026-09-30 (host returns 403 for all paths).
  12. Kubernetes, KEP-1205: Bound Service Account Tokens Kubernetes SIG-Auth, GA in 1.22 (2021). Read from raw source 2026-09-30.
  13. W3C / Google, Device Bound Session Credentials explainer W3C WebAppSec. Read from raw source 2026-09-30.
  14. OpenID Foundation, Continuous Access Evaluation Profile (CAEP) 1.0 OpenID Shared Signals WG, 2025-08-29. Read from raw source 2026-09-30.
  15. IETF, RFC 9700: Best Current Practice for OAuth 2.0 Security IETF OAuth WG, 2025-01. Checked 2026-09-30 (retrieved via search).
  16. IETF, RFC 9449: OAuth 2.0 Demonstrating Proof of Possession (DPoP) IETF OAuth WG, 2023-09. Checked 2026-09-30 (retrieved via search).
  17. Squarcina et al., Cookie Crumbles: Breaking and Fixing Web Session Integrity USENIX Security, 2023-08. Checked 2026-09-30 (retrieved via search).
  18. Ward & Beyer, BeyondCorp: A New Approach to Enterprise Security USENIX ;login:, 2014-12. Checked 2026-09-30 (retrieved via search).
  19. Cappalli & Tulshibagwale, CAEP Deep Dive: Implementing Session Revocation and Authorization Identiverse, 2023-06-01. Checked 2026-09-30 (retrieved via search).
  20. Slack, Building Slack's Anomaly Event Response Slack Engineering, 2025-09-04. Checked 2026-09-30 (retrieved via search).
  21. Eric Lawrence, Protecting Auth Tokens textslashplain, 2023-10-23. Checked 2026-09-30 (retrieved via search).
  22. ERNW, Token Theft in Microsoft Entra ID (Part 2 of 4): Continuous Access Evaluation insinuator.net, 2026-09. Checked 2026-09-30 (retrieved via search).
  23. Lydia Graslie, Where Continuous Access Evaluation Stops Being Continuous Substack, 2026. Checked 2026-09-30 (retrieved via search).
  24. Microsoft, Continuous access evaluation in Microsoft Entra Microsoft Learn, living document, 2026. Checked 2026-09-30 (retrieved via search).
  25. Google, Protecting Cookies with Device Bound Session Credentials Google Security Blog, 2026-04. Checked 2026-09-30 (retrieved via search).
  26. SpyCloud, 2025 Annual Identity Exposure Report SpyCloud, 2025. Checked 2026-09-30 (retrieved via search). Vendor figure.