Home Supported Standards Terms & Conditions Privacy Policy Documentation Contact About

← All protocols

Shared Signals (SSF) Debugger

What Shared Signals is, and how this page is laid out

The Shared Signals Framework (OpenID SSF 1.0, final 2 September 2025) is the one protocol on this site that runs the other way round. SAML and OpenID Connect authenticate at one instant; after that the relying party holds a session that stays good for hours whatever happens next. Shared Signals inverts it: the identity provider tells the relying party when something changed.

SSF is the pipe and not the vocabulary. It defines how two parties agree a stream, who the events are about (RFC 9493 subject identifiers), what they travel in (RFC 8417 Security Event Tokens) and how they get there (RFC 8935 push, RFC 8936 poll) — and exactly two events of its own, both about the pipe. The vocabularies are CAEP (what happened to a session) and RISC (what happened to an account); this page implements the framework, and those two are the next parts of this work. The Transmit pane says which event types are here and which are not, rather than leaving a short list to be read as a broken page.

Tip: click a pane’s title to collapse or expand it.

Profile — which vocabulary this workflow speaks
Why this is a choice at all, and what each one changes

SSF is the pipe and not the vocabulary. It says how two parties agree a stream, who the events are about and how they get delivered — and exactly two events of its own, both about the pipe. CAEP and RISC are two different vocabularies spoken over it, and they answer two different questions: CAEP says this session is no longer trustworthy, RISC says this account is no longer trustworthy. That distinction is the whole reason there are two specifications.

Choosing one narrows every event list on this page — the stream’s events_requested checkboxes and the Transmit pane’s menu — so that a stream cannot be agreed for events this page will not then send. Nothing is hidden: the pipe is the same machinery underneath all three, and every pane below is used by every profile. CAEP additionally brings up the CAEP session pane, which is the thing its eight events are about.

Who you are, and the tokens this session has used
How this workflow gets a token, and why the whole set comes back

SSF 1.0 section 8 requires a transmitter’s stream management, status, subject, verification and poll endpoints to be protected, and it has the transmitter publish what it accepts in authorization_schemes — so a receiver discovers the scheme rather than guessing. Almost every transmitter names OAuth 2.0, and this workflow gets its token the way the SCIM page does: it sends you to the OAuth2 / OIDC workflow, you run any grant there, and the tokens come back here.

The whole set comes back, not just the bearer token, and that is why this pane can name you: an access token this service issues is opaque to a client, and the identity is in the ID Token. Every set is kept below for the length of this tab — the same Token History the OAuth2 / OIDC results page keeps, for the reason a stream outlives the token that created it.

No token yet. The panes below will run without one against a transmitter that requires none.

No tokens recorded yet.

Configuration Parameters
Why the transmitter’s own endpoints are not in this table

Everything the panes below read, with the source of each. The transmitter’s own endpoints are not here: SSF fixes no paths, so every one of them is discovered from the metadata document in the next pane and this page composes none.

SettingValueSource
you

you
Only the api call path can ignore this — a browser refuses a certificate it does not trust before this page sees anything.you
you
you

Asking the api what it will do…

Transmitter configuration metadata
Where the well-known document is looked for, and in which two shapes

SSF 1.0 section 6. Every endpoint this workflow calls comes out of this document and none is composed here — a transmitter that publishes its stream management API at /v1/streams/manage is driven with nothing typed. It is looked for at /.well-known/ssf-configuration in both shapes: RFC 8414 inserts the well-known segment before the issuer’s path and OpenID Connect Discovery appends it, and insertion is tried first.

Nothing fetched yet.

Stream
What the stream management API is

The control plane. One path and five methods, which is the specification’s own shape: the configuration endpoint is the resource. Read events_delivered rather than events_requested when the answer comes back — the first is what will be sent and the second is what you asked for, and SSF has no refusal for an event type a transmitter will not agree to. Its absence from that list is the only notice you get, so this page says so out loud.

Fetch the metadata first, or leave every box clear to ask for everything the transmitter supports.

No stream yet.

What paused and disabled mean, and why they differ

