Skip to content

Shared Signals Framework

  • OpenID Shared Signals Framework 1.0
  • OpenID Continuous Access Evaluation Profile (CAEP) 1.0
  • OpenID RISC Profile Specification 1.0
  • RFC 8417 (SET), RFC 8935 (push), RFC 8936 (poll)

SSF is a durable session in Looking Glass: /looking-glass?protocol=ssf. Catalog flow IDs are presets into one Looking Glass session (they fill the event/delivery chrome). They do not replace the chrome.

  • Fire event encodes and delivers a CAEP/RISC SET for the selected subject to every enabled stream that requested that event type (the Looking Glass lab stream and any Stream Management poll/push Receivers). That is the only Looking Glass control that mutates RP account state. Verify stream reads transmitter metadata and POSTs /verify; it does not revoke sessions or disable accounts.

SSF remains its own image (protocolsoup-ssf) behind the gateway, the same way SCIM does. RP security state is stored on the SSF service. After a verified CAEP session-revoked SET, the receiver also POSTs to federation over HTTP so Alice/Bob OAuth sessions actually die.

/ssf-sandbox redirects to Looking Glass.

Looking Glass hides the per-event action dropdown. The chrome (subject, event, push/poll) is the control surface. Catalog IDs below still work as deep-link presets (/looking-glass?protocol=ssf&flow=caep-session-revoked).

Flow ID Name Looking Glass role
ssf-stream-lab Looking Glass session Default durable session
ssf-stream-configuration Stream Configuration Preset: use Verify stream (does not change RP state)
ssf-push-delivery Push Delivery Preset: delivery = RFC 8935, then Fire event
ssf-poll-delivery Poll Delivery Preset: delivery = RFC 8936, then Fire event
caep-session-revoked Session Revoked (CAEP §3.1) Preset: event = session-revoked, then Fire event
caep-credential-change Credential Change (CAEP §3.3) Preset: event = credential-change, then Fire event
risc-account-disabled Account Disabled (RISC §2.3) Preset: event = account-disabled, then Fire event
risc-credential-compromise Credential Compromise (RISC §2.7) Preset: event = credential-compromise, then Fire event
  • SSF in Looking Glass – Durable Looking Glass session for CAEP/RISC events
  • Session Revocation Demo – CAEP session revoked event lifecycle
  • Credential Compromise Response – RISC response action execution
  • Push vs Poll Comparison – Delivery mode behavior comparison

session-revoked, credential-change, device-compliance-change, credential-compromise, account-disabled, account-enabled, account-purged, identifier-changed, assurance-level-change, token-claims-change, identifier-recycled, account-credential-change-required

The lab action sessions-revoked maps to CAEP session-revoked (all sessions). RISC sessions-revoked is not emitted (RISC §2.11).

Path Methods Purpose
/.well-known/ssf-configuration GET SSF discovery (issuer insertion, SSF §7.2)
/ssf/jwks GET Transmitter JWKS
/ssf/stream POST, GET, PUT, PATCH, DELETE Stream CRUD (GET without stream_id returns that Receiver’s list; PUT replaces Receiver-Supplied properties; nested delivery)
/ssf/status GET, POST Stream status (stream_id required; body includes stream_id)
/ssf/verify POST Stream verification (stream_id required; state optional; 204 empty)
/ssf/subjects GET Looking Glass demo identities
/ssf/subjects/add POST Add Subject (stream_id + RFC 9493 subject; 200 empty)
/ssf/subjects/remove POST Remove Subject (stream_id + RFC 9493 subject; 204)
/ssf/actions/{action} POST Trigger event action (fan-out to eligible streams)
/ssf/poll/{stream_id} POST Poll delivery (RFC 8936). URL is Transmitter-supplied on the stream.
Path Methods Purpose
/ssf/receiver/push POST Receive pushed SETs
/ssf/receiver/status GET Receiver health
/ssf/receiver/events GET Received event log
/ssf/receiver/actions GET Response action log
Path Methods Purpose
/ssf/events GET Event history
/ssf/security-state GET All security states
/ssf/security-state/{email} GET State by subject
/ssf/security-state/{email}/reset POST Reset RP posture
/ssf/decode POST Decode SET

SSF runs as protocolsoup-ssf (cmd/server-ssf) with a standalone receiver on port 8081 alongside the main API on port 8080. Push delivery to {baseURL}/ssf/receiver/push is proxied to the internal receiver and returns 202. The receiver validates SETs and executes response actions via ReceiverActionExecutor on this service. After a verified CAEP session-revoked SET it POSTs { "email": "[email protected]" } to FEDERATION_SERVICE_URL/oauth2/demo/caep/revoke-subject (bearer SSF_TO_FEDERATION_TOKEN) so MockIdP sessions and tokens die. That hop is RP policy, not an SSF SET field, and is shown on the Looking Glass bus.

Do not register SSF in the federation binary. Cross-service CAEP is HTTP only (loopback on the Fly/cmd/server monolith).

Local/demo issuer may be http:// (SSF §7.1 wants https). Same lab TLS story as other ProtocolSoup services.

  • Stream configuration: nested delivery: { method, endpoint_url }, events_supported vs events_delivered
  • Discovery: GET /.well-known/ssf-configuration, spec_version "1_0", issuer identical to SET iss, authorization_schemes includes urn:ietf:rfc:6749, default_subjects "ALL"
  • Stream management is stream_id addressed. GET /ssf/stream without stream_id returns that Receiver’s list ([] when none). Create is 201. Delete is 204.
  • Stream Management is an OAuth 2.0 resource server when SSF_AS_JWKS_URI is set: ssf.read / ssf.manage, bearer header only (no query access_token). The Transmitter also checks revocation status (MockIdP on the monolith, or SSF_AS_INTROSPECT_URI on the split SSF image). The federation AS seeds confidential client ssf-stream-client for those scopes (GET /oauth2/demo/clients).
  • SET structure: iss, iat, jti, aud, events (exactly one event), top-level sub_id, no JWT sub or exp, typ=secevent+jwt, RS256
  • Push delivery: Content-Type: application/secevent+jwt, signature, 202 (not 200); push URL is the Receiver’s delivery.endpoint_url
  • Poll delivery: POST to the stream’s Transmitter-supplied delivery.endpoint_url (/ssf/poll/{stream_id}); sets map keyed by jti; unacknowledged SETs retransmit; maxEvents: 0 is ack-only; acks / setErrs on the next poll
  • Subject Management: POST /ssf/subjects/add (200) and POST /ssf/subjects/remove (204) with stream_id + RFC 9493 subject. default_subjects is ALL; remove excludes that subject from transmission.
  • Device Compliance: CAEP device-compliance-change SETs use a Complex sub_id (user + device) and reason_admin. The Receiver restricts RP access when current_status is not-compliant.
  • Verification: stream_id required, 204 empty, verification SET sub_id opaque stream id; state echoed only when supplied
  • CAEP/RISC members: namespace + current_level; credential_type; not-compliant; RISC reason only hijacking | bulk-account
  • Stream Management tokens: signature, expiry, iss/aud/scope, and RFC 7009 revocation status (in-process MockIdP or RFC 7662 introspection)
  • Looking Glass Flow tab is the Looking Glass bus only (no executor-local spoof timeline)