An identity service that connects application sign-in, account policies and directory integrations.
Several applications share this service for sign-in and sessions, and this single sign-on case study looks at how it works. Users, keys and login rules sit inside identity domains called realms. Each realm is set up on its own.
Within a realm, administrators can connect existing directories and apply policies that reach across applications. We built those connections on standard identity protocols. Each application can then rely on the service for its sign-in flow and its session handling.
The challenge
Applications can share users and still ask for other verification steps. One person may have several login attempts open in separate browser tabs. Each attempt needs its own context. It should still be able to use a valid session that already exists.
The hand-off to the application needs care. The service checks return addresses, one-time codes and client policies at the right stage. Error paths get the same checks.
What we built
The browser flow starts by looking for an existing sign-on session. If a sign-in is still needed, configurable stages handle the credentials and any extra verification. The options here include one-time codes, WebAuthn and passkeys. Recovery codes and outside identity providers round out the set.
A successful sign-in can lead to a required action, such as a password change. Account and admin consoles cover the management work, and a REST API handles the same tasks in code. Resources, policies and permissions set out access beyond login.
LDAP and related directory connections let existing identity systems stay in use, and brokering widens that choice to another OpenID Connect or SAML provider. Users can then sign in through the account source they already have.
Separate login state for each browser tab
A root authentication session holds per-tab state. Parallel login attempts can then keep their own client and flow context. The short-lived authentication session can expire. A restart cookie lets the user pick the attempt back up without starting over.
An unknown user still triggers dummy password-hash work, which hides whether the account exists. Repeated failures can switch on lockout rules. Conditional stages can ask for extra verification where an administrator has set it.
One-time code handling
The authorization endpoint validates the return address before it uses that address to send a response or an error. The token exchange checks the saved address and the client security settings a second time.
Reading an authorization code removes it from the store in the same step. If the code is used again, client-session cleanup is scheduled so that it survives a rollback of the failed request. Refresh-token rotation is set up on its own, because the single-use rule for an authorization code does not carry over to every token path.
Extensible authentication and shared policy
Authenticators and other server features arrive through interfaces and factories. A request-scoped session finds the providers and sets the database transaction boundary.
Client policies pair conditions with actions at named request events, such as the stages before a token request and before authorization. An administrator can apply one rule across connected applications at those points. Custom extensions carry a trade-off, because they need upkeep when server versions change, above all when they depend on private interfaces.
The server runs on Java and Quarkus. It stores data in a relational database with managed schema migrations. A production setup also needs an external database, set hostnames and a suitable TLS or proxy setup.
Project success
Connected applications can share authentication while they keep the verification rules set for their realm. Existing directories and outside identity providers stay available as account sources.
The session design holds parallel browser login attempts apart, while atomic code consumption and shared client policies supply the controls at the hand-off. Administrators can manage those controls in one place instead of building the whole flow into every application.
Technology stack
Server
Java, Quarkus
Persistence
JPA, Liquibase, supported relational databases
Cache and session infrastructure
Infinispan
Consoles
React, PatternFly
Themes
FreeMarker
Identity protocols
OpenID Connect, OAuth 2.0, SAML 2.0
Other engagements
Recognize the pattern?
If one of these looks like your situation, the discovery call is where we find out how close.