Status. A paused stream keeps queueing and delivers nothing, so what happened while it was paused is still there when it is enabled again; a disabled one drops it. That is the difference between “I was not listening” and “it did not happen”, and it is why a receiver taking a maintenance window pauses rather than disables.

Why verification is the only end-to-end test a stream has

Verification is the only end-to-end test a stream has. Everything above exercises the management API and proves nothing about whether an event can actually be delivered; this asks the transmitter to send one down the ordinary path. The state comes back inside the event unchanged, and it is the only thing tying the two together.

Subjects — who the stream is about
The eight formats, their closed member sets, and what an empty subject list means

RFC 9493 gives eight formats and SSF adds the complex subject, whose members are each themselves an identifier. That is what makes “this session was revoked” expressible at all: the person is not revoked, one session of theirs is.

Each format’s member set is closed. A subject carrying an extra member is one a conforming receiver must reject — it cannot tell whether the member narrows the subject — and it looks perfectly fine in a log. This page refuses it and names the member, which is what the Check button is for.

What an empty subject list means is default_subjects in the metadata: with ALL the stream is about everybody and adding a subject narrows nothing; with NONE it is about nobody until one is added. Guessing wrong gets you every event in the estate or none, and both look like a broken transmitter.

CAEP session — the thing these events are about
Why a CAEP event names a session and not a person

CAEP (OpenID Continuous Access Evaluation Profile 1.0, final 2 September 2025) is the enterprise session vocabulary. Its eight event types all say something about one session, and the subject each of them carries is normally SSF’s complex subject — because the person is not revoked, one session of theirs is. A subject naming only the person asks a receiver to end every session that person has, which is a much larger instruction than the one that was meant and looks perfectly reasonable in a log.

This pane holds a simulated session, seeded from whatever the OAuth2 / OIDC workflow handed over. It is a model and not a session anybody holds: what makes an event about a real session is the sid claim, and where the ID Token carried none the identifier below was generated here and says so. Every field is editable, so a real one can be pasted in.

Every simulate button below builds a whole event, signs it and pushes it through the Transmitting events pane — which is left visible on purpose, so that what goes out can be read before and after. The session state and the counts move with what was actually sent.

The four claims CAEP gives every one of its events

All four are optional (CAEP section 2), which surprises people about the first: a receiver deciding whether to end a session wants event_timestamp more than anything else in the payload, and a conforming transmitter need not send one. Leaving it out here is how a receiver that assumes it is present gets to fail in a test. reason_admin and reason_user are objects keyed by a language tag and not strings — the commonest mistake in the whole profile, and the one with no symptom, because a receiver indexing by language reads nothing from a string and reports no error.

What each button sends, and which of them a real transmitter sends on its own

Three of the eight describe things a transmitter can actually observe — a session starting, being presented and ending — and this stack’s mock sends those by itself when you sign in, sign in again and sign out. The other five describe things nothing observes for you: no device reports compliance to a mock and no risk engine talks to one. Every button here builds the event this page would send as the transmitter, whichever half you are testing.

RISC account — the thing these events are about
Why a RISC event names a person and a CAEP event names a session

RISC (OpenID RISC Profile Specification 1.0, published 29 August 2025 and final on 2 September 2025) is the account vocabulary. CAEP says this session is no longer trustworthy; RISC says this account is no longer trustworthy, and the second is the larger sentence by orders of magnitude — a revoked session is one sign-in at one relying party, and a purged account is every session that person has anywhere, for ever. CAEP is aimed within an enterprise and RISC across providers: its origin is a consumer provider noticing that an account has been taken over and telling every site that account signs in to.

The subject is a PLAIN one, and that is the whole difference said in one line of JSON. SSF’s complex subject exists because a CAEP event is about one session of one person, so {user, session, device} is how that person, on that device, in that session is expressible at all. A RISC event is about the account: the person is the subject, there is nothing to narrow, and a complex subject here would say this account was disabled, on this device, which is a sentence with no meaning.

Eleven of the fourteen carry no payload members at all, so for those the subject is the entire message — account-purged says nothing but its own type and who it is about. A subject naming the wrong person is therefore not a partly wrong event; it is a wholly wrong one, with nothing else in it to notice by. That is what makes the format selector below the consequential control on this pane.

