mirror of
https://github.com/keycloak/keycloak.git
synced 2026-04-24 16:08:48 -05:00
Allow forwarding parameters set as a client note in the authentication session
Closes #41670 Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com>
This commit is contained in:
@@ -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 `<root>{kc_realms_path}/{realm-name}/.well-known/openid-configuration`. This link is a JSON document describing metadata about the IDP.
|
||||
|
||||
+25
-17
@@ -505,8 +505,9 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
|
||||
.queryParam(OAUTH2_PARAMETER_RESPONSE_TYPE, "code")
|
||||
.queryParam(OAUTH2_PARAMETER_CLIENT_ID, getConfig().getClientId())
|
||||
.queryParam(OAUTH2_PARAMETER_REDIRECT_URI, request.getRedirectUri());
|
||||
AuthenticationSessionModel authenticationSession = request.getAuthenticationSession();
|
||||
String loginHint = authenticationSession.getClientNote(OIDCLoginProtocol.LOGIN_HINT_PARAM);
|
||||
|
||||
String loginHint = request.getAuthenticationSession().getClientNote(OIDCLoginProtocol.LOGIN_HINT_PARAM);
|
||||
if (getConfig().isLoginHint() && loginHint != null) {
|
||||
uriBuilder.queryParam(OIDCLoginProtocol.LOGIN_HINT_PARAM, loginHint);
|
||||
}
|
||||
@@ -517,31 +518,19 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
|
||||
|
||||
String prompt = getConfig().getPrompt();
|
||||
if (prompt == null || prompt.isEmpty()) {
|
||||
prompt = request.getAuthenticationSession().getClientNote(OAuth2Constants.PROMPT);
|
||||
prompt = authenticationSession.getClientNote(OAuth2Constants.PROMPT);
|
||||
}
|
||||
if (prompt != null) {
|
||||
uriBuilder.queryParam(OAuth2Constants.PROMPT, prompt);
|
||||
}
|
||||
|
||||
String acr = request.getAuthenticationSession().getClientNote(OAuth2Constants.ACR_VALUES);
|
||||
if (acr != null) {
|
||||
uriBuilder.queryParam(OAuth2Constants.ACR_VALUES, acr);
|
||||
}
|
||||
String forwardParameterConfig = getConfig().getForwardParameters() != null ? getConfig().getForwardParameters(): "";
|
||||
List<String> 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<C extends OAuth2IdentityPro
|
||||
return uriBuilder;
|
||||
}
|
||||
|
||||
private void setForwardParameters(AuthenticationSessionModel authenticationSession, UriBuilder uriBuilder) {
|
||||
C config = getConfig();
|
||||
String forwardParameterConfig = config.getForwardParameters() != null ? config.getForwardParameters(): OAuth2Constants.ACR_VALUES;
|
||||
|
||||
for (String forwardParameter: List.of(forwardParameterConfig.split("\\s*,\\s*"))) {
|
||||
String name = AuthorizationEndpoint.LOGIN_SESSION_NOTE_ADDITIONAL_REQ_PARAMS_PREFIX + forwardParameter.trim();
|
||||
String parameter = authenticationSession.getClientNote(name);
|
||||
|
||||
if (parameter == null) {
|
||||
// try a value set as a client note
|
||||
parameter = authenticationSession.getClientNote(forwardParameter);
|
||||
}
|
||||
|
||||
if (parameter != null && !parameter.isEmpty()) {
|
||||
uriBuilder.queryParam(forwardParameter, parameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get JSON property as text. JSON numbers and booleans are converted to text. Empty string is converted to null.
|
||||
*
|
||||
|
||||
+10
-2
@@ -11,8 +11,10 @@ import static org.keycloak.testsuite.broker.BrokerTestTools.waitForPage;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.admin.client.resource.UsersResource;
|
||||
import org.keycloak.models.IdentityProviderSyncMode;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.testsuite.Assert;
|
||||
@@ -36,7 +38,7 @@ public class KcOidcBrokerParameterForwardTest extends AbstractBrokerTest {
|
||||
IdentityProviderRepresentation idp = createIdentityProvider(IDP_OIDC_ALIAS, IDP_OIDC_PROVIDER_ID);
|
||||
Map<String, String> 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)));
|
||||
|
||||
Reference in New Issue
Block a user