Introduction
When implementing Single Sign-On (SSO) with Google as an Identity Provider (IdP) in Keycloak, you may notice that a single user login generates multiple login events—one for each client application. This can cause confusion, especially when debugging authentication flows or tracking user sessions.
In this blog post, we will explore why this happens, how to replicate it locally, and how to fix or control this behavior using Keycloak settings.
Why Do Multiple Login Events Occur in Keycloak During Google SSO?
This issue arises due to the OAuth 2.0 Authorization Code Flow with OpenID Connect (OIDC) that Google follows. When a user logs into one client application and then accesses another client application under the same Keycloak realm, Keycloak registers a separate login event for each client.
Key Factors Contributing to Multiple Login Events
-
Google Uses a Shared Authentication Session:
- When a user logs into Client1 via Google, Google creates a session.
- When the user accesses Client2, Google detects the active session and automatically authenticates the user, without prompting for credentials.
- Even though the user did not re-enter credentials, Keycloak registers a new login event.
-
Keycloak Treats Each Client Separately:
- Keycloak considers each client as an independent entity.
- When a user accesses multiple clients, even within the same session, Keycloak triggers separate login events for tracking purposes.
-
Google Login Response Includes New ID Tokens Per Client:
- When Keycloak redirects the user to Google for login, Google issues a new ID Token for each client.
- Even though the user remains authenticated, the new token issuance results in a new event.
-
Keycloak Logs Each Authentication Request as a New Event:
- Keycloak logs a separate authentication event each time an authentication request is made to the IdP (Google), even if credentials are not re-entered.
How to Configure Session Handling in Keycloak
Keycloak allows you to control whether users share the same session across multiple clients or have separate sessions per client. This can help manage login events more effectively.
Using the Same Session Across Clients
To enforce session sharing across multiple clients:
Navigate to Realm Settings →
Tokens
Adjust the SSO Session Idle Timeout and SSO Session Max Lifespan to maintain session continuity.
Ensure that Full Scope Allowed is enabled for clients to share user sessions.
Use the
SameSite=None
cookie setting to ensure session continuity in cross-client authentication.
Controlling the Number of Sessions in Keycloak
To limit how many active sessions a user can have:
Navigate to Realm Settings →
Sessions
.Configure
Maximum Sessions per User
to define the maximum concurrent sessions allowed.Enable
Single Sign-Out
so that logging out from one session logs the user out from all active sessions.Adjust
Session Limits
per client under Clients →client1
→Settings
.
These settings help you control how sessions are handled across different clients and prevent excessive login events.
Using Separate Sessions Per Client
If you need independent sessions for each client:
Disable Full Scope Allowed for the client under Clients →
client1
orclient2
.Set Client Session Idle Timeout and Client Session Max Lifespan separately for each client under Advanced Settings.
Use the
prompt=login
parameter to force Google authentication for each client.
How to Replicate Multiple Login Events Locally
Step 1: Set Up Keycloak Locally
- Start Keycloak in development mode:
./kc.sh start-dev
- Create a new realm (e.g.,
my-realm
). - Create two clients (
client1
andclient2
) in the same realm. - Configure both clients to use Google as an Identity Provider:
- Go to
Identity Providers
→Add provider
→Google
. - Configure the Client ID and Client Secret from your Google Cloud Console.
- Set
Redirect URIs
for both clients (http://localhost:8081/*
andhttp://localhost:8082/*
). - Enable
Standard Flow
andImplicit Flow
.
- Go to
Step 2: Run Two Applications Using Keycloak Authentication
Run two separate web applications:
- Client1 →
http://localhost:8081
- Client2 →
http://localhost:8082
Ensure both applications:
- Use the same Keycloak realm.
- Have
client_id
configured accordingly. - Redirect to Google for authentication.
Step 3: Simulate an SSO Login Flow
- Open an Incognito browser window.
- Navigate to
http://localhost:8081
and initiate login. - Authenticate using Google.
- Open another tab and go to
http://localhost:8082
. - Notice that the second application logs in without prompting for credentials.
- Check Keycloak logs under
Events
→Login Events
, and you will see two separate login entries.
How to Fix or Control This Behavior
1. Enable Single Session Across Clients
By default, Keycloak logs each client authentication as a separate event. However, we can enforce session sharing across clients:
- Go to Realm Settings →
Tokens
- Increase the SSO Session Max Lifespan to keep the session active longer.
- Increase SSO Session Idle Timeout to avoid unnecessary re-authentication.
2. Adjust Client Session Settings
Each client may have different session handling settings. To standardize session behavior across clients:
- Navigate to Clients →
client1
orclient2
. - Under Advanced Settings, adjust the SSO Session Idle Timeout.
- Ensure
Full Scope Allowed
is enabled to share user sessions across multiple clients.
3. Enforce User Session Limits
To control how many login events are generated:
- Go to Realm Settings →
Sessions
. - Set
Maximum Sessions per User
to 1 to ensure a single session is active at a time. - Enable
Single Sign-Out
to ensure logging out from one client logs the user out from all clients.
4. Modify Google Authentication Prompt Behavior
If you want Google to prompt users for login every time (rather than using an existing session), modify the authentication request:
- In the Keycloak Identity Provider settings for Google, set the
prompt
parameter:prompt=select_account
- This forces Google to show the account selection screen every time a login is requested.
5. Control Login Event Logging in Keycloak
If you want to reduce unnecessary login event logging, you can modify Keycloak’s logging levels:
./kc.sh start-dev --log-level=INFO
Or update the logging configuration in standalone.xml:
<logger category="org.keycloak.events">
<level name="WARN"/>
</logger>
How Custom SSO Calls Trigger Login Events in Keycloak
Custom authentication flows in Keycloak can also trigger login events. Here’s how:
-
Using Keycloak REST API for Login:
- When calling the
POST /realms/{realm}/protocol/openid-connect/token
endpoint with valid credentials, Keycloak registers a login event.
- When calling the
-
Programmatic Login via JavaScript Adapter:
keycloak.login({ redirectUri: 'http://localhost:8081/home' });
- This triggers a login event for the client initiating the request.
-
Custom Authentication Flows:
- Implementing a custom authenticator in Keycloak SPI that handles login logic can generate login events.
-
Silent Authentication Requests:
- When the frontend attempts a silent login via
check-sso
, Keycloak may log an event if a session refresh is required.
- When the frontend attempts a silent login via
Conclusion
Experiencing multiple login events when using Google SSO with Keycloak is a common scenario due to how OAuth 2.0 and OIDC work. The main reasons include Google’s session management, Keycloak’s client separation, and Google issuing new ID tokens per client.
By following the recommended fixes and understanding how custom SSO calls interact with Keycloak, you can control and optimize login event handling effectively.