Every simulate button builds a whole event, signs it and pushes it through the Transmitting events pane, which is left visible on purpose. The account’s three states and the counts move with what was actually sent.

The three claims RISC gives to ONE of its fourteen events

CAEP section 2 gives event_timestamp, initiating_entity, reason_admin and reason_user to every one of its eight events. RISC gives three of them — there is no initiating_entity — and gives them to exactly one of its fourteen, credential-compromise. On any other type the fields below are composed and dropped, rather than sent as members the specification does not define.

event_timestamp means something different here too: RISC section 2.7 words it as when the transmitter discovered the compromise rather than when it happened. A credential found in a breach corpus was compromised long before anybody noticed, so a receiver reading it as an occurrence time dates the incident from the wrong end.

RISC does not repeat CAEP’s requirement that the two reason members be language maps rather than strings, which makes a bare string arguably conforming to RISC and certainly unreadable to a receiver built against CAEP. This page sends the map, because that is the reading that is right under both.

What each button sends, and the two that are not what they look like

Four of the fourteen describe things a transmitter can actually observe in its own directory — a person deleted, an account marked inactive or active again, an identifier moving — and this stack’s mock sends those by itself when the directory changes over SCIM, over LDAP or from its console. That is a different observer from CAEP’s, watching the provisioning layer rather than the authentication one.

The four opt-out buttons ARE state transitions, not reports of one: RISC section 2.8 words each as the account is in this state, so pressing one moves the account here. And sessions-revoked is deprecated by RISC itself in favour of CAEP’s session-revoked — plural against singular, one letter apart, every session this person has against the one the subject names. It is offered because a debugger that could not build a deprecated event could not find out what a receiver does with one.

Receiving events
Why poll delivery works in this browser and push delivery does not

Poll delivery works in this browser and push delivery cannot, and that is a property of the two specifications rather than of this tool. RFC 8936 has the receiver come to the transmitter, which a page can do; RFC 8935 has the transmitter POST to the receiver, and a page is not an HTTP server. So the api layer hosts an endpoint on this page’s behalf — and on a deployment with no api there is nothing to host, which is exactly what the hosted static sites are.

What is checked on an arriving token, and why each check is named

Anything that arrives is decoded and every check is reported by name. A single “valid” over a token whose audience is somebody else is the most dangerous thing this page could say.

Why the verifier chooses the algorithm

The verifier chooses the algorithm, never the token (RFC 8725 section 3.1). A mismatch with the header is reported rather than accommodated.

Transmitting events — this page as the transmitter
What this pane sends, and the media type that is silently wrong everywhere

The other half of the protocol, and the one a receiver under test needs: build any event SSF defines, sign it, and push it to somebody’s RFC 8935 endpoint. The media type is the thing that is silently wrong everywhere — RFC 8417 section 2.3 gives a SET application/secevent+jwt, and a receiver that dispatches on the type drops one sent as application/jwt with no error anybody sees. This page can send either, on purpose.

Why a SET is the document here most worth signing post-quantum

A SET is the document here most worth signing post-quantum. It records that something HAPPENED, RFC 8417 section 4.1.4 forbids it to expire, and it is therefore read long after it was written — which is the case a harvest-now-decrypt-later argument is actually about. ML-DSA, SLH-DSA and the six composite ML-DSA + traditional algorithms are all here.

Event message history
Why the tokens are kept and the Authorization header is not

Every Security Event Token this page sent or received, whole, with what it decoded to and what every check said. The tokens are kept because a SET is evidence rather than a credential — holding one grants nothing and presenting one achieves nothing — and evidence is what a debugger most needs to survive a navigation. What is stripped is the Authorization header of the exchange that carried it, which is a credential.

No events yet.

The last exchange
What the browser call path can and cannot show

What went out and what came back. On the browser call path this is what the page can see, which is less than the whole: a browser withholds the headers it adds and CORS withholds most of those that come back. The api path is made by the backend and can therefore be reported in full, which is one of the three reasons that path exists.

Operations History
What Sent means in this table

One row per call, newest first. Sent is not a success: it means the call left this page and nothing came back to resolve it.