Security events
When a session is revoked here, applications that issued their own sessions from it need telling, by push, or by collection for receivers nobody can reach.
Revoking a session in Cardinal ends it in Cardinal. An application that signed somebody in over OIDC issued a session of its own, and it learns nothing until its token expires, which, for a compromised account, is the whole incident.
Cardinal speaks the standard for saying so: SSF (Shared Signals Framework) carrying CAEP events, as signed security event tokens.
| Event | Sent when |
|---|---|
session-revoked |
a session ends before its own expiry |
credential-change |
a passkey is registered or removed |
assurance-level-change |
how somebody authenticated changes |
verification |
on request: the stream is alive and wired up |
Tokens are signed with the OIDC signing key, so a receiver verifies them against the JWKS it already fetches for id_tokens. No second trust relationship.
Push
The classic shape: Cardinal POSTs each event to an HTTPS endpoint the
receiver runs.
cardinal ssf stream add aura -endpoint https://aura.internal/events
cardinal ssf stream add aura -endpoint https://aura.internal/events \
-events session-revoked,credential-change
cardinal ssf stream list
cardinal ssf stream pause aura # keeps the queue
cardinal ssf stream resume aura # sends what was missed
cardinal ssf stream remove aura
cardinal ssf status # what is queued, what is failing
Pausing does not discard. Resuming delivers what accumulated, which is what makes a receiver's deployment window survivable.
Poll
Push asks the receiver to run an endpoint Cardinal can reach. That is reasonable for a service in the same network and impossible for one behind NAT, on a laptop, or in a CI job, and those receivers could not be told about a revocation at all.
Poll (RFC 8936) inverts it. The receiver connects to Cardinal:
cardinal ssf stream add aura -delivery poll
cardinal ssf token aura # the receiver's own credential, shown once
The receiver POSTs to /ssf/poll with that token as a bearer and
acknowledges each event by its jti. Acknowledgement is separate from
delivery, so a receiver that crashes mid-handling gets the event again rather
than losing it.
The token is an access token with the events scope,
which reads nothing but the events already addressed to that stream.
In the console
Integrations → Security events lists every receiver, its delivery style, what is queued and what is failing, which is the thing that is otherwise invisible. A push stream that has been quietly failing for a week looks identical to a quiet week from the outside.
Streams are added, paused, resumed and removed from that page as well as from the CLI. Issuing a poll token is CLI-only, because the value is shown exactly once.
Best for
- Anywhere sessions outlive the sign-in that created them, which is every OIDC integration.
- Estates where "we revoked their access" needs to be true in more than one system within seconds.
The trade-off
The receiver has to do something with the event. Cardinal sends a signed statement that a session was revoked; an application that receives it and does not end its own session has gained nothing. That work is on the application side and is not always small.
Push and poll are the same events with different plumbing. Push is fewer moving parts when the network allows it; poll needs a credential to manage but works from anywhere.
Limits
- Cardinal is a transmitter, not a receiver. It does not consume events from another provider.
- No stream-level replay by time. A receiver gets what is queued for it; there is no "resend everything since Tuesday".
- Delivery is at-least-once. Acknowledgement by
jtimeans a receiver must be idempotent. - The endpoint must be HTTPS. A cleartext one is refused, not warned about.