Security · 2026-04-28
SSF and CAEP: Closing the Cross-IdP Revocation Latency Gap
By J. W. Bouckaert
Revocation across identity providers
Within one identity provider, revoking a session is a database update. Most organizations run several: one for workforce sign-on, one for Microsoft 365, an in-house OpenID Connect provider for an older product, and increasingly a broker for agent identities. When a credential is compromised or a phone number shows signs of a SIM swap, every relying party that trusts any of those providers needs to learn about it.
The OpenID Shared Signals Framework (SSF) and the Continuous Access Evaluation Profile (CAEP) standardize that propagation. The OpenID Foundation approved both as Final Specifications on September 2, 2025; the final documents are dated August 29, 2025.
This article covers what SSF and CAEP standardize, how they compare with token introspection, and how PasskeyBridge implements both the receiving and transmitting sides.
Introspection compared with pushed events
Before shared signals, a relying party learned about revocation through OAuth token introspection (RFC 7662), calling the authorization server to ask whether a token is still active, or by waiting for the access token to expire.
| Property | Token introspection | SSF and CAEP |
|---|---|---|
| When the relying party learns of revocation | On its next introspection call, or at token expiry if responses are cached | When the event is delivered |
| Calls per protected request | One, unless cached | None |
| Load on the identity provider | Grows with requests | Grows with events |
| Standing relationship needed | No | Yes, a configured stream |
Introspection works and needs no setup between the parties. Its cost is a call on each request, and caching that call reintroduces delay. Pushed events remove the per-request call, at the cost of configuring and maintaining a stream.
SSF
SSF is the transport. It defines how events get from a Transmitter, the system that knows about the event, to a Receiver, the system that needs to act on it. It does not define what the events mean.
- Streams. A Transmitter and Receiver configure a stream through management endpoints. The Transmitter publishes its configuration at a well-known
/.well-known/ssf-configurationlocation, and the endpoint URLs come from that document. - Subjects. A stream can be limited to the subjects the Receiver cares about, such as users, sessions or devices.
- Security Event Tokens. Events are sent as Security Event Tokens (RFC 8417): signed JWTs carrying event types and their payloads.
- Delivery. Two methods are defined: HTTP push (RFC 8935), where the Transmitter posts each token to the Receiver, and HTTP poll (RFC 8936), where the Receiver fetches them.
SSF can carry CAEP events, RISC events or other event types.
CAEP
CAEP defines events for changes in session and credential state. The ones PasskeyBridge processes:
| Event type | Meaning |
|---|---|
session-revoked | A session was ended |
token-claims-change | Claims on an active token changed, such as a role or group |
credential-change | A credential was created, revoked, updated or deleted |
assurance-level-change | The subject's authentication assurance level changed |
device-compliance-change | A device's compliance status changed |
risk-level-change | The Transmitter's risk assessment of a subject changed |
The Transmitter is responsible for delivering events. Each Receiver decides what to do with them under its own policy.
Receiving events in PasskeyBridge
The shield-sse-caep function accepts events from streams a tenant has configured with an upstream provider. For each delivered token it:
- Verifies the signature against the stream's configured JSON Web Key Set, accepting ES256, ES384 and RS256. Key sets are cached for five minutes.
- Checks the claims required by RFC 8417, rejecting tokens whose
iatis more than 60 seconds in the future or more than 24 hours old. - Rejects duplicates through a unique index on tenant, issuer and
jti, so a redelivered token is reported as a duplicate and not processed twice. - Rate-limits deliveries to 60 per minute for each sending address, keyed by a keyed hash of the IP address.
It then maps the event to a cascade signal:
| Inbound event | Signal | Class |
|---|---|---|
session-revoked | account_takeover | Hard |
credential-change with change type revoke, rotate, compromise or delete | account_takeover | Hard |
device-compliance-change reporting not compliant | device_compromise | Hard |
Other credential-change and device-compliance-change events, token-claims-change, assurance-level-change | behavioral_anomaly | Soft |
A hard signal runs the revocation cascade in the same request, scoped to the event's subject: shadow identities matching the subject's keyed digests are frozen. Agent delegates, trust negotiations and tunnels have no subject field, so the receiver leaves them alone and records that it skipped them. A soft signal is recorded without a cascade. Each cascade produces a signed receipt.
If the cascade fails, the event is marked failed and the receiver answers with an error so the Transmitter redelivers it. An operator can switch off cascade dispatch from inbound events with the SSE_CASCADE_ENABLED setting, for example during incident triage.
Transmitting events from PasskeyBridge
PasskeyBridge publishes its transmitter configuration for each tenant at /.well-known/ssf-configuration/v1/tenants/<slug> on api.passkeybridge.io, along with the tenant's signing keys as a JSON Web Key Set.
A scheduled worker, shield-sse-deliver, runs every five minutes. On each run it queues a CAEP risk-level-change event for each new classified signal on every stream that asked for that event, signs queued events with the tenant's P-256 key, and delivers them by HTTP push. Failed deliveries are retried with exponential backoff from 30 seconds up to one hour, and a delivery that keeps failing is moved to a dead-letter state. Receiver URLs must use HTTPS and may not point to private, link-local or loopback addresses. Tenant admins can also emit events by hand.
Setup steps are in the SSF/CAEP receiver quickstart and the SSF/CAEP Shared Signals reference guide.
Operational points
Duplicates. Transmitters can deliver the same token twice. Deduplicate on jti for each issuer.
Unknown event types. Providers add their own event types. A Receiver should record and acknowledge events it does not understand without acting on them.
Acknowledgment after processing. If a Receiver acknowledges an event and then fails to act on it, the signal is lost. Answering with an error until processing succeeds lets the Transmitter redeliver.
Stream health. SSF defines a verification event a Receiver can request to confirm a stream is working. Check stream status regularly and alert when deliveries stop.
Key rotation. Cache the Transmitter's keys for a short period and refetch when a token arrives with an unknown key ID.
Summary
SSF moves security events between systems as signed tokens, and CAEP defines the session and credential events most relevant to revocation. Compared with introspection they remove the per-request call and deliver changes when they happen, at the cost of maintaining streams. PasskeyBridge receives CAEP events and runs a subject-scoped revocation cascade for hard events, and publishes risk-level-change events to subscribed receivers.
---
The companion DPoP token binding article covers binding access tokens to a client key, and running CAEP in production covers signing outbound events.