Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
141 commits
Select commit Hold shift + click to select a range
463fb2f
Initial support for Shared Signals Framework
thomasdarimont Oct 20, 2025
fad9148
Next iteration of SSF support
thomasdarimont Nov 4, 2025
0e5730a
WIP Next iteration of SSF support
thomasdarimont Nov 7, 2025
d941386
WIP Next iteration of SSF support
thomasdarimont Nov 9, 2025
2730d44
WIP Refactoring
thomasdarimont Nov 9, 2025
be5da81
WIP Refactoring
thomasdarimont Nov 9, 2025
0d66f0e
Make spotless happy
thomasdarimont Nov 24, 2025
259a96f
Revise SSF Receiver support for review
thomasdarimont Nov 27, 2025
dccede1
Make it more explicit that this is only about SSF Receivers
thomasdarimont Nov 27, 2025
ee797a0
Use password controls for push auth header and transmitter access token
thomasdarimont Jan 30, 2026
1e756a5
Add HttpServerUtil helper to ease return HttpServer responses
thomasdarimont Jan 31, 2026
c807b25
Refactor SSF Receiver support
thomasdarimont Jan 31, 2026
7b98a1d
Add initial SsfReceiverTests
thomasdarimont Jan 31, 2026
4e427b5
Revise DefaultSsfEventListener
thomasdarimont Feb 1, 2026
9ae5480
Next iteration of SSF Receiver support
thomasdarimont Feb 12, 2026
366b451
Revise SSF Receiver Provider configuration UI
thomasdarimont Feb 12, 2026
1473b79
Split SSF Receiver Provider configuration UI in general / stream sett…
thomasdarimont Feb 12, 2026
cb15567
Split SSF Receiver Provider configuration UI in general / stream sett…
thomasdarimont Feb 12, 2026
5558dae
Add Trigger Verification to SSF Receiver Provider toolbar
thomasdarimont Feb 12, 2026
5be7c3e
Polishing
thomasdarimont Feb 12, 2026
2da4c43
Fix code review issues
thomasdarimont Feb 12, 2026
8daf9bc
Fix code review issues
thomasdarimont Feb 12, 2026
0c3864c
Fix code review issues
thomasdarimont Feb 12, 2026
ef600b3
Fix code review issues
thomasdarimont Feb 12, 2026
5905d0a
Fix code review issues
thomasdarimont Feb 12, 2026
a124fc2
Revise transmitterMetadataUrlHelp
thomasdarimont Feb 12, 2026
6be020e
Add client authentication support to SSF Receiver
thomasdarimont Feb 18, 2026
7d97ecb
Revise DefaultSsfEventListener
thomasdarimont Feb 18, 2026
afed92c
Allow idp lookups by SubjectUserLookup
thomasdarimont Feb 18, 2026
613a80e
Make SsfAdminRealmResourceProviderFactory environment dependent
thomasdarimont Feb 19, 2026
987ca90
Initial support for SSF Transmitters
thomasdarimont Mar 9, 2026
afe5465
SSF Refactoring
thomasdarimont Mar 17, 2026
8927e1c
SSF Refactoring
thomasdarimont Mar 17, 2026
127475f
Add support for transmitting SSF Events to multiple streams
thomasdarimont Mar 17, 2026
e75c2a1
Add support for async push delivery
thomasdarimont Mar 17, 2026
c0f8921
SSF: Ensure to use the provided push authorization header as-is
thomasdarimont Apr 9, 2026
3e069eb
SSF:Avoid using the legacy SSE CAEP events profile by default
thomasdarimont Apr 9, 2026
2b10bf5
SSF: Add admin UI for SSF Receiver capability and Transmitter toggle
thomasdarimont Apr 13, 2026
02cf21b
SSF: Add dedicated SSF tab, events SPI, stream admin API
thomasdarimont Apr 13, 2026
027e3e3
SSF: Source push endpoint timeouts from the server config
thomasdarimont Apr 13, 2026
5147be6
SSF: Ssf Cleanup
thomasdarimont Apr 13, 2026
5705588
SSF: Run spotless
thomasdarimont Apr 13, 2026
b8f5990
SSF: Make transmitter defaults configurable via SPI
thomasdarimont Apr 13, 2026
1125e11
SSF: Add initial SSF transmitter metadata tests
thomasdarimont Apr 13, 2026
2a2622b
SSF: Add initial SSF transmitter stream management tests
thomasdarimont Apr 13, 2026
1c9a93c
SSF: Add stream verification tests and fix async push delivery
thomasdarimont Apr 13, 2026
5fcde81
SSF: Add push delivery tests and fix stream status persistence
thomasdarimont Apr 13, 2026
2847299
SSF: Add SSF Transmitter push failure tests
thomasdarimont Apr 13, 2026
7748207
SSF: Add SSF Transmitter tests for custom events
thomasdarimont Apr 13, 2026
1361b32
SSF: Rename findAllEnabledStreams to findStreamsForSsfReceiverClients
thomasdarimont Apr 13, 2026
a69a4d3
SSF: Filter default supported events to emittable set and expose as a…
thomasdarimont Apr 13, 2026
ccf3394
SSF: Make Ssf.events()/transmitter()/receiver() and SET deserializati…
thomasdarimont Apr 13, 2026
b67315a
SSF: Align SET signing and verification with CAEP interop profile §2.6
thomasdarimont Apr 13, 2026
7a6214a
SSF: Add configurable user subject format for outgoing SETs
thomasdarimont Apr 13, 2026
228efe8
SSF: Revise SSF Receiver help message
thomasdarimont Apr 13, 2026
ef1d78d
SSF: Fix build issue in IdentityProviderSsfReceiver.tsx
thomasdarimont Apr 13, 2026
9f346d6
SSF: Move ssf classes from org.keycloak.protocol.ssf to org.keycloak.ssf
thomasdarimont Apr 14, 2026
7f529a0
SSF: Split-up SSF support into dedicated modules
thomasdarimont Apr 15, 2026
0e2667b
SSF: Add stream description, createdAt, updatedAt to stream section i…
thomasdarimont Apr 15, 2026
5eaf883
SSF: Add dedicated representations for StreamConfigInput and StreamCo…
thomasdarimont Apr 15, 2026
4f2b275
SSF: Enforce limits for SSF configuration request fields
thomasdarimont Apr 15, 2026
3e92693
SSF: Store SSF Receiver / Stream configuration as client attributes
thomasdarimont Apr 15, 2026
5d0526a
SSF: Explicitly pass KeycloakSession to SsfTransmitter resources
thomasdarimont Apr 15, 2026
d445a8a
SSF: Return stream status vua SsfAdminResource
thomasdarimont Apr 15, 2026
d539cfd
SSF: Ensure compatibility with SSE CAEP Profile for Apple Business Ma…
thomasdarimont Apr 15, 2026
16647fa
SSF: Add support for sending unsolicited steam verification events fr…
thomasdarimont Apr 15, 2026
e277ba0
SSF: Record the timestamp of the last verification request
thomasdarimont Apr 15, 2026
6df231f
SSF: Revise SecurityEventTokenDispatcher
thomasdarimont Apr 15, 2026
2580a26
SSF: Add support for creating streams directly from the admin ui
thomasdarimont Apr 15, 2026
a26eac4
SSF: Optimize SET creation in SsfTransmitterEventListener
thomasdarimont Apr 15, 2026
e31deae
SSF: Spotless
thomasdarimont Apr 15, 2026
5b49799
SSF: Send out verification events synchronously if possible
thomasdarimont Apr 16, 2026
e2f24f7
SSF: Mark SsfTransmitterEventListener as global
thomasdarimont Apr 16, 2026
9795199
SSF: Revise SsfTransmitterEventListener
thomasdarimont Apr 16, 2026
29a1600
SSF: Revise SSF Transmitter endpoint authentication
thomasdarimont Apr 16, 2026
de5c188
SSF: Remove support for using Keycloak as SSF Receiver
thomasdarimont Apr 16, 2026
5c1ea2b
SSF: Remove unused logger from DefaultSsfTransmitterProvider
thomasdarimont Apr 16, 2026
38cf0d6
SSF: PoC Transactional Outbox
thomasdarimont Apr 16, 2026
44fc1b1
SSF: Refactor Transmitter and SsfOutboxStore
thomasdarimont Apr 16, 2026
7e658f3
SSF: Add tests for SsfOutboxStore
thomasdarimont Apr 16, 2026
00da479
SSF: Refactoring
thomasdarimont Apr 16, 2026
b8ad999
SSF: Spotless
thomasdarimont Apr 16, 2026
952aed6
SSF: Revise SsfTransmitterMetadataWellKnownProvider infrastructure
thomasdarimont Apr 16, 2026
9ed7365
SSF: Spotless
thomasdarimont Apr 16, 2026
e9e0cec
SSF: Make default subjects configurable for transmitter
thomasdarimont Apr 16, 2026
6c9f068
SSF: Add transactional outbox, subject management, and admin UI
thomasdarimont Apr 17, 2026
a44437a
SSF: Rename URL helper methods and fix test imports after package move
thomasdarimont Apr 17, 2026
bb455bb
Fix root pom.xml after merge conflict
thomasdarimont Apr 17, 2026
dd53f6c
SSF: Add OpenAPI annotations to SSF endpoints
thomasdarimont Apr 17, 2026
8a8f595
SSF: Synthetic event emitter, nested receiver UI, factory-based event…
thomasdarimont Apr 17, 2026
ceb7e10
SSF: Make outbox table partition-friendly
thomasdarimont Apr 17, 2026
61b3701
SSF: HTTP POLL delivery (RFC 8936), sse-caep gate, hide kc_* from wire
thomasdarimont Apr 18, 2026
1bc5130
SSF: Treat 2XX Status code as successful push
thomasdarimont Apr 18, 2026
a58d23d
SSF: stream-updated SET, hold-on-pause, per-receiver event TTL
thomasdarimont Apr 18, 2026
d86aa7f
SSF: discard on disabled, hold in-flight on pause, push order tiebreak
thomasdarimont Apr 18, 2026
ea839b5
SSF: publish critical_subject_members in transmitter metadata
thomasdarimont Apr 18, 2026
20f8443
SSF: Ensure StreamUpdatedEvent is only sent when transitioning stream…
thomasdarimont Apr 18, 2026
f52a73e
SSF: PollErrorRepresentation with RFC 8936 err/description keys
thomasdarimont Apr 18, 2026
8f23629
SSF: fail-loud when email subject format has no email
thomasdarimont Apr 18, 2026
6489932
SSF: complex(user + tenant) subject format for multi-tenant SETs
thomasdarimont Apr 18, 2026
c32c32f
SSF: map credential events to accurate CAEP change_type
thomasdarimont Apr 18, 2026
1a55b30
SSF: admin "Pending Events" tab — lookup + emit from the console
thomasdarimont Apr 18, 2026
d869d69
SSF: inactivity_timeout + events-map=1 guard
thomasdarimont Apr 18, 2026
77e137e
SSF: Wrap SSF Tab contents into Cards
thomasdarimont Apr 18, 2026
370326d
SSF: migrate queued outbox rows on delivery-method change; apply stre…
thomasdarimont Apr 18, 2026
fb88e61
SSF: add Prometheus metrics binder for dispatcher / drainer / poll
thomasdarimont Apr 19, 2026
dce64bc
SSF: meter the verification path (receiver / admin / transmitter)
thomasdarimont Apr 19, 2026
d6d8fa4
SSF: §9.3 subject-removal grace tombstone (transmitter + per-receiver)
thomasdarimont Apr 19, 2026
d4db253
SSF: TransmitterContext bootstrap refactor + registry available/built…
thomasdarimont Apr 19, 2026
73cdec7
SSF: pluggable SsfSubjectInclusionResolver via TransmitterProvider
thomasdarimont Apr 19, 2026
f4cb4c7
SSF: Move logging of event SET to trace logging in PushDeliveryService
thomasdarimont Apr 19, 2026
6ce6169
SSF: add Description field to the Receiver tab
thomasdarimont Apr 19, 2026
1d6e23f
SSF: fix Audience help text on Receiver tab
thomasdarimont Apr 19, 2026
d15df15
SSF: per-receiver ssf.manualOnlyEvents (suppress native auto-emit)
thomasdarimont Apr 19, 2026
7462be3
SSF: smooth the custom-event extension surface
thomasdarimont Apr 19, 2026
be9499b
SSF: keycloak_ssf_drainer_tick_last_at_seconds gauge for stall detection
thomasdarimont Apr 19, 2026
bccc323
SSF: per-event validate() hook + CAEP credential_type translation
thomasdarimont Apr 20, 2026
5dc99cc
SSF: Remove dangling add SSF receiver provider message
thomasdarimont Apr 20, 2026
83ad30f
SSF: Add SSF tag to org.keycloak.common.constants.KeycloakOpenAPI
thomasdarimont Apr 20, 2026
b3e17f9
SSF: pre-token subject gate in native event listener
thomasdarimont Apr 20, 2026
499357e
SSF: Run ssf integration tests in the CI
thomasdarimont Apr 20, 2026
f496ed0
SSF: Fix timestamp checks in SsfPendingEventStoreTests to support pos…
thomasdarimont Apr 20, 2026
51c944f
SSF: Fix timestamp checks in SsfPendingEventStoreTests to support pos…
thomasdarimont Apr 20, 2026
a348b2b
SSF: Revise logging in SsfStreamManagementResource
thomasdarimont Apr 20, 2026
a6bcd4a
SSF: Ensure the stream config is correctly populated with overlays af…
thomasdarimont Apr 20, 2026
45c1094
SSF: Only stamp stream verification on explicitly requested verificat…
thomasdarimont Apr 20, 2026
a129b6b
SSF: Handle duplicate JSON export/import of SSF clients
thomasdarimont Apr 20, 2026
8ef93ee
SSF: Log unexpected exceptions as errors in createStream
thomasdarimont Apr 20, 2026
0a13169
SSF: Async batched outbox cleanup for client/realm removal
thomasdarimont Apr 20, 2026
15cc9a6
SSF: Make spotless happy
thomasdarimont Apr 21, 2026
82631d1
SSF: Map admin-initiated credential changes to CAEP events
thomasdarimont Apr 21, 2026
f101077
SSF: Fix polynomial ReDoS in admin-event path matchers
thomasdarimont Apr 22, 2026
124fb62
SSF: Rename SecurityEventTokenMapper.toSecurityEvent->toSecurityEven…
thomasdarimont Apr 22, 2026
a09d987
Adapted SSF tests for the Refactor builders in testsuite part 1
thomasdarimont Apr 23, 2026
d8aafd2
SSF: Allow exposing custom attributes in SsfEvents
thomasdarimont Apr 23, 2026
632ab93
SSF: Add additional credential attributes to CaepCredentialChange Event
thomasdarimont Apr 23, 2026
596ac32
SSF: Avoid NPE in SsfTab when emitting synthetic events
thomasdarimont Apr 24, 2026
f5783b6
SSF: Make outbox DELIVERED row retention configurable
thomasdarimont Apr 24, 2026
eccad4f
SSF: Extract SsfPushOutboxDrainerTask config parameters into SsfPushO…
thomasdarimont Apr 24, 2026
06f6463
SSF: Revise UI
thomasdarimont Apr 24, 2026
661a3ea
SSF: Add missing null check to applyCustomAttributes
thomasdarimont Apr 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1221,6 +1221,27 @@ jobs:
- name: Run tests
run: ./mvnw package -f scim/tests/pom.xml

