Beta

Create a tenant

A new tenant starts with its own users, OAuth settings, audit history and logs. You are its first Tenant Admin.

BTL Admin

Revoking access and sharing security events

Ending access you did not grant

On Day 2, at 08:50, an alert reached Cedar Inc.'s security team. It combined three weak signals on Riley's account: a sign-in from a hosting provider, a new authenticator added minutes later, and a network Riley had never used. Quinn, who led the investigation, confirmed that someone other than Riley had been using the account since the previous morning. Once the records the investigation needed were preserved, that person's access had to end, and it was spread across more places than a single account setting.

The familiar tools are signing out everywhere and changing the password. Signing out everywhere invalidates every session record the identity provider holds for the account, along with the refresh tokens it issued, the server-side ending that Staying signed in called for. Changing the password helps only if the change also ends existing sessions. The attacker had not needed Riley's password since 09:14 the previous day, because they had the session the relay captured. Providers that record which version of the credential each session was created with can end every older session when the password changes, usually keeping the one that made the change.

Both actions reach only what the identity provider controls. Each application the account was used to open through single sign-on created a session of its own, as Trust across systems explains, and access tokens already issued to applications are checked by the APIs that receive them, not by the provider. Signing out everywhere at the provider leaves those in place until something else ends them.

Some of what the attacker left is not a session at all: the authenticator app they registered, the mail access they granted to a third-party app called "Invoice Sync", and a mail forwarding rule. No sign-out removes these. They need their own removal, which How attackers stay in and Containing and recovering cover.

Each kind of access ends differently

Whether a revocation takes effect at once depends on who checks the credential, and how. A session at the identity provider is a record in the provider's own storage. Each request looks it up, so deleting the record ends the session at the next request.

An application's own session works the same way, except that the record belongs to the application and the provider cannot delete it. The application learns that something changed only when the person goes back to the provider, when its own session expires, or when someone tells it.

A refresh token is checked by the authorization server every time it is used, so revoking it takes effect at the next refresh. Access tokens come in two kinds. A reference token is an opaque value that the API looks up with the authorization server through introspection, so revocation takes effect at the next lookup. A self-contained token, usually a signed JWT, carries its claims and expiry inside it. The API validates it locally with the issuer's public key and never asks whether it has been revoked, so it keeps working until it expires. The table below repeats the comparison from Token revocation, with sessions added.

When revoking access takes effect
Kind of accessWho checks itWhen revocation takes effect
Session at the identity providerThe provider, on every requestAt the next request
Session at an applicationThe application, against its own recordWhen the application's session expires, unless the application is told sooner
Refresh tokenThe authorization server, at each refreshAt the next refresh
Reference access tokenThe API, through introspectionAt the next lookup, after any time the API caches the answer
Self-contained access tokenThe API, locally, from its signature and expiryWhen the token expires

The gap before a token expires

The time between revoking access and the moment every copy stops working is the revocation gap. For a self-contained access token, it can be the token's whole lifetime. Suppose the photo application's API accepts self-contained tokens that last 30 minutes, and a customer's account is disabled at 13:45. Refresh fails from then on, so no new tokens are issued, but a token issued at 13:40 keeps working until 14:10.

There are two main ways to shrink the gap. Short lifetimes bound it directly: a token that lasts five minutes cannot outlive a revocation by more than five minutes, at the cost of more frequent refreshes. Introspection closes it for tokens the API looks up on each request, at the cost of a call to the authorization server every time and a dependency on that server being available. Many APIs cache introspection answers briefly, which brings back a small gap in exchange for speed. Token revocation and Token introspection describe both endpoints.

A common middle path uses short-lived self-contained tokens for ordinary calls and a fresh check for the operations that matter most, such as changing payment details. The gap is then a few minutes for reading data and close to nothing for the riskiest actions.

Application sessions are often the widest gap of all. A session an application created through single sign-on might last a full working day, and short token lifetimes do nothing to shorten it. Closing that gap needs the identity provider to tell the application what changed. For applications that sign people in with OpenID Connect, Back-channel logout already does this for one kind of change: the provider sends each application a signed logout token, server to server, naming the sessions to end.

Telling other systems what changed

Suppose Cedar's staff sign in to an expense service run by another company, at expenses.example.test, through Cedar's identity provider. When Cedar ends Riley's sessions, the expense service cannot know unless Cedar sends word. A logout token would end the expense sessions, but Cedar also wants to say why, and to report changes that end no session at all, such as a changed credential or a laptop that no longer meets policy. The OpenID Shared Signals Framework (SSF) standardizes that broader conversation. A transmitter, here Cedar's identity provider, sends events about changes to receivers, here the expense service, over a stream the two configured in advance. Events are either pushed to the receiver as they happen or collected by the receiver when it polls.

