8000 Add Shared Signals Framework Transmitter capability by thomasdarimont · Pull Request #48256 · keycloak/keycloak · GitHub
[go: up one dir, main page]

Skip to content

Add Shared Signals Framework Transmitter capability - #48256

Merged
pedroigor merged 1 commit into
keycloak:mainfrom
thomasdarimont:issue/gh-48254-ssf-tx-support-v1
May 12, 2026
Merged

pedroigor merged 1 commit into
keycloak:mainfrom
thomasdarimont:issue/gh-48254-ssf-tx-support-v1

Conversation

@thomasdarimont
@thomasdarimont thomasdarimont commented Apr 20, 2026 •
Copy link
Copy Markdown
Contributor

Adds Shared Signals Framework support to Keycloak in the SSF Transmitter role: Keycloak signs Security Event Tokens (SETs, RFC 8417) describing realm/user/session/credential events and delivers them to OAuth clients
registered as SSF Receivers, either by HTTP PUSH (RFC 8935) or HTTP POLL (RFC 8936).

Targets the OpenID Shared Signals Framework 1.0 (Final) specification plus the CAEP Interoperability Profile 1.0. Ships the legacy SSE CAEP profile alongside for Apple Business Manager / Apple School Manager interop, since Apple device-fleet enrolment is a concrete drive-use case.

Gated behind Profile.Feature.SSF experimental, opt-in.

Background

Issue #43614 originally proposed SSF Receiver support (Keycloak ingesting SETs from upstream IdPs / risk engines). After exploring both sides, we're shipping the Transmitter first (see #48254) because it covers the strongest community asks (federate Keycloak events to downstream SaaS, Apple device fleet revoke flow) and lets us validate the SSF data-plane against real receivers before designing the harder "action mapping" question on the Receiver side. Receiver support remains on the roadmap and is tracked separately via #43614.

Scope (experimental)

In:

  • Compliance with SSF 1.0, CAEP 1.0, RISC 1.0, RFC 8935, RFC 8936, RFC 9493, RFC 8417
  • SSF Transmitter support (Keycloak Realm can act as a SSF Transmitter)
  • SSF Stream management (CRUD, status, verification)
  • SSF Subjects management (subjects)
  • SET delivery via HTTP PUSH (RFC 8935) and HTTP POLL (RFC 8936) with POLL in a return-immediately form
  • SSF events temporarily stored in durable outbox with cluster-aware drainer and exponential backoff
  • SSF Receivers managed as OIDC Clients with client credentials grant or auth code grant (currently only one stream per client)
  • Support for SSF Stream, CAEP 1.0 and RISC 1.0 events (custom events via SPI)
  • CAEP credential-change / session-revoked / (device-compliance-change) event mapping from native Keycloak events
  • Support for RFC 9493 Subject Identifiers for Security Event Tokens
  • Support for SSF Receiver subject event subscription with subject selection (per-user / per-orgssf.notify.attribute, support fordefault_subjectspolicy (ALL, NONE))
  • Support for Synthetic event emittance via REST endpoint for non-Keycloak-native event sources (external IAM solution)
  • Per-receiver "Emit-only events" gate to suppress auto-emit per event type per receiver
  • Support for legacy SSE CAEP profile for Apple Business Manager / Apple School Manager interop (verified)
  • Per-realm SSF admin REST + Admin UI for SSF-enabled clients (Receiver / Stream / Subjects / Events)
  • Prometheus metrics (dispatcher, drainer, poll, verification, outbox depth, delivery metrics)

Out (tracked as separate follow-up issues):

  • SSF Receiver role for Keycloak (ingestion of SETs)
  • POLL long-polling (returnImmediately=false honoured)
  • Dedicated SSF signing key (separate from realm OIDC signing key)
  • Chunked HELD release for very large backlogs
  • Performance characterization + security review
  • Formal interop matrix (caep.dev, ABM)

Tasks

  • All code gated behind Profile.Feature.SSF (experimental, off by default)
  • Per-realm ssf.transmitterEnabled toggle; per-client ssf.enabled toggle
  • SSF event listener registered as global (not user-toggleable per realm)
  • Receiver-facing endpoints conformant with SSF 1.0
  • CAEP credential-change / session-revoked / device-compliance mapping pass interop testing against caep.dev
  • SSE CAEP profile narrowed shape works with Apple Business Manager
  • Integration test coverage for the dispatch / outbox / push / poll pipeline (100+ tests)
  • Prometheus metrics exposed under keycloak_ssf_*
  • Design notes published

Documentation

A more detailed description for the design Design + behaviour can be found here: (Design Document)

Fixes #48901

Signed-off-by: Thomas Darimont thomas.darimont@googlemail.com

This PR was partially co-authored with Claude AI

@thomasdarimont thomasdarimont added team/core-iam kind/feature Categorizes a PR related to a new feature labels Apr 20, 2026
@thomasdarimont
thomasdarimont force-pushed the issue/gh-48254-ssf-tx-support-v1 branch from 6b46c3e to 279353a Compare April 20, 2026 07:53
@thomasdarimont
thomasdarimont commented Apr 20, 2026 •
Copy link
Copy Markdown
Contributor Author