ssf-integration-tests:
name: SSF IT
runs-on: ubuntu-latest
needs:
- build
timeout-minutes: 45
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0

- id: integration-test-setup
name: Integration test setup
uses: ./.github/actions/integration-test-setup

# This step is necessary because test/clustering requires building a new Keycloak image built from tar.gz
# file that is not part of m2-keycloak.tzts archive
- name: Build tar keycloak-quarkus-dist
run: ./mvnw package -pl quarkus/server/,quarkus/dist/

- name: Run tests
run: ./mvnw package -f ssf/tests/pom.xml

authzen-integration-tests:
name: AuthZen IT
runs-on: ubuntu-latest
Expand Down
2 changes: 2 additions & 0 deletions common/src/main/java/org/keycloak/common/Profile.java
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ public enum Feature {

DB_TIDB("TiDB database type", Type.EXPERIMENTAL),

SSF("Shared Signals Framework", Type.EXPERIMENTAL),

HTTP_OPTIMIZED_SERIALIZERS("Optimized JSON serializers for better performance of the HTTP layer", Type.PREVIEW),

OPENAPI("OpenAPI specification served at runtime", Type.EXPERIMENTAL, CLIENT_ADMIN_API_V2),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,19 @@ public static class Tags {
public static final String USERS = "Users";
public static final String ORGANIZATIONS = "Organizations";
public static final String WORKFLOWS = "Workflows";
public static final String SSF = "SSF";
private Tags() { }
}

}

