OrganizationGroupMembershipMapper.resolveFromRequestedScopes() calls
OrganizationScope.valueOfScope() which returns null when the request does
not include an organization scope. The method then calls
resolveOrganizations() on the null reference, causing a NullPointerException.
This mirrors the null guard already present in OrganizationMembershipMapper.
Closes#48834
Signed-off-by: Umberto Toniolo <amountainram@gmail.com>
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 #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.
**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#48901
This PR was partially co-authored with Claude AI
Signed-off-by: Thomas Darimont <thomas.darimont@googlemail.com>
Enable the rule (previously "off") and fix all violations across the JS
workspace. The core change makes RealmContext.realmRepresentation
non-optional — guarded by the existing KeycloakSpinner in the provider —
allowing ~30 downstream consumers to drop redundant optional chains.
Where TypeScript types declare a value as non-nullable but runtime
behaviour can still produce undefined/null (API responses, react-hook-form
dynamic values, route params present on one route but not another, array
index access, DOM queries), the existing guards are preserved with
eslint-disable-next-line comments explaining the rationale.
Additional fixes surfaced during this work:
- PermissionConfigurationDetails: fix spinner blocking the "create
permission" form by distinguishing "loading" (null) from "new" ({})
- ResourceType: restore resourceIds?.some() guard — form.getValues
returns undefined when the field has no default value
- clients.ts createOrUpdatePolicy: narrow catch to 404 NetworkError
only instead of swallowing all errors
Closes#17770
Signed-off-by: Pierluigi Lenoci <pierluigilenoci@gmail.com>
* Resolve realm display name localization placeholders in TOTP issuer name
Resolve the realm display name before it is used as the issuer name when configuring TOTP credentials. This allows values that use localization placeholder syntax (e.g., ${realm.displayName}) to be resolved using the LOGIN theme messages and the user’s resolved locale, so authenticator applications show the localized display name instead of the raw placeholder.
Fixes#48680
Signed-off-by: Mohammed Elbagoury <m.a.bagoury@gmail.com>
* Cleanup the TotpUtils + add deprecation
Signed-off-by: Martin Bartoš <mabartos@redhat.com>
---------
Signed-off-by: Mohammed Elbagoury <m.a.bagoury@gmail.com>
Signed-off-by: Martin Bartoš <mabartos@redhat.com>
Co-authored-by: Martin Bartoš <mabartos@redhat.com>
Enforce RFC 6749 Section 3.1.2 redirect URI rules (no fragments, no wildcards) via a new "OAuth 2.0 Compliant" client policy flag. This is less strict than the existing OAuth 2.1 flag, which additionally bans localhost and requires HTTPS.
Also fixes the "complient" typo in the existing OAuth 2.1 field and method names.
Closes#41164
Signed-off-by: Jon Koops <jonkoops@gmail.com>