@pedroigor @sguilhen as discussed here is the initial PR with a fully featured SSF Transmitter implementation without the SSF Receiver support.

The SSF feature is now aligned with the structure of the SCIM feature as multiple sub modules:
image

@thomasdarimont
thomasdarimont commented Apr 20, 2026 •
Copy link
Copy Markdown
Contributor Author

Admin UI Screenshots

If the SSF feature is enabled for the server the SSF Transmitter capability can be enabled for the realm.
If enabled a link to the ssf-configuration metadata is added.
image

If the SSF feature is enabled for the server and for the current realm, the SSF Receiver capability can be enabled on an authenticated client.
image

The SSF tab of a Client shows details about the SSF Receiver configuration.
image

image

The Stream tab shows the current SSF stream configuration:
image

The Subjects tab allows to manage interested subjects for a stream.
image

The Events Search tab allows to lookup the state of the event processing for an event.
image

The Emit Events tab allows to emit supported events for a subject.
image

@keycloak-github-bot
Copy link
Copy Markdown

Unreported flaky test detected

If the flaky tests below are affected by the changes, please review and update the changes accordingly. Otherwise, a maintainer should report the flaky tests prior to merging the PR.

org.keycloak.testsuite.model.singleUseObject.SingleUseObjectModelTest#testCluster

Keycloak CI - Store Model Tests

java.lang.AssertionError: 
threads didn't terminate in time: [main (RUNNABLE):
	at java.management@25.0.2/sun.management.ThreadImpl.dumpThreads0(Native Method)
	at java.management@25.0.2/sun.management.ThreadImpl.dumpAllThreads(ThreadImpl.java:505)
	at java.management@25.0.2/sun.management.ThreadImpl.dumpAllThreads(ThreadImpl.java:493)
...

Report flaky test

@keycloak-github-bot keycloak-github-bot Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unreported flaky test detected, please review

@thomasdarimont
thomasdarimont force-pushed the issue/gh-48254-ssf-tx-support-v1 branch 6 times, most recently from 9be57a4 to df16cab Compare April 23, 2026 17:10
@keycloak-github-bot keycloak-github-bot Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unreported flaky test detected, please review

@thomasdarimont
thomasdarimont force-pushed the issue/gh-48254-ssf-tx-support-v1 branch from 8e8f588 to bb99279 Compare May 6, 2026 08:30
@keycloak-github-bot keycloak-github-bot Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unreported flaky test detected, please review

@keycloak-github-bot
Copy link
Copy Markdown

Unreported flaky test detected

If the flaky tests below are affected by the changes, please review and update the changes accordingly. Otherwise, a maintainer should report the flaky tests prior to merging the PR.

org.keycloak.testsuite.adapter.servlet.SAMLServletAdapterTest#employeeSigPostNoIdpKeyTestCertSubjectAsKeyNameInKeyInfo

Keycloak CI - Adapter IT Strict Cookies

org.opentest4j.AssertionFailedError: expected: <true> but was: <false>
	at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
	at org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
	at org.junit.jupiter.api.AssertTrue.failNotTrue(AssertTrue.java:63)
	at org.junit.jupiter.api.AssertTrue.assertTrue(AssertTrue.java:36)
...

Report flaky test

org.keycloak.testsuite.adapter.servlet.SAMLServletAdapterTest#salesPostTest

Keycloak CI - Adapter IT Strict Cookies

org.opentest4j.AssertionFailedError: expected: <true> but was: <false>
	at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
	at org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
	at org.junit.jupiter.api.AssertTrue.failNotTrue(AssertTrue.java:63)
	at org.junit.jupiter.api.AssertTrue.assertTrue(AssertTrue.java:36)
...

Report flaky test

org.keycloak.testsuite.adapter.servlet.SAMLServletAdapterTest#testMultipleTabsParallelLogin

Keycloak CI - Adapter IT Strict Cookies

org.awaitility.core.ConditionTimeoutException: Assertion condition defined as a Lambda expression in org.keycloak.testsuite.util.URLAssert URL expected to begin with: https://localhost:8543/auth/realms/demo/login-action ; actual URL: https://localhost:8643/sales-post/ ==> expected: <true> but was: <false> within 10 seconds.
	at org.awaitility.core.ConditionAwaiter.await(ConditionAwaiter.java:167)
	at org.awaitility.core.AssertionCondition.await(AssertionCondition.java:119)
	at org.awaitility.core.AssertionCondition.await(AssertionCondition.java:31)
	at org.awaitility.core.ConditionFactory.until(ConditionFactory.java:1160)
...

Report flaky test

