Skip to content

curityio/sso-revocation-plugins

Repository files navigation

Quality

Session Revocation Management Plugins

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.

How It Works

Store SSO Session Event Listener

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

Check SSO Session Status Authentication Action

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

Session Revocation

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 LogoutAuthenticationEvent to 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.

Configuration

Both plugins require a Bucket backed by a data source.

Event Listener

<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>

Authentication Action

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.

Configuration Options

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.

Building

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 build

The plugin JAR is created in build/release/ with:

./gradlew createReleaseDir

Deploy to a local Curity server (requires IDSVR_HOME):

./gradlew deployToLocal

Running Integration Tests

Integration 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 and curity-ps-sdk-commons test fixtures

The license key can be supplied in any of the following ways (checked in order):

  1. LICENSE_KEY environment variable in the shell running Gradle
  2. A .env file in the repository root containing LICENSE_KEY=<your-license-key> (see .env-example) — convenient for a per-repo setting
  3. curity.licenseKey property in ~/.gradle/gradle.properties — convenient for a global setting shared across Curity plugin repos (same pattern as gpr.user/gpr.token)

Run all integration tests:

./gradlew integrationTest

Run 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.

License

This plugin is licensed under the Apache License, Version 2.0.

About

A set of plugins enabling the possibility to keep a status list for SSO sessions. Enabling a global logout by making sessions revokable

Resources

License

Stars

Watchers

Forks

Packages