public static class Ssf {

private Ssf() { }

public static class Tags {
public static final String TRANSMITTER = "SSF Transmitter";
private Tags() { }
}
}
}

Large diffs are not rendered by default.

82 changes: 82 additions & 0 deletions js/apps/admin-ui/src/clients/ClientDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import useToggle from "../utils/useToggle";
import { AdvancedTab } from "./AdvancedTab";
import { ClientSessions } from "./ClientSessions";
import { ClientSettings } from "./ClientSettings";
import { SsfTab } from "./SsfTab";
import { AuthorizationEvaluate } from "./authorization/AuthorizationEvaluate";
import { AuthorizationExport } from "./authorization/AuthorizationExport";
import { AuthorizationPermissions } from "./authorization/Permissions";
Expand All @@ -67,6 +68,7 @@ import {
import { ClientParams, ClientTab, toClient } from "./routes/Client";
import { toClientRole } from "./routes/ClientRole";
import { ClientScopesTab, toClientScopesTab } from "./routes/ClientScopeTab";
import { SsfClientTab, toSsfClientTab } from "./routes/ClientSsfTab";
import { toClients } from "./routes/Clients";
import { toCreateRole } from "./routes/NewRole";
import { ClientScopes } from "./scopes/ClientScopes";
Expand Down Expand Up @@ -225,6 +227,11 @@ export default function ClientDetails() {
defaultValue: "client-secret",
});