Two profiles define the events. The Continuous Access Evaluation Profile (CAEP) covers changes that affect current sessions, such as a revoked session, a changed credential, a change in how strongly the person signed in, or a device that no longer meets policy. Risk Incident Sharing and Coordination (RISC) covers events about the account itself, such as a credential known to be compromised, a disabled account, or a changed identifier. Events can travel in both directions, so an application that notices suspicious activity can tell the identity provider too.

Quinn asks Cedar's identity provider to revoke Riley's sessions. The provider ends its own sessions and refresh tokens, then pushes a signed security event to the expense service saying that the session for Riley's issuer and subject was revoked. The expense service verifies the signature with Cedar's published key, checks the issuer, audience and event identifier, and answers 202 Accepted. It maps the issuer and subject to Riley's account and ends its expense sessions. A later request from a browser with an existing session for Riley is refused and must sign in again. Quinn asks Cedar's identity provider to revoke Riley's sessions. The provider ends its own sessions and refresh tokens, then pushes a signed security event to the expense service saying that the session for Riley's issuer and subject was revoked. The expense service verifies the signature with Cedar's published key, checks the issuer, audience and event identifier, and answers 202 Accepted. It maps the issuer and subject to Riley's account and ends its expense sessions. A later request from a browser with an existing session for Riley is refused and must sign in again.
The expense service verifies the event before acting on it. Without the event, its session for Riley would have lasted until it expired.

Each event travels as a Security Event Token (SET), a signed JWT defined in RFC 8417. Here is a fictional one, decoded so its fields are readable:

Header
{
  "alg": "ES256",
  "kid": "cedar-events-2026-01",
  "typ": "secevent+jwt"
}

Payload
{
  "iss": "https://login.cedar.example",
  "aud": "https://expenses.example.test",
  "jti": "evt-5b1d93e0",
  "iat": 1773221400,
  "sub_id": {
    "format": "iss_sub",
    "iss": "https://login.cedar.example",
    "sub": "usr_4182"
  },
  "events": {
    "https://schemas.openid.net/secevent/caep/event-type/session-revoked": {
      "event_timestamp": 1773221340,
      "initiating_entity": "admin"
    }
  }
}

The type secevent+jwt keeps a security event from being mistaken for an ID token or access token signed by the same provider, as logout+jwt does for a logout token, and kid identifies the signing key. In the payload, iss names the transmitter and aud names the receiver the event is meant for. jti is unique to this event, so the receiver can recognize it if it arrives twice. sub_id identifies the subject by the issuer and subject identifier the expense service already stores for Riley's account, not by an email address. The events claim holds one event: its type is the CAEP URL for a revoked session, event_timestamp records when the revocation happened at Cedar, a minute before the token was issued, and initiating_entity says an administrator did it, rather than Riley or an automatic policy. It carries no email address, password, or free-text reason, only what the receiver needs to act.

An event can change someone's access, so the receiver checks it as carefully as a sign-in. It verifies the signature with the transmitter's published keys, accepts only the issuer it configured for this stream and only events addressed to itself, ignores identifiers it has already processed, and finds the account through the issuer and subject it already stores. An endpoint that accepted any well-formed event would let anyone sign people out at will, or send events that change how accounts are treated. Even a genuine event is a report, not a command: it says what happened at the transmitter, and the receiver's own policy decides what to do about it.

Deciding what a change should end

Not every change should end everything. Ending all sessions whenever anything changes signs people out so often that they stop paying attention, and it floods the help desk. Ending too little leaves an attacker in place. The useful question for each change is what it says about the access that already exists.

  • A password the person changed themselves: end their other sessions and refresh tokens, and keep the session that made the change.
  • A suspected compromise: block new sign-ins, end every session and refresh token, send events to the applications that receive them, and remove the sign-in methods and app grants the attacker added.
  • An account disabled because someone left: end everything, everywhere, including application sessions.
  • A role removed: check authorization again at each application. Signing the person out is often unnecessary, but a token that carries the old role should not outlive the change by long.
  • A new sign-in method added: usually nothing needs to end, but the owner should be told, and a method added from an unfamiliar network deserves a closer look.

Riley's case was the second kind. Each revocation and each event sent or received belongs in the records too, with who triggered it and why, so that an investigation can later show when every kind of access actually ended.

Try it in the Lab

PUT IT INTO PRACTICE

Check your understanding

Try these questions before moving on. If an answer isn't right, use the feedback and try again.

0 of 2 answered correctly

Enable JavaScript to answer these questions and save progress in this browser.

QUESTION 1 OF 2An account is disabled at 10:00. An application accepts self-contained access tokens that last one hour, and it handles no security events. When does the account's access to that application end?

QUESTION 2 OF 2An application accepts any well-formed security event posted to its endpoint, without checking the signature or the issuer. What can an attacker do?

We value your privacy

We use cookies and similar technologies to enhance your browsing experience, and analytics to understand our traffic. By clicking "Allow All", you consent to optional analytics. Cookie Policy

Learn identity