KEYCLOAK-18903 More customizable OIDC WellKnown provider
This commit is contained in:
parent
7efc3e8170
commit
9b0e1fff8d
11 changed files with 315 additions and 17 deletions
|
@ -46,6 +46,7 @@ import org.keycloak.services.clientregistration.ClientRegistrationService;
|
|||
import org.keycloak.services.clientregistration.oidc.OIDCClientRegistrationProviderFactory;
|
||||
import org.keycloak.services.resources.RealmsResource;
|
||||
import org.keycloak.urls.UrlType;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
import org.keycloak.wellknown.WellKnownProvider;
|
||||
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
|
@ -88,10 +89,18 @@ public class OIDCWellKnownProvider implements WellKnownProvider {
|
|||
// KEYCLOAK-7451 OAuth Authorization Server Metadata for Proof Key for Code Exchange
|
||||
public static final List<String> DEFAULT_CODE_CHALLENGE_METHODS_SUPPORTED = list(OAuth2Constants.PKCE_METHOD_PLAIN, OAuth2Constants.PKCE_METHOD_S256);
|
||||
|
||||
private KeycloakSession session;
|
||||
private final KeycloakSession session;
|
||||
private final Map<String, Object> openidConfigOverride;
|
||||
private final boolean includeClientScopes;
|
||||
|
||||
public OIDCWellKnownProvider(KeycloakSession session) {
|
||||
this(session, null, true);
|
||||
}
|
||||
|
||||
public OIDCWellKnownProvider(KeycloakSession session, Map<String, Object> openidConfigOverride, boolean includeClientScopes) {
|
||||
this.session = session;
|
||||
this.openidConfigOverride = openidConfigOverride;
|
||||
this.includeClientScopes = includeClientScopes;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -150,12 +159,15 @@ public class OIDCWellKnownProvider implements WellKnownProvider {
|
|||
config.setClaimTypesSupported(DEFAULT_CLAIM_TYPES_SUPPORTED);
|
||||
config.setClaimsParameterSupported(true);
|
||||
|
||||
List<String> scopeNames = realm.getClientScopesStream()
|
||||
.filter(clientScope -> Objects.equals(OIDCLoginProtocol.LOGIN_PROTOCOL, clientScope.getProtocol()))
|
||||
.map(ClientScopeModel::getName)
|
||||
.collect(Collectors.toList());
|
||||
scopeNames.add(0, OAuth2Constants.SCOPE_OPENID);
|
||||
config.setScopesSupported(scopeNames);
|
||||
// Include client scopes can be disabled in the environments with thousands of client scopes to avoid potentially expensive iteration over client scopes
|
||||
if (includeClientScopes) {
|
||||
List<String> scopeNames = realm.getClientScopesStream()
|
||||
.filter(clientScope -> Objects.equals(OIDCLoginProtocol.LOGIN_PROTOCOL, clientScope.getProtocol()))
|
||||
.map(ClientScopeModel::getName)
|
||||
.collect(Collectors.toList());
|
||||
scopeNames.add(0, OAuth2Constants.SCOPE_OPENID);
|
||||
config.setScopesSupported(scopeNames);
|
||||
}
|
||||
|
||||
config.setRequestParameterSupported(true);
|
||||
config.setRequestUriParameterSupported(true);
|
||||
|
@ -190,6 +202,7 @@ public class OIDCWellKnownProvider implements WellKnownProvider {
|
|||
MTLSEndpointAliases mtlsEndpointAliases = getMtlsEndpointAliases(config);
|
||||
config.setMtlsEndpointAliases(mtlsEndpointAliases);
|
||||
|
||||
config = checkConfigOverride(config);
|
||||
return config;
|
||||
}
|
||||
|
||||
|
@ -269,4 +282,15 @@ public class OIDCWellKnownProvider implements WellKnownProvider {
|
|||
mtls_endpoints.setPushedAuthorizationRequestEndpoint(config.getPushedAuthorizationRequestEndpoint());
|
||||
return mtls_endpoints;
|
||||
}
|
||||
|
||||
private OIDCConfigurationRepresentation checkConfigOverride(OIDCConfigurationRepresentation config) {
|
||||
if (openidConfigOverride != null) {
|
||||
Map<String, Object> asMap = JsonSerialization.mapper.convertValue(config, Map.class);
|
||||
// Override configuration
|
||||
asMap.putAll(openidConfigOverride);
|
||||
return JsonSerialization.mapper.convertValue(asMap, OIDCConfigurationRepresentation.class);
|
||||
} else {
|
||||
return config;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,9 +17,16 @@
|
|||
|
||||
package org.keycloak.protocol.oidc;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.common.util.FindFile;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
import org.keycloak.wellknown.WellKnownProvider;
|
||||
import org.keycloak.wellknown.WellKnownProviderFactory;
|
||||
|
||||
|
@ -30,13 +37,36 @@ public class OIDCWellKnownProviderFactory implements WellKnownProviderFactory {
|
|||
|
||||
public static final String PROVIDER_ID = "openid-configuration";
|
||||
|
||||
private static final Logger logger = Logger.getLogger(OIDCWellKnownProviderFactory.class);
|
||||
|
||||
private Map<String, Object> openidConfigOverride = null;
|
||||
private boolean includeClientScopes = true;
|
||||
|
||||
@Override
|
||||
public WellKnownProvider create(KeycloakSession session) {
|
||||
return new OIDCWellKnownProvider(session);
|
||||
return new OIDCWellKnownProvider(session, openidConfigOverride, includeClientScopes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
String openidConfigurationOverride = config.get("openid-configuration-override");
|
||||
this.includeClientScopes = config.getBoolean("include-client-scopes", true);
|
||||
logger.debugf("Include Client Scopes in OIDC Well-known endpoint: %s", this.includeClientScopes);
|
||||
if (openidConfigurationOverride != null) {
|
||||
initConfigOverrideFromFile(openidConfigurationOverride);
|
||||
}
|
||||
}
|
||||
|
||||
protected void initConfigOverrideFromFile(String openidConfigurationOverrideFile) {
|
||||
try {
|
||||
InputStream is = FindFile.findFile(openidConfigurationOverrideFile);
|
||||
this.openidConfigOverride = JsonSerialization.readValue(is, Map.class);
|
||||
logger.infof("Overriding default OIDC well-known endpoint configuration with the options from file '%s'", openidConfigurationOverrideFile);
|
||||
} catch (RuntimeException re) {
|
||||
logger.warnf(re, "Unable to find file specified for openid-configuration-override on custom location '%s'. Will stick to the default configuration for OIDC WellKnown endpoint", openidConfigurationOverrideFile);
|
||||
} catch (IOException ioe) {
|
||||
logger.warnf(ioe, "Error when trying to deserialize JSON from the file '%s'. Check the JSON format. Will stick to the default configuration for OIDC WellKnown endpoint", openidConfigurationOverrideFile);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -52,4 +82,13 @@ public class OIDCWellKnownProviderFactory implements WellKnownProviderFactory {
|
|||
return PROVIDER_ID;
|
||||
}
|
||||
|
||||
// Custom implementation with alias "openid-configuration" should win over this default one
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 100;
|
||||
}
|
||||
|
||||
protected Map<String, Object> getOpenidConfigOverride() {
|
||||
return openidConfigOverride;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.keycloak.models.KeycloakSession;
|
|||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.protocol.LoginProtocol;
|
||||
import org.keycloak.protocol.LoginProtocolFactory;
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
import org.keycloak.services.CorsErrorResponseException;
|
||||
import org.keycloak.services.clientregistration.ClientRegistrationService;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
|
@ -40,6 +41,7 @@ import org.keycloak.services.util.CacheControlUtil;
|
|||
import org.keycloak.services.util.ResolveRelative;
|
||||
import org.keycloak.utils.ProfileHelper;
|
||||
import org.keycloak.wellknown.WellKnownProvider;
|
||||
import org.keycloak.wellknown.WellKnownProviderFactory;
|
||||
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.NotFoundException;
|
||||
|
@ -47,7 +49,6 @@ import javax.ws.rs.OPTIONS;
|
|||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
@ -55,6 +56,8 @@ import javax.ws.rs.core.Response.ResponseBuilder;
|
|||
import javax.ws.rs.core.UriBuilder;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import java.net.URI;
|
||||
import java.util.Comparator;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
|
@ -243,14 +246,22 @@ public class RealmsResource {
|
|||
}
|
||||
|
||||
@GET
|
||||
@Path("{realm}/.well-known/{provider}")
|
||||
@Path("{realm}/.well-known/{alias}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response getWellKnown(final @PathParam("realm") String name,
|
||||
final @PathParam("provider") String providerName) {
|
||||
final @PathParam("alias") String alias) {
|
||||
RealmModel realm = init(name);
|
||||
checkSsl(realm);
|
||||
|
||||
WellKnownProvider wellKnown = session.getProvider(WellKnownProvider.class, providerName);
|
||||
WellKnownProviderFactory wellKnownProviderFactoryFound = session.getKeycloakSessionFactory().getProviderFactoriesStream(WellKnownProvider.class)
|
||||
.map(providerFactory -> (WellKnownProviderFactory) providerFactory)
|
||||
.filter(wellKnownProviderFactory -> alias.equals(wellKnownProviderFactory.getAlias()))
|
||||
.sorted(Comparator.comparingInt(WellKnownProviderFactory::getPriority))
|
||||
.findFirst().orElseThrow(NotFoundException::new);
|
||||
|
||||
logger.tracef("Use provider with ID '%s' for well-known alias '%s'", wellKnownProviderFactoryFound.getId(), alias);
|
||||
|
||||
WellKnownProvider wellKnown = session.getProvider(WellKnownProvider.class, wellKnownProviderFactoryFound.getId());
|
||||
|
||||
if (wellKnown != null) {
|
||||
ResponseBuilder responseBuilder = Response.ok(wellKnown.getConfig()).cacheControl(CacheControlUtil.noCache());
|
||||
|
|
|
@ -24,4 +24,24 @@ import org.keycloak.provider.ProviderFactory;
|
|||
*/
|
||||
public interface WellKnownProviderFactory extends ProviderFactory<WellKnownProvider> {
|
||||
|
||||
/**
|
||||
* Alias, which will be used as URL suffix of this well-known provider. For example if you use alias like "openid-configuration", then your WellKnown provider
|
||||
* might be available under URL like "https://myhost/auth/realms/myrealm/.well-known/openid-configuration". If there are multiple provider factories with same alias,
|
||||
* the one with lowest priority will be used.
|
||||
*
|
||||
* @see #getPriority()
|
||||
*
|
||||
*/
|
||||
default String getAlias() {
|
||||
return getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Use low priority, so custom implementation with alias "openid-configuration" will win over the default implementation
|
||||
* with alias "openid-configuration", which is provided by Keycloak (OIDCWellKnownProviderFactory).
|
||||
*
|
||||
*/
|
||||
default int getPriority() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -954,6 +954,18 @@ public class TestingResourceProvider implements RealmResourceProvider {
|
|||
}
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/set-system-property")
|
||||
@Consumes(MediaType.TEXT_HTML_UTF_8)
|
||||
@NoCache
|
||||
public void setSystemPropertyOnServer(@QueryParam("property-name") String propertyName, @QueryParam("property-value") String propertyValue) {
|
||||
if (propertyValue == null) {
|
||||
System.getProperties().remove(propertyName);
|
||||
} else {
|
||||
System.setProperty(propertyName, propertyValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This will send POST request to specified URL with specified form parameters. It's not easily possible to "trick" web driver to send POST
|
||||
* request with custom parameters, which are not directly available in the form.
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright 2021 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.wellknown;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.protocol.oidc.OIDCWellKnownProvider;
|
||||
import org.keycloak.protocol.oidc.representations.MTLSEndpointAliases;
|
||||
import org.keycloak.protocol.oidc.representations.OIDCConfigurationRepresentation;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class CustomOIDCWellKnownProvider extends OIDCWellKnownProvider {
|
||||
|
||||
public CustomOIDCWellKnownProvider(KeycloakSession session, Map<String, Object> openidConfigOverride, boolean includeClientScopes) {
|
||||
super(session, openidConfigOverride, includeClientScopes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getConfig() {
|
||||
OIDCConfigurationRepresentation config = (OIDCConfigurationRepresentation) super.getConfig();
|
||||
config.getOtherClaims().put("foo", "bar");
|
||||
return config;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MTLSEndpointAliases getMtlsEndpointAliases(OIDCConfigurationRepresentation config) {
|
||||
MTLSEndpointAliases mtlsEndpointAliases = super.getMtlsEndpointAliases(config);
|
||||
mtlsEndpointAliases.setRegistrationEndpoint("https://placeholder-host-set-by-testsuite-provider/registration");
|
||||
return mtlsEndpointAliases;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright 2021 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.wellknown;
|
||||
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.protocol.oidc.OIDCWellKnownProviderFactory;
|
||||
import org.keycloak.wellknown.WellKnownProvider;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class CustomOIDCWellKnownProviderFactory extends OIDCWellKnownProviderFactory {
|
||||
|
||||
public static final String INCLUDE_CLIENT_SCOPES = "oidc.wellknown.include.client.scopes";
|
||||
|
||||
@Override
|
||||
public WellKnownProvider create(KeycloakSession session) {
|
||||
return new CustomOIDCWellKnownProvider(session, getOpenidConfigOverride(), includeClientScopes());
|
||||
}
|
||||
|
||||
private boolean includeClientScopes() {
|
||||
String includeClientScopesProp = System.getProperty("oidc.wellknown.include.client.scopes");
|
||||
return includeClientScopesProp == null || Boolean.parseBoolean(includeClientScopesProp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
ClassLoader orig = Thread.currentThread().getContextClassLoader();
|
||||
try {
|
||||
Thread.currentThread().setContextClassLoader(CustomOIDCWellKnownProviderFactory.class.getClassLoader());
|
||||
initConfigOverrideFromFile("classpath:wellknown/oidc-well-known-config-override.json");
|
||||
} finally {
|
||||
Thread.currentThread().setContextClassLoader(orig);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "custom-testsuite-oidc-well-known-factory";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAlias() {
|
||||
return OIDCWellKnownProviderFactory.PROVIDER_ID;
|
||||
}
|
||||
|
||||
// Should be prioritized over default factory
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 1;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# Copyright 2021 Red Hat, Inc. and/or its affiliates
|
||||
# and other contributors as indicated by the @author tags.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
#
|
||||
|
||||
org.keycloak.testsuite.wellknown.CustomOIDCWellKnownProviderFactory
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"some-new-property": "some-new-property-value",
|
||||
"some-new-property-compound": {
|
||||
"nested1": "nested-value"
|
||||
},
|
||||
"introspection_endpoint_auth_methods_supported": ["private_key_jwt", "client_secret_jwt", "tls_client_auth", "custom_nonexisting_authenticator"]
|
||||
}
|
|
@ -342,6 +342,14 @@ public interface TestingResource {
|
|||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
Response disableFeature(@PathParam("feature") String feature);
|
||||
|
||||
/**
|
||||
* If property-value is null, the system property will be unset (removed) on the server
|
||||
*/
|
||||
@GET
|
||||
@Path("/set-system-property")
|
||||
@Consumes(MediaType.TEXT_HTML_UTF_8)
|
||||
void setSystemPropertyOnServer(@QueryParam("property-name") String propertyName, @QueryParam("property-value") String propertyValue);
|
||||
|
||||
|
||||
/**
|
||||
* This method is here just to have all endpoints from TestingResourceProvider available here.
|
||||
|
|
|
@ -43,10 +43,12 @@ import org.keycloak.services.resources.RealmsResource;
|
|||
import org.keycloak.testsuite.AbstractKeycloakTest;
|
||||
import org.keycloak.testsuite.Assert;
|
||||
import org.keycloak.testsuite.admin.AbstractAdminTest;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude;
|
||||
import org.keycloak.testsuite.util.AdminClientUtil;
|
||||
import org.keycloak.testsuite.util.ClientManager;
|
||||
import org.keycloak.testsuite.util.OAuthClient;
|
||||
import org.keycloak.testsuite.util.TokenSignatureUtil;
|
||||
import org.keycloak.testsuite.wellknown.CustomOIDCWellKnownProviderFactory;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
import javax.ws.rs.client.Client;
|
||||
|
@ -57,8 +59,10 @@ import javax.ws.rs.core.UriBuilder;
|
|||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer.REMOTE;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
|
@ -148,8 +152,8 @@ public class OIDCWellKnownProviderTest extends AbstractKeycloakTest {
|
|||
// Client authentication
|
||||
Assert.assertNames(oidcConfig.getTokenEndpointAuthMethodsSupported(), "client_secret_basic", "client_secret_post", "private_key_jwt", "client_secret_jwt", "tls_client_auth");
|
||||
Assert.assertNames(oidcConfig.getTokenEndpointAuthSigningAlgValuesSupported(), Algorithm.PS256, Algorithm.PS384, Algorithm.PS512, Algorithm.RS256, Algorithm.RS384, Algorithm.RS512, Algorithm.ES256, Algorithm.ES384, Algorithm.ES512, Algorithm.HS256, Algorithm.HS384, Algorithm.HS512);
|
||||
Assert.assertNames(oidcConfig.getIntrospectionEndpointAuthMethodsSupported(), "client_secret_basic",
|
||||
"client_secret_post", "private_key_jwt", "client_secret_jwt", "tls_client_auth");
|
||||
// NOTE: Those are overriden in "oidc-well-known-config-override.json" and they are tested in testDefaultProviderCustomizations
|
||||
//Assert.assertNames(oidcConfig.getIntrospectionEndpointAuthMethodsSupported(), "private_key_jwt", "client_secret_jwt", "tls_client_auth", "custom_nonexisting_authenticator");
|
||||
Assert.assertNames(oidcConfig.getIntrospectionEndpointAuthSigningAlgValuesSupported(), Algorithm.PS256,
|
||||
Algorithm.PS384, Algorithm.PS512, Algorithm.RS256, Algorithm.RS384, Algorithm.RS512, Algorithm.ES256,
|
||||
Algorithm.ES384, Algorithm.ES512, Algorithm.HS256, Algorithm.HS384, Algorithm.HS512);
|
||||
|
@ -160,9 +164,7 @@ public class OIDCWellKnownProviderTest extends AbstractKeycloakTest {
|
|||
Assert.assertTrue(oidcConfig.getClaimsParameterSupported());
|
||||
|
||||
// Scopes supported
|
||||
Assert.assertNames(oidcConfig.getScopesSupported(), OAuth2Constants.SCOPE_OPENID, OAuth2Constants.OFFLINE_ACCESS,
|
||||
OAuth2Constants.SCOPE_PROFILE, OAuth2Constants.SCOPE_EMAIL, OAuth2Constants.SCOPE_PHONE, OAuth2Constants.SCOPE_ADDRESS,
|
||||
OIDCLoginProtocolFactory.ROLES_SCOPE, OIDCLoginProtocolFactory.WEB_ORIGINS_SCOPE, OIDCLoginProtocolFactory.MICROPROFILE_JWT_SCOPE);
|
||||
assertScopesSupportedMatchesWithRealm(oidcConfig);
|
||||
|
||||
// Request and Request_Uri
|
||||
Assert.assertTrue(oidcConfig.getRequestParameterSupported());
|
||||
|
@ -282,6 +284,42 @@ public class OIDCWellKnownProviderTest extends AbstractKeycloakTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@AuthServerContainerExclude(REMOTE)
|
||||
public void testDefaultProviderCustomizations() throws IOException {
|
||||
Client client = AdminClientUtil.createResteasyClient();
|
||||
try {
|
||||
OIDCConfigurationRepresentation oidcConfig = getOIDCDiscoveryRepresentation(client, OAuthClient.AUTH_SERVER_ROOT);
|
||||
|
||||
// Assert that CustomOIDCWellKnownProvider was used as a prioritized provider over default OIDCWellKnownProvider
|
||||
MTLSEndpointAliases mtlsEndpointAliases = oidcConfig.getMtlsEndpointAliases();
|
||||
Assert.assertEquals("https://placeholder-host-set-by-testsuite-provider/registration", mtlsEndpointAliases.getRegistrationEndpoint());
|
||||
Assert.assertEquals("bar", oidcConfig.getOtherClaims().get("foo"));
|
||||
|
||||
// Assert some configuration was overriden
|
||||
Assert.assertEquals("some-new-property-value", oidcConfig.getOtherClaims().get("some-new-property"));
|
||||
Assert.assertEquals("nested-value", ((Map) oidcConfig.getOtherClaims().get("some-new-property-compound")).get("nested1"));
|
||||
Assert.assertNames(oidcConfig.getIntrospectionEndpointAuthMethodsSupported(), "private_key_jwt", "client_secret_jwt", "tls_client_auth", "custom_nonexisting_authenticator");
|
||||
|
||||
// Exact names already tested in OIDC
|
||||
assertScopesSupportedMatchesWithRealm(oidcConfig);
|
||||
|
||||
// Temporarily disable client scopes
|
||||
getTestingClient().testing().setSystemPropertyOnServer(CustomOIDCWellKnownProviderFactory.INCLUDE_CLIENT_SCOPES, "false");
|
||||
oidcConfig = getOIDCDiscoveryRepresentation(client, OAuthClient.AUTH_SERVER_ROOT);
|
||||
Assert.assertNull(oidcConfig.getScopesSupported());
|
||||
} finally {
|
||||
getTestingClient().testing().setSystemPropertyOnServer(CustomOIDCWellKnownProviderFactory.INCLUDE_CLIENT_SCOPES, null);
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void assertScopesSupportedMatchesWithRealm(OIDCConfigurationRepresentation oidcConfig) {
|
||||
Assert.assertNames(oidcConfig.getScopesSupported(), OAuth2Constants.SCOPE_OPENID, OAuth2Constants.OFFLINE_ACCESS,
|
||||
OAuth2Constants.SCOPE_PROFILE, OAuth2Constants.SCOPE_EMAIL, OAuth2Constants.SCOPE_PHONE, OAuth2Constants.SCOPE_ADDRESS,
|
||||
OIDCLoginProtocolFactory.ROLES_SCOPE, OIDCLoginProtocolFactory.WEB_ORIGINS_SCOPE, OIDCLoginProtocolFactory.MICROPROFILE_JWT_SCOPE);
|
||||
}
|
||||
|
||||
private OIDCConfigurationRepresentation getOIDCDiscoveryRepresentation(Client client, String uriTemplate) {
|
||||
try {
|
||||
return JsonSerialization.readValue(getOIDCDiscoveryConfiguration(client, uriTemplate), OIDCConfigurationRepresentation.class);
|
||||
|
|
Loading…
Reference in a new issue