const ssfEnabled = useWatch({
control: form.control,
name: convertAttributeNameToForm<FormFields>("attributes.ssf.enabled"),
});

const [client, setClient] = useState<ClientRepresentation>();

const loader = async () => {
Expand All @@ -249,6 +256,7 @@ export default function ClientDetails() {
const sessionsTab = useRoutableTab(tab("sessions"));
const permissionsTab = useRoutableTab(tab("permissions"));
const advancedTab = useRoutableTab(tab("advanced"));
const ssfTab = useRoutableTab(tab("ssf"));
const eventsTab = useRoutableTab(tab("events"));

const [activeEventsTab, setActiveEventsTab] = useState("userEvents");
Expand All @@ -265,6 +273,17 @@ export default function ClientDetails() {
clientScopesTabRoute("evaluate"),
);

const ssfTabRoute = (tab: SsfClientTab) =>
toSsfClientTab({
realm,
clientId,
tab,
});
const ssfReceiverTab = useRoutableTab(ssfTabRoute("receiver"));
const ssfStreamTab = useRoutableTab(ssfTabRoute("stream"));
const ssfSubjectsTab = useRoutableTab(ssfTabRoute("subjects"));
const ssfPendingEventsTab = useRoutableTab(ssfTabRoute("pending-events"));

const authorizationTabRoute = (tab: AuthorizationTab) =>
toAuthorizationTab({
realm,
Expand Down Expand Up @@ -688,6 +707,69 @@ export default function ClientDetails() {
>
<AdvancedTab save={save} client={client} />
</Tab>
{client.protocol === "openid-connect" &&
!client.publicClient &&
ssfEnabled?.toString() === "true" && (
<Tab
id="ssf"
data-testid="ssfTab"
title={<TabTitleText>{t("ssf")}</TabTitleText>}
{...ssfTab}
>
<RoutableTabs
defaultLocation={ssfTabRoute("receiver")}
mountOnEnter
unmountOnExit
>
<Tab
id="ssfReceiverTab"
data-testid="ssfReceiverTab"
title={<TabTitleText>{t("ssfTabReceiver")}</TabTitleText>}
{...ssfReceiverTab}
>
<SsfTab
save={save}
client={client}
activeTab="receiver"
/>
</Tab>
<Tab
id="ssfStreamTab"
data-testid="ssfStreamTab"
title={<TabTitleText>{t("ssfTabStream")}</TabTitleText>}
{...ssfStreamTab}
>
<SsfTab save={save} client={client} activeTab="stream" />
</Tab>
<Tab
id="ssfSubjectsTab"
data-testid="ssfSubjectsTab"
title={<TabTitleText>{t("ssfTabSubjects")}</TabTitleText>}
{...ssfSubjectsTab}
>
<SsfTab
save={save}
client={client}
activeTab="subjects"
/>
</Tab>
<Tab
id="ssfPendingEventsTab"
data-testid="ssfPendingEventsTab"
title={
<TabTitleText>{t("ssfTabPendingEvents")}</TabTitleText>
}
{...ssfPendingEventsTab}
>
<SsfTab
save={save}
client={client}
activeTab="pending-events"
/>
</Tab>
</RoutableTabs>
</Tab>
)}
{hasAccess("view-events") && (
<Tab
data-testid="events-tab"
Expand Down
Loading
Loading