From 84fc9bb3e58688f045e397d43bdeda0f8834d995 Mon Sep 17 00:00:00 2001 From: Pedro Igor Date: Tue, 5 Aug 2025 11:04:36 -0300 Subject: [PATCH] Allow forwarding parameters set as a client note in the authentication session Closes #41670 Signed-off-by: Pedro Igor --- .../topics/identity-broker/oidc.adoc | 4 ++ .../oidc/AbstractOAuth2IdentityProvider.java | 42 +++++++++++-------- .../KcOidcBrokerParameterForwardTest.java | 12 +++++- 3 files changed, 39 insertions(+), 19 deletions(-) diff --git a/docs/documentation/server_admin/topics/identity-broker/oidc.adoc b/docs/documentation/server_admin/topics/identity-broker/oidc.adoc index 439741dc584..06894528a1c 100644 --- a/docs/documentation/server_admin/topics/identity-broker/oidc.adoc +++ b/docs/documentation/server_admin/topics/identity-broker/oidc.adoc @@ -81,6 +81,10 @@ If the user is unauthenticated in the IDP, the client still receives a `login_re |Validating Public Key Id |This setting applies if *Use JWKS URL* is *OFF*. This setting specifies the ID of the public key in PEM format. Because there is no standard way for computing key ID from the key, external identity providers can use different algorithms from what {project_name} uses. If this field's value is not specified, {project_name} uses the validating public key for all requests, regardless of the key ID sent by the external IDP. When *ON*, this field's value is the key ID used by {project_name} for validating signatures from providers and must match the key ID specified by the IDP. +|Forwarded query parameters +| Define the query parameters to be forwarded to an external AS from the initial authorization request sent to the authorization endpoint. Multiple parameters can be entered, separated by comma (,). The parameters available +to forward are any non OpenID Connect/OAuth standard parameter or standard parameters that are available as a client note from the authentication session. + |=== You can import all this configuration data by providing a URL or file that points to OpenID Provider Metadata. If you connect to a {project_name} external IDP, you can import the IDP settings from `{kc_realms_path}/{realm-name}/.well-known/openid-configuration`. This link is a JSON document describing metadata about the IDP. diff --git a/services/src/main/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProvider.java b/services/src/main/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProvider.java index 196ef1b97c5..67a13658d7e 100755 --- a/services/src/main/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProvider.java +++ b/services/src/main/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProvider.java @@ -505,8 +505,9 @@ public abstract class AbstractOAuth2IdentityProvider forwardParameters = Arrays.asList(forwardParameterConfig.split("\\s*,\\s*")); - for(String forwardParameter: forwardParameters) { - String name = AuthorizationEndpoint.LOGIN_SESSION_NOTE_ADDITIONAL_REQ_PARAMS_PREFIX + forwardParameter.trim(); - String parameter = request.getAuthenticationSession().getClientNote(name); - if(parameter != null && !parameter.isEmpty()) { - uriBuilder.queryParam(forwardParameter, parameter); - } - } + setForwardParameters(authenticationSession, uriBuilder); if (getConfig().isPkceEnabled()) { String codeVerifier = PkceUtils.generateCodeVerifier(); String codeChallengeMethod = getConfig().getPkceMethod(); - request.getAuthenticationSession().setClientNote(BROKER_CODE_CHALLENGE_PARAM, codeVerifier); - request.getAuthenticationSession().setClientNote(BROKER_CODE_CHALLENGE_METHOD_PARAM, codeChallengeMethod); + authenticationSession.setClientNote(BROKER_CODE_CHALLENGE_PARAM, codeVerifier); + authenticationSession.setClientNote(BROKER_CODE_CHALLENGE_METHOD_PARAM, codeChallengeMethod); String codeChallenge = PkceUtils.encodeCodeChallenge(codeVerifier, codeChallengeMethod); uriBuilder.queryParam(OAuth2Constants.CODE_CHALLENGE, codeChallenge); @@ -551,6 +540,25 @@ public abstract class AbstractOAuth2IdentityProvider config = idp.getConfig(); applyDefaultConfiguration(config, syncMode); - config.put("forwardParameters", FORWARDED_PARAMETER +", " + PARAMETER_NOT_SET); + config.put("forwardParameters", FORWARDED_PARAMETER +", " + PARAMETER_NOT_SET + ", " + OAuth2Constants.ACR_VALUES + ", " + OIDCLoginProtocol.CLAIMS_PARAM); return idp; } } @@ -46,7 +48,9 @@ public class KcOidcBrokerParameterForwardTest extends AbstractBrokerTest { oauth.clientId("broker-app"); loginPage.open(bc.consumerRealmName()); - String queryString = "&" + FORWARDED_PARAMETER + "=" + FORWARDED_PARAMETER_VALUE + "&" + PARAMETER_NOT_FORWARDED + "=" + "value"; + String queryString = "&" + FORWARDED_PARAMETER + "=" + FORWARDED_PARAMETER_VALUE + "&" + PARAMETER_NOT_FORWARDED + "=" + "value" + + "&" + OAuth2Constants.ACR_VALUES + "=" + "phr" + + "&" + OIDCLoginProtocol.CLAIMS_PARAM + "=" + "myclaims"; driver.navigate().to(driver.getCurrentUrl() + queryString); log.debug("Clicking social " + bc.getIDPAlias()); @@ -59,6 +63,10 @@ public class KcOidcBrokerParameterForwardTest extends AbstractBrokerTest { assertThat(FORWARDED_PARAMETER + "=" + FORWARDED_PARAMETER_VALUE + " should be part of the url", driver.getCurrentUrl(), containsString(FORWARDED_PARAMETER + "=" + FORWARDED_PARAMETER_VALUE)); + assertThat(OAuth2Constants.ACR_VALUES + "=" + "phr" + " should be part of the url", + driver.getCurrentUrl(), containsString(OAuth2Constants.ACR_VALUES + "=" + "phr")); + assertThat(OIDCLoginProtocol.CLAIMS_PARAM + "=" + "myclaims" + " should be part of the url", + driver.getCurrentUrl(), containsString(OIDCLoginProtocol.CLAIMS_PARAM + "=" + "myclaims")); assertThat("\"" + PARAMETER_NOT_SET + "\"" + " should NOT be part of the url", driver.getCurrentUrl(), not(containsString(PARAMETER_NOT_SET)));