Skip to content

IdentityProviderAuthenticator creates an infinite redirect loop when an IdP returns an error (e.g. access_denied) and the login was initiated with kc_idp_hint #47955

@maeventer

Description

@maeventer

Before reporting an issue

  • I have read and understood the above terms for submitting issues, and I understand that my issue may be closed without action if I do not follow them.

Area

identity-brokering

Describe the bug

PR #47244 (commit 3e3191d) changed IdentityProviderAuthenticator.authenticate() to read kc_idp_hint from the authentication session client note as a fallback (for PAR support). However, when the IdP callback returns an error and Keycloak re-enters the browser flow via IdentityBrokerService.browserAuthentication(), the client note still contains the original kc_idp_hint value. The authenticator picks it up and re-redirects to the same IdP, creating an infinite loop.

The existing forwardedErrorMessage guard that prevents this loop exists only in the default-provider branch — the kc_idp_hint branch has no such check.

Version

26.6.0

Regression

  • The issue is a regression

Expected behavior

When an IdP returns an error (e.g. error=access_denied) during a kc_idp_hint-initiated login, IdentityProviderAuthenticator should call context.attempted() (as it did in 26.5.4), allowing subsequent authenticators in the flow to handle the error - such as showing the login page or redirecting the user back to the RP with an error.

Actual behavior

IdentityProviderAuthenticator reads the persisted kc_idp_hint from the authentication session client note and calls redirect() → context.forceChallenge(), sending the user back to the same failing IdP. This creates an infinite redirect loop.
Subsequent authenticators in the browser flow never execute.

How to Reproduce?

  1. Configure a browser flow with these ALTERNATIVE executions in order:
    • identity-provider-redirector
    • auth-username-password-form (or any other authenticator)
  2. Configure an external IdP (e.g. idp) in the realm
  3. Initiate a login with kc_idp_hint=idp: /realms/{realm}/protocol/openid-connect/auth?client_id=...&kc_idp_hint=idp
  4. On the IdP side, return an error: error=access_denied&error_description=User+denied+consent
  5. Observe that Keycloak redirects back to the IdP instead of falling through to the next authenticator

Anything else?

No response

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions