PasskeyBridge

Security · 2026-04-28

SSF and CAEP: Closing the Cross-IdP Revocation Latency Gap

By J. W. Bouckaert

SSF and CAEP: Closing the Cross-IdP Revocation Latency Gap

The revocation latency problem no one wants to talk about

In a single-IdP world, session revocation is a database update. The IdP marks the session invalid, and the next request that hits the IdP's introspection endpoint gets a clean rejection. Most enterprise identity stories are told in single-IdP terms because that is the easy case.

The actual operational reality of a 2026 enterprise is multi-IdP: Okta for workforce SSO, Azure AD for Microsoft 365, an in-house OIDC provider for the legacy product line, and increasingly an agent-identity broker for autonomous workloads. When a security event fires—a compromised credential, an out-of-band MFA challenge that fails the device-binding check, an invisible SIM swap signal on a phone-bound account—the revocation needs to land at every relying party that trusts any of those IdPs. Within seconds. Reliably. Without a polling loop.

This is the problem the OpenID Shared Signals Framework (SSF) and the Continuous Access Evaluation Profile (CAEP) were built to solve. Both reached final-form publication on August 29, 2025, with the OpenID Foundation membership approving them as Final Specifications on September 2, 2025. Both are now in production at the major IdP vendors. And—this is the part most identity teams have not internalized yet—the polling-based alternatives that the industry tolerated through 2024 have already lost.

This article covers what SSF and CAEP actually standardize, the gap they close, and how PasskeyBridge implements both directions—as an SSF Transmitter publishing identity threat events outward, and as an SSF Receiver consuming inbound CAEP events from upstream IdPs and converting them into in-process revocation cascade dispatches.

Polling has lost

Before SSF/CAEP, the standard answer to "how does the relying party know the session was revoked?" was OAuth token introspection (RFC 7662)—every protected request, the resource server calls back to the IdP and asks "is this token still valid?"

Token introspection works. It also has three properties that have made it operationally untenable at modern scale:

PropertyToken IntrospectionSSF/CAEP Push
Latency between revocation event and RP enforcementUp to access-token TTL (typically 1 hour)Seconds
Network calls per protected request1 (or cached, with TTL latency)0
IdP-side loadO(requests)O(events)
Requires standing connection from RPNoYes (SSF Stream)
Works with sender-constrained tokensYesYes
Detects revocation during cached-token windowNoYes

The latency line is the one that has changed the calculus. For a workforce credential, an hour of post-revocation usability used to be acceptable—administrators assumed insider threats would be caught by SIEM rather than by real-time enforcement. For a compromised credential being actively exploited by an attacker who knows they have under an hour to move laterally, an hour is not acceptable. For an agentic identity that can issue thousands of API calls per minute, an hour is catastrophic.

CAEP frames this directly: the value of the profile is shrinking the window between when a security-relevant event occurs at the IdP and when relying parties can act on it. The final CAEP 1.0 specification exists to standardize that propagation so the window can be measured in seconds rather than token TTLs.

SSF

SSF—the Shared Signals Framework—is the transport. It does not define what events mean; it defines how events get from a Transmitter (the system that knows about the event) to a Receiver (the system that needs to react to it).

The core mechanics:

  1. Streams. Two parties (Transmitter and Receiver) agree on a long-lived stream. Streams are managed by REST endpoints whose URLs are implementation-defined and discovered through the Transmitter's /.well-known/ssf-configuration document—there is no standardized literal path.
  2. Subjects. A stream is scoped to a set of subjects (users, sessions, devices). The Receiver tells the Transmitter which subjects it cares about; the Transmitter only sends events about those subjects.
  3. Security Event Tokens (SETs). Events are serialized as Security Event Tokens (RFC 8417)—signed JWTs that carry an event-type identifier and an event-specific payload.
  4. Delivery methods. Two are standardized: HTTP Push (Transmitter POSTs SETs to a Receiver-provided endpoint) and HTTP Poll (Receiver pulls SETs from a Transmitter-hosted queue). Both are idempotent and acknowledge-based.

