A pair of Curity Identity Server plugins that together enable global SSO session revocation. Packaged as a single JAR containing an Event Listener and an Authentication Action that share a Bucket to track active SSO sessions.
Listens for CreatedSsoSessionEvent and maintains a map of active SSO sessions per subject in a Bucket with purpose sso-sessions. Each session entry stores the session ID and the ACR used for authentication.
When a user authenticates and an SSO session is created, the listener either creates a new Bucket entry or appends the session to the existing map. Duplicate session IDs are ignored.
Plugin type: store-sso-session
An authentication action intended to run on SSO. It checks if the current SSO session ID exists in the Bucket. The action handles three states:
| Bucket State | Behavior |
|---|---|
| No bucket entry | New login or plugin just added. Stores the current session ID in the Bucket and allows SSO. |
| Session ID found | Session is valid. Allows SSO. |
| Session ID not found | Session has been revoked. Sets a configurable action attribute (default: sessionRevoked, configured via revocation-attribute-name) so that the authentication pipeline can handle it (e.g., with a Deny action that checks the attribute). |
Plugin type: check-session-status
Sessions can be revoked by removing individual session IDs from the Bucket. This can be done outside of the authentication flow, for example:
- Profile page - Allow users to view and revoke individual sessions
- Logout event listener - Listen for
LogoutAuthenticationEventto revoke sessions in all other browsers when a user logs out in one
Note: Revoking a session ID by updating the Bucket does not log the user out and does not trigger any server events. The revocation only takes effect the next time SSO is attempted and the action runs.
Both plugins require a Bucket backed by a data source.
<processing xmlns="https://curity.se/ns/conf/base">
<event-listeners>
<event-listener>
<id>store-sso</id>
<store-sso-session xmlns="https://curity.se/ns/ext-conf/store-sso-session">
<bucket>
<data-source>default-datasource</data-source>
</bucket>
<sessions-ttl>3600</sessions-ttl> <!-- optional, seconds, default 3600, 0 to disable -->
</store-sso-session>
</event-listener>
</event-listeners>
</processing>Configure the Check SSO Session Status action as an SSO action on the authenticator:
<authentication-actions>
<authentication-action>
<id>check_session_status</id>
<check-session-status xmlns="https://curity.se/ns/ext-conf/check-session-status">
<bucket>
<data-source>default-datasource</data-source>
</bucket>
<sessions-ttl>3600</sessions-ttl> <!-- optional, seconds, default 3600, 0 to disable -->
<revocation-attribute-name>sessionRevoked</revocation-attribute-name> <!-- optional, default "sessionRevoked" -->
</check-session-status>
</authentication-action>
</authentication-actions>
<authenticators>
<authenticator>
<id>my-authenticator</id>
<authentication-actions>
<sso>check_session_status</sso>
</authentication-actions>
<!-- ... -->
</authenticator>
</authenticators>Both plugins should use the same data source so they share the same Bucket.
| Option | Plugin | Default | Description |
|---|---|---|---|
sessions-ttl |
Both | 3600 |
Time-to-live in seconds for the bucket entry. Set to 0 to disable expiry. The expiry is refreshed on each update. |
revocation-attribute-name |
Action | sessionRevoked |
The action attribute name set to true when a session is revoked. Use this in a downstream Deny action's attribute condition. |
Requires JDK 21 and GitHub Packages credentials for the SDK dependency (GITHUB_ACTOR + GITHUB_TOKEN env vars, or gpr.user/gpr.token in gradle.properties). See https://github.com/Curity-PS/curity-plugin-dev?tab=readme-ov-file#github-authentication for details
./gradlew buildThe plugin JAR is created in build/release/ with:
./gradlew createReleaseDirDeploy to a local Curity server (requires IDSVR_HOME):
./gradlew deployToLocalIntegration tests spin up the Curity Identity Server in a Testcontainers-managed Docker container, deploy the plugin JAR, and exercise the flows end-to-end with a headless browser.
Requirements:
- Docker running locally (the test harness pulls the Curity Identity Server image and starts a container)
- A valid Curity Identity Server license (see below for the ways to provide it)
- GitHub Packages credentials (same as for
build) to resolve the SDK andcurity-ps-sdk-commonstest fixtures
The license key can be supplied in any of the following ways (checked in order):
LICENSE_KEYenvironment variable in the shell running Gradle- A
.envfile in the repository root containingLICENSE_KEY=<your-license-key>(see.env-example) — convenient for a per-repo setting curity.licenseKeyproperty in~/.gradle/gradle.properties— convenient for a global setting shared across Curity plugin repos (same pattern asgpr.user/gpr.token)
Run all integration tests:
./gradlew integrationTestRun a single spec:
./gradlew integrationTest --tests '*.CheckSessionStatusIntegrationSpec'The configuration applied to the container lives in src/test/resources/authentication-config.xml and src/test/resources/event-listener-config.xml.
This plugin is licensed under the Apache License, Version 2.0.