@thomasdarimont
thomasdarimont force-pushed the issue/gh-48254-ssf-tx-support-v1 branch from bb99279 to 49a6790 Compare May 6, 2026 20:44
@thomasdarimont
thomasdarimont requested a review from edewit May 6, 2026 22:19
@thomasdarimont
thomasdarimont force-pushed the issue/gh-48254-ssf-tx-support-v1 branch 3 times, most recently from 1fc3ec8 to cfa9ae3 Compare May 9, 2026 14:28
@thomasdarimont
thomasdarimont force-pushed the issue/gh-48254-ssf-tx-support-v1 branch 2 times, most recently from f84d9d7 to f79d1ed Compare May 11, 2026 18:18
@thomasdarimont thomasdarimont added this to the 26.7.0 milestone May 11, 2026
@thomasdarimont thomasdarimont added the area/ssf Shared Signals Framework — CAEP/RISC events, push delivery, event streams label May 11, 2026
@thomasdarimont
thomasdarimont force-pushed the issue/gh-48254-ssf-tx-support-v1 branch from f79d1ed to eccb7de Compare May 11, 2026 19:51
Adds Shared Signals Framework support to Keycloak in the **SSF Transmitter** role: Keycloak signs Security Event Tokens (SETs, RFC 8417) describing realm/user/session/credential events and delivers them to OAuth clients
registered as **SSF Receivers**, either by HTTP PUSH (RFC 8935) or HTTP POLL (RFC 8936).

Targets the OpenID Shared Signals Framework 1.0 (Final) specification plus the CAEP Interoperability Profile 1.0. Ships the legacy SSE CAEP profile alongside for Apple Business Manager / Apple School Manager interop, since Apple device-fleet enrolment is a concrete drive-use case.

Gated behind \`Profile.Feature.SSF\` experimental, opt-in.

Issue keycloak#43614 originally proposed SSF *Receiver* support (Keycloak ingesting SETs from upstream IdPs / risk engines). After exploring both sides, we're shipping the **Transmitter** first (see keycloak#48254) because it covers the strongest community asks (federate Keycloak events to downstream SaaS, Apple device fleet revoke flow) and lets us validate the SSF data-plane against real receivers before designing the harder "action mapping" question on the Receiver side. Receiver support remains on the roadmap and is tracked separately via keycloak#43614.

**In:**
- Compliance with SSF 1.0, CAEP 1.0, RISC 1.0, RFC 8935, RFC 8936, RFC 9493, RFC 8417
- SSF Transmitter support (Keycloak Realm can act as a SSF Transmitter)
- SSF Stream management (CRUD, status, verification)
- SSF Subjects management  (subjects)
- SET delivery via HTTP PUSH (RFC 8935) and HTTP POLL (RFC 8936) with  POLL in a return-immediately form
- SSF events temporarily stored in durable outbox with cluster-aware drainer and exponential backoff
- SSF Receivers managed as OIDC Clients with client credentials grant or auth code grant (currently only one stream per client)
- Support for SSF Stream, CAEP 1.0 and RISC 1.0  events (custom events via SPI)
- CAEP credential-change / session-revoked / (device-compliance-change) event mapping from native Keycloak events
- Support for RFC 9493 Subject Identifiers for Security Event Tokens
- Support for SSF Receiver subject event subscription with subject selection (per-user / per-orgssf.notify.<clientId>attribute, support fordefault_subjectspolicy (ALL, NONE))
- Support for Synthetic event emittance via REST endpoint for non-Keycloak-native event sources (external IAM solution)
- Per-receiver "Emit-only events" gate to suppress auto-emit per event type per receiver
- Support for legacy SSE CAEP profile for Apple Business Manager / Apple School Manager interop (verified)
- Per-realm SSF admin REST + Admin UI for SSF-enabled clients (Receiver / Stream / Subjects / Events)
- Prometheus metrics (dispatcher, drainer, poll, verification, outbox depth, delivery metrics)

**Out (tracked as separate follow-up issues):**
- SSF Receiver role for Keycloak (ingestion of SETs)
- POLL long-polling (\`returnImmediately=false\` honoured)
- Dedicated SSF signing key (separate from realm OIDC signing key)
- Chunked HELD release for very large backlogs
- Performance characterization + security review
- Formal interop matrix (caep.dev, ABM)

- [X] All code gated behind \`Profile.Feature.SSF\` (experimental, off by default)
- [X] Per-realm \`ssf.transmitterEnabled\` toggle; per-client \`ssf.enabled\` toggle
- [X] SSF event listener registered as global (not user-toggleable per realm)
- [X] Receiver-facing endpoints conformant with SSF 1.0
- [X] CAEP credential-change / session-revoked / device-compliance mapping pass interop testing against \`caep.dev\`
- [X] SSE CAEP profile narrowed shape works with Apple Business Manager
- [X] Integration test coverage for the dispatch / outbox / push / poll pipeline (100+ tests)
- [X] Prometheus metrics exposed under \`keycloak_ssf_*\`
- [X] Design notes published

Fixes keycloak#48901

This PR was partially co-authored with Claude AI

Signed-off-by: Thomas Darimont <thomas.darimont@googlemail.com>
@thomasdarimont
thomasdarimont force-pushed the issue/gh-48254-ssf-tx-support-v1 branch from eccb7de to ed6cd53 Compare May 11, 2026 19:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/ssf Shared Signals Framework — CAEP/RISC events, push delivery, event streams flaky-test kind/feature Categorizes a PR related to a new feature team/cloud-native team/core-iam

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Deliver the baseline to enable Keycloak as an SSF Transmitter

5 participants

0