The deliberate design choice in SSF is that the framework does not care what events you send. You can use SSF for CAEP events. You can use SSF for RISC (Risk Incident Sharing and Coordination) events. You can use SSF for entirely custom event vocabularies. The framework is intentionally event-agnostic—the same way HTTP is intentionally payload-agnostic.

CAEP

CAEP—the Continuous Access Evaluation Profile—defines the event vocabulary for session and credential lifecycle changes. The standardized event types most relevant to a 2026 identity stack are:

Event TypeTriggered WhenTypical Receiver Action
session-revokedA session is explicitly invalidatedTerminate all dependent sessions
token-claims-changeClaims on an active token change (group membership, role)Refresh authorization decisions
credential-changeA credential is added, removed, or rotated (passkey, password)Re-evaluate device trust
assurance-level-changeThe IdP downgrades the user's assurance level (failed step-up, lost MFA factor)Step-up challenge or session termination
device-compliance-changeThe endpoint posture changes (jailbreak detected, MDM removed)Quarantine or revoke device-bound credentials

Each event carries a structured payload identifying the affected subject, the precise change, and a timestamp. The Receiver verifies the SET signature against the Transmitter's published JWKs, applies the event to its local state, and acknowledges receipt.

The critical design property: the Transmitter is not responsible for guaranteeing the Receiver's downstream enforcement. The Transmitter is only responsible for delivering the event. This separation lets each Receiver apply its own policy—one tenant might revoke immediately on assurance-level-change, another might step up a challenge instead.

PasskeyBridge's implementation

PasskeyBridge runs both directions of SSF/CAEP. If you want to subscribe to an upstream IdP's stream right now, the Wire an SSF/CAEP Receiver in 5 Minutes quickstart is the shortest path; the SSF/CAEP Shared Signals reference guide covers the full transmitter and receiver surface.

As an SSF Transmitter, PasskeyBridge publishes identity threat playbook outcomes—SIM swap detections, device-attestation failures, behavioral drift threshold breaches, carrier signal anomalies—as CAEP-conformant SETs to every relying party that has subscribed. A confirmed silent number recycling event generates a credential-change SET; a behavioral-drift breach generates an assurance-level-change SET; an explicit revocation triggers session-revoked. The relying parties consume these events through their existing CAEP Receiver implementations and apply their own enforcement policies.

As an SSF Receiver, PasskeyBridge consumes inbound CAEP events from upstream IdPs (Okta, Azure AD, Auth0, ForgeRock, custom OIDC providers) via the shield-sse-caep edge function. Events arrive, signatures are verified against the configured Transmitter's JWKs, the payload is normalized to PasskeyBridge's internal event schema, and—this is the important part—the event is dispatched directly into the in-process revocation cascade engine. No queue. No batch worker. The cascade fires on the same request that received the inbound CAEP event.

This is the wiring most CAEP implementations get wrong. Receiving the event is the easy part. Acting on it within the latency budget the standard exists to provide requires the cascade dispatch to happen synchronously. PasskeyBridge's Pass 4 hardening (April 2026) made that wiring explicit: shield-sse-caep parses the inbound SET, maps the event type to a cascade trigger, and invokes executeCascade in the same request handler. End-to-end latency from inbound CAEP event to outbound revocation propagation is typically 30-80 ms.

The CAEP event-to-cascade mapping

The mapping from inbound CAEP event types to PasskeyBridge cascade actions:

Inbound CAEP EventCascade ActionDownstream Effect
session-revokedhard_revokeAll sessions for subject terminated; DPoP bindings invalidated; outbound session-revoked SET fanned out to subscribed RPs
token-claims-changerefresh_authzCached authorization decisions for subject invalidated; next request triggers fresh evaluation
credential-changereattest_requiredDevice attestation re-verified on next request; session continues if attestation still valid
assurance-level-change (downgrade)step_up_requiredSubject forced through fresh authentication on next request
device-compliance-change (non-compliant)device_quarantineDevice-bound credentials revoked; subject can re-authenticate from a different device

The cascade engine handles the actual enforcement work—invalidating session tokens, marking DPoP bindings as no-longer-valid, fanning out outbound events, and writing to the zero-knowledge audit trail. The CAEP event handler's only job is to translate and dispatch.

Beyond compliance

CAEP is increasingly a procurement requirement. The FAPI 2.0 Security Profile and the upcoming NIST SP 800-63 Rev. 4 updates both reference shared-signals frameworks as the expected mechanism for cross-RP session lifecycle propagation. Vendors that ship CAEP support pass procurement; vendors that do not, increasingly do not.

But the deeper reason CAEP matters is operational. An identity stack without shared signals is an identity stack with a per-RP polling tax—every relying party paying the introspection cost on every request, with the latency that polling implies. An identity stack with shared signals is an identity stack where the IdP's view of session validity propagates to enforcement points in seconds, where the 50-millisecond verification budget we run identity decisions inside actually has room to do useful work, and where the autonomous agent that issued 2,000 API calls in the minute before its session was revoked gets cut off at call 2,001 instead of call 60,000.

That is the gap. Polling-based revocation tolerates an hour of post-compromise blast radius. CAEP-based revocation tolerates 30-80 milliseconds of post-compromise blast radius. Both numbers used to be acceptable. Only one of them still is.

The hard parts

Implementing CAEP cleanly at production scale surfaced a few non-obvious problems worth flagging:

Stream lifecycle management. Streams are long-lived. They can break. The Receiver has to detect a broken stream (missed heartbeats, repeated SET delivery failures), reconnect, and—critically—query the Transmitter for events missed during the outage window. SSF specifies a /streams/{id}/verify endpoint for this, but Transmitter implementations vary in how they handle backfill.

SET signature verification at scale. Every inbound SET requires a JWK fetch (cached) and a JWT signature verification. At high event rates, the verification cost is non-trivial. We ended up with a tenant-scoped JWK cache with a 5-minute TTL and a strict allowlist of permitted signing algorithms.

Idempotency. Networks repeat. SSF Transmitters can deliver the same SET twice. The Receiver has to deduplicate by jti (the SET's unique identifier) within a sliding window. We use a 24-hour idempotency cache.

Event-type extensibility. CAEP defines a base vocabulary. Vendors extend it. Okta ships several Okta-specific event types alongside the standard ones; Azure AD ships its own. The Receiver has to handle unknown event types gracefully—log and acknowledge, do not error—without dispatching cascade actions for events it does not understand.

Acknowledgment semantics. SSF distinguishes between "received" and "processed." A Receiver that acknowledges an event but then fails to enforce it has silently dropped a security signal. PasskeyBridge acknowledges after the cascade dispatch returns successfully—accepting the cost of slower acknowledgment in exchange for never silently dropping an enforcement event.

The trajectory

Both SSF and CAEP are now in their post-final, post-deployment phase. The OpenID Foundation's Shared Signals Working Group is iterating on the next-generation event vocabulary—expect richer device-posture events, agent-identity-specific events, and tighter integration with the emerging Verifiable Credential ecosystem over the next 18 months.

Vendor support has consolidated faster than most identity standards. Okta, Azure AD, Auth0, Ping, ForgeRock, and Cloudflare Access all ship CAEP support in production today. The integration story is no longer "can we connect to your IdP"—it is "what is your event vocabulary and how do we map it to our enforcement primitives."

The teams that win the next two years are the teams that treat session lifecycle as a signal, not a poll. CAEP is the standardized way to do that. The latency gap closes; the post-compromise blast radius shrinks; the identity stack stops being the slowest layer in the security architecture.

That is what shared signals are for.

---

Wiring CAEP into your identity stack? Start with the 5-minute receiver quickstart, then graduate to the SSF/CAEP Shared Signals reference guide for the full transmitter/receiver implementation. The companion DPoP Token Binding article covers what the revoked sessions were actually carrying.

Start free · Test the API