From 106e6e15a9ad2796113a0a785b1553bcd6aa44fb Mon Sep 17 00:00:00 2001 From: Douglas Palmer Date: Tue, 10 Dec 2019 12:03:44 -0800 Subject: [PATCH] [KEYCLOAK-11859] Added option to always display a client in the accounts console --- .../idm/ClientRepresentation.java | 9 ++++++ .../cache/infinispan/ClientAdapter.java | 10 +++++++ .../models/cache/infinispan/RealmAdapter.java | 5 ++++ .../cache/infinispan/RealmCacheSession.java | 4 +++ .../infinispan/entities/CachedClient.java | 6 ++++ .../keycloak/models/jpa/ClientAdapter.java | 10 +++++++ .../keycloak/models/jpa/JpaRealmProvider.java | 14 ++++++++++ .../org/keycloak/models/jpa/RealmAdapter.java | 5 ++++ .../models/jpa/entities/ClientEntity.java | 11 ++++++++ .../META-INF/jpa-changelog-9.0.0.xml | 28 +++++++++++++++++++ .../META-INF/jpa-changelog-master.xml | 1 + .../models/utils/ModelToRepresentation.java | 1 + .../models/utils/RepresentationToModel.java | 2 ++ .../AbstractReadOnlyClientStorageAdapter.java | 6 ++++ .../java/org/keycloak/models/ClientModel.java | 4 +++ .../org/keycloak/models/ClientProvider.java | 2 ++ .../java/org/keycloak/models/RealmModel.java | 2 ++ .../services/managers/RealmManager.java | 5 ++++ .../resources/account/AccountRestService.java | 5 ++++ .../storage/ClientStorageManager.java | 5 ++++ .../openshift/OpenshiftSAClientAdapter.java | 5 ++++ .../HardcodedClientStorageProvider.java | 5 ++++ .../account/AbstractRestServiceTest.java | 11 ++++++++ .../account/AccountRestServiceTest.java | 7 +++-- .../migration/AbstractMigrationTest.java | 7 +++++ .../testsuite/util/ClientBuilder.java | 5 ++++ 26 files changed, 172 insertions(+), 3 deletions(-) create mode 100644 model/jpa/src/main/resources/META-INF/jpa-changelog-9.0.0.xml diff --git a/core/src/main/java/org/keycloak/representations/idm/ClientRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ClientRepresentation.java index 6258c886a8..b3de65774c 100755 --- a/core/src/main/java/org/keycloak/representations/idm/ClientRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/idm/ClientRepresentation.java @@ -36,6 +36,7 @@ public class ClientRepresentation { protected String baseUrl; protected Boolean surrogateAuthRequired; protected Boolean enabled; + protected Boolean alwaysDisplayInConsole; protected String clientAuthenticatorType; protected String secret; protected String registrationAccessToken; @@ -119,6 +120,14 @@ public class ClientRepresentation { this.enabled = enabled; } + public Boolean isAlwaysDisplayInConsole() { + return alwaysDisplayInConsole; + } + + public void setAlwaysDisplayInConsole(Boolean alwaysDisplayInConsole) { + this.alwaysDisplayInConsole = alwaysDisplayInConsole; + } + public Boolean isSurrogateAuthRequired() { return surrogateAuthRequired; } diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/ClientAdapter.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/ClientAdapter.java index 0e81024362..8dac4ee3b8 100755 --- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/ClientAdapter.java +++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/ClientAdapter.java @@ -168,6 +168,16 @@ public class ClientAdapter implements ClientModel, CachedObject { updated.setEnabled(enabled); } + public boolean isAlwaysDisplayInConsole() { + if(isUpdated()) return updated.isAlwaysDisplayInConsole(); + return cached.isAlwaysDisplayInConsole(); + } + + public void setAlwaysDisplayInConsole(boolean alwaysDisplayInConsole) { + getDelegateForUpdate(); + updated.setAlwaysDisplayInConsole(alwaysDisplayInConsole); + } + @Override public String getClientAuthenticatorType() { if (isUpdated()) return updated.getClientAuthenticatorType(); diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java index 72dfc6d2c1..203086e7d7 100755 --- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java +++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java @@ -695,6 +695,11 @@ public class RealmAdapter implements CachedRealmModel { return cacheSession.getClients(this); } + @Override + public List getAlwaysDisplayInConsoleClients() { + return cacheSession.getAlwaysDisplayInConsoleClients(this); + } + @Override public ClientModel addClient(String name) { return cacheSession.addClient(this, name); diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmCacheSession.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmCacheSession.java index 2c14954c84..19653cfbd0 100755 --- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmCacheSession.java +++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmCacheSession.java @@ -546,6 +546,10 @@ public class RealmCacheSession implements CacheRealmProvider { return getClientDelegate().getClients(realm); } + @Override + public List getAlwaysDisplayInConsoleClients(RealmModel realm) { + return getClientDelegate().getAlwaysDisplayInConsoleClients(realm); + } @Override public boolean removeClient(String id, RealmModel realm) { diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedClient.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedClient.java index 5d0110db0b..ddd40a41f0 100755 --- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedClient.java +++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedClient.java @@ -42,6 +42,7 @@ public class CachedClient extends AbstractRevisioned implements InRealm { protected String realm; protected Set redirectUris = new HashSet<>(); protected boolean enabled; + protected boolean alwaysDisplayInConsole; protected String clientAuthenticatorType; protected String secret; protected String registrationToken; @@ -81,6 +82,7 @@ public class CachedClient extends AbstractRevisioned implements InRealm { description = model.getDescription(); this.realm = realm.getId(); enabled = model.isEnabled(); + alwaysDisplayInConsole = model.isAlwaysDisplayInConsole(); protocol = model.getProtocol(); attributes.putAll(model.getAttributes()); authFlowBindings.putAll(model.getAuthenticationFlowBindingOverrides()); @@ -145,6 +147,10 @@ public class CachedClient extends AbstractRevisioned implements InRealm { return enabled; } + public boolean isAlwaysDisplayInConsole() { + return alwaysDisplayInConsole; + } + public String getClientAuthenticatorType() { return clientAuthenticatorType; } diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java index 592c1e2d16..cda52e2613 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java @@ -106,6 +106,16 @@ public class ClientAdapter implements ClientModel, JpaModel { entity.setEnabled(enabled); } + @Override + public boolean isAlwaysDisplayInConsole() { + return entity.isAlwaysDisplayInConsole(); + } + + @Override + public void setAlwaysDisplayInConsole(boolean alwaysDisplayInConsole) { + entity.setAlwaysDisplayInConsole(alwaysDisplayInConsole); + } + @Override public boolean isPublicClient() { return entity.isPublicClient(); diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java index c74f711ccc..504df79f95 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java @@ -574,6 +574,20 @@ public class JpaRealmProvider implements RealmProvider { return this.getClients(realm, null, null); } + @Override + public List getAlwaysDisplayInConsoleClients(RealmModel realm) { + TypedQuery query = em.createNamedQuery("getAlwaysDisplayInConsoleClients", String.class); + query.setParameter("realm", realm.getId()); + List clients = query.getResultList(); + if (clients.isEmpty()) return Collections.EMPTY_LIST; + List list = new LinkedList<>(); + for (String id : clients) { + ClientModel client = session.realms().getClientById(id, realm); + if (client != null) list.add(client); + } + return Collections.unmodifiableList(list); + } + @Override public ClientModel getClientById(String id, RealmModel realm) { ClientEntity app = em.find(ClientEntity.class, id); diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java index 992632b619..a67ee6ef60 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java @@ -797,6 +797,11 @@ public class RealmAdapter implements RealmModel, JpaModel { return session.realms().getClients(this, firstResult, maxResults); } + @Override + public List getAlwaysDisplayInConsoleClients() { + return session.realms().getAlwaysDisplayInConsoleClients(this); + } + @Override public ClientModel addClient(String name) { return session.realms().addClient(this, name); diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java index 6b39068777..5e9823a3d2 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java @@ -54,6 +54,7 @@ import java.util.Set; @NamedQuery(name="getClientsByRealm", query="select client from ClientEntity client where client.realm = :realm"), @NamedQuery(name="getClientById", query="select client from ClientEntity client where client.id = :id and client.realm.id = :realm"), @NamedQuery(name="getClientIdsByRealm", query="select client.id from ClientEntity client where client.realm.id = :realm"), + @NamedQuery(name="getAlwaysDisplayInConsoleClients", query="select client.id from ClientEntity client where client.alwaysDisplayInConsole = true and client.realm.id = :realm"), @NamedQuery(name="findClientIdByClientId", query="select client.id from ClientEntity client where client.clientId = :clientId and client.realm.id = :realm"), @NamedQuery(name="searchClientsByClientId", query="select client.id from ClientEntity client where lower(client.clientId) like lower(concat('%',:clientId,'%')) and client.realm.id = :realm"), @NamedQuery(name="getRealmClientsCount", query="select count(client) from ClientEntity client where client.realm.id = :realm"), @@ -75,6 +76,8 @@ public class ClientEntity { private String clientId; @Column(name="ENABLED") private boolean enabled; + @Column(name = "ALWAYS_DISPLAY_IN_CONSOLE") + private boolean alwaysDisplayInConsole; @Column(name="SECRET") private String secret; @Column(name="REGISTRATION_TOKEN") @@ -205,6 +208,14 @@ public class ClientEntity { this.enabled = enabled; } + public boolean isAlwaysDisplayInConsole() { + return alwaysDisplayInConsole; + } + + public void setAlwaysDisplayInConsole(boolean alwaysDisplayInConsole) { + this.alwaysDisplayInConsole = alwaysDisplayInConsole; + } + public String getClientId() { return clientId; } diff --git a/model/jpa/src/main/resources/META-INF/jpa-changelog-9.0.0.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-9.0.0.xml new file mode 100644 index 0000000000..aa9cbe9af0 --- /dev/null +++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-9.0.0.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + diff --git a/model/jpa/src/main/resources/META-INF/jpa-changelog-master.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-master.xml index dd3ddf69d1..ae056eb232 100755 --- a/model/jpa/src/main/resources/META-INF/jpa-changelog-master.xml +++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-master.xml @@ -64,4 +64,5 @@ + diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java index 7ba1229702..6358ef207d 100755 --- a/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java +++ b/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java @@ -555,6 +555,7 @@ public class ModelToRepresentation { rep.setName(clientModel.getName()); rep.setDescription(clientModel.getDescription()); rep.setEnabled(clientModel.isEnabled()); + rep.setAlwaysDisplayInConsole(clientModel.isAlwaysDisplayInConsole()); rep.setAdminUrl(clientModel.getManagementUrl()); rep.setPublicClient(clientModel.isPublicClient()); rep.setFrontchannelLogout(clientModel.isFrontchannelLogout()); diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java index e3cf4c0f20..a5b0c27f76 100755 --- a/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java +++ b/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java @@ -1239,6 +1239,7 @@ public class RepresentationToModel { if (resourceRep.getName() != null) client.setName(resourceRep.getName()); if (resourceRep.getDescription() != null) client.setDescription(resourceRep.getDescription()); if (resourceRep.isEnabled() != null) client.setEnabled(resourceRep.isEnabled()); + if (resourceRep.isAlwaysDisplayInConsole() != null) client.setAlwaysDisplayInConsole(resourceRep.isAlwaysDisplayInConsole()); client.setManagementUrl(resourceRep.getAdminUrl()); if (resourceRep.isSurrogateAuthRequired() != null) client.setSurrogateAuthRequired(resourceRep.isSurrogateAuthRequired()); @@ -1426,6 +1427,7 @@ public class RepresentationToModel { if (rep.getName() != null) resource.setName(rep.getName()); if (rep.getDescription() != null) resource.setDescription(rep.getDescription()); if (rep.isEnabled() != null) resource.setEnabled(rep.isEnabled()); + if (rep.isAlwaysDisplayInConsole() != null) resource.setAlwaysDisplayInConsole(rep.isAlwaysDisplayInConsole()); if (rep.isBearerOnly() != null) resource.setBearerOnly(rep.isBearerOnly()); if (rep.isConsentRequired() != null) resource.setConsentRequired(rep.isConsentRequired()); if (rep.isStandardFlowEnabled() != null) resource.setStandardFlowEnabled(rep.isStandardFlowEnabled()); diff --git a/server-spi-private/src/main/java/org/keycloak/storage/client/AbstractReadOnlyClientStorageAdapter.java b/server-spi-private/src/main/java/org/keycloak/storage/client/AbstractReadOnlyClientStorageAdapter.java index eb9279fcec..3e50971da2 100644 --- a/server-spi-private/src/main/java/org/keycloak/storage/client/AbstractReadOnlyClientStorageAdapter.java +++ b/server-spi-private/src/main/java/org/keycloak/storage/client/AbstractReadOnlyClientStorageAdapter.java @@ -58,6 +58,12 @@ public abstract class AbstractReadOnlyClientStorageAdapter extends AbstractClien } + @Override + public void setAlwaysDisplayInConsole(boolean alwaysDisplayInConsole) { + throw new ReadOnlyException("client is read only for this update"); + + } + @Override public void setWebOrigins(Set webOrigins) { throw new ReadOnlyException("client is read only for this update"); diff --git a/server-spi/src/main/java/org/keycloak/models/ClientModel.java b/server-spi/src/main/java/org/keycloak/models/ClientModel.java index ea1d960e60..1a2337e0ad 100755 --- a/server-spi/src/main/java/org/keycloak/models/ClientModel.java +++ b/server-spi/src/main/java/org/keycloak/models/ClientModel.java @@ -62,6 +62,10 @@ public interface ClientModel extends ClientScopeModel, RoleContainerModel, Prot void setEnabled(boolean enabled); + boolean isAlwaysDisplayInConsole(); + + void setAlwaysDisplayInConsole(boolean alwaysDisplayInConsole); + boolean isSurrogateAuthRequired(); void setSurrogateAuthRequired(boolean surrogateAuthRequired); diff --git a/server-spi/src/main/java/org/keycloak/models/ClientProvider.java b/server-spi/src/main/java/org/keycloak/models/ClientProvider.java index d02522d8e7..2d5f7f82c3 100644 --- a/server-spi/src/main/java/org/keycloak/models/ClientProvider.java +++ b/server-spi/src/main/java/org/keycloak/models/ClientProvider.java @@ -43,5 +43,7 @@ public interface ClientProvider extends ClientLookupProvider, Provider { Set getClientRoles(RealmModel realm, ClientModel client); + List getAlwaysDisplayInConsoleClients(RealmModel realm); + boolean removeClient(String id, RealmModel realm); } diff --git a/server-spi/src/main/java/org/keycloak/models/RealmModel.java b/server-spi/src/main/java/org/keycloak/models/RealmModel.java index 9d10645c22..761fb471bb 100755 --- a/server-spi/src/main/java/org/keycloak/models/RealmModel.java +++ b/server-spi/src/main/java/org/keycloak/models/RealmModel.java @@ -255,6 +255,8 @@ public interface RealmModel extends RoleContainerModel { List getClients(Integer firstResult, Integer maxResults); Long getClientsCount(); + List getAlwaysDisplayInConsoleClients(); + ClientModel addClient(String name); ClientModel addClient(String id, String clientId); diff --git a/services/src/main/java/org/keycloak/services/managers/RealmManager.java b/services/src/main/java/org/keycloak/services/managers/RealmManager.java index bf019d5577..18114939cd 100755 --- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java +++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java @@ -165,6 +165,7 @@ public class RealmManager { adminConsole.setWebOrigins(Collections.singleton("+")); adminConsole.setEnabled(true); + adminConsole.setAlwaysDisplayInConsole(false); adminConsole.setPublicClient(true); adminConsole.setFullScopeAllowed(false); adminConsole.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL); @@ -188,6 +189,7 @@ public class RealmManager { adminCli = KeycloakModelUtils.createClient(realm, Constants.ADMIN_CLI_CLIENT_ID); adminCli.setName("${client_" + Constants.ADMIN_CLI_CLIENT_ID + "}"); adminCli.setEnabled(true); + adminCli.setAlwaysDisplayInConsole(false); adminCli.setPublicClient(true); adminCli.setFullScopeAllowed(false); adminCli.setStandardFlowEnabled(false); @@ -407,6 +409,7 @@ public class RealmManager { accountClient = KeycloakModelUtils.createClient(realm, Constants.ACCOUNT_MANAGEMENT_CLIENT_ID); accountClient.setName("${client_" + Constants.ACCOUNT_MANAGEMENT_CLIENT_ID + "}"); accountClient.setEnabled(true); + accountClient.setAlwaysDisplayInConsole(false); accountClient.setFullScopeAllowed(false); accountClient.setRootUrl(Constants.AUTH_BASE_URL_PROP); @@ -431,6 +434,7 @@ public class RealmManager { accountConsoleClient = KeycloakModelUtils.createClient(realm, Constants.ACCOUNT_CONSOLE_CLIENT_ID); accountConsoleClient.setName("${client_" + Constants.ACCOUNT_CONSOLE_CLIENT_ID + "}"); accountConsoleClient.setEnabled(true); + accountConsoleClient.setAlwaysDisplayInConsole(false); accountConsoleClient.setFullScopeAllowed(false); accountConsoleClient.setPublicClient(true); accountConsoleClient.setDirectAccessGrantsEnabled(false); @@ -462,6 +466,7 @@ public class RealmManager { if (client == null) { client = KeycloakModelUtils.createClient(realm, Constants.BROKER_SERVICE_CLIENT_ID); client.setEnabled(true); + client.setAlwaysDisplayInConsole(false); client.setName("${client_" + Constants.BROKER_SERVICE_CLIENT_ID + "}"); client.setFullScopeAllowed(false); client.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL); diff --git a/services/src/main/java/org/keycloak/services/resources/account/AccountRestService.java b/services/src/main/java/org/keycloak/services/resources/account/AccountRestService.java index 64e0303596..cef54b1c61 100755 --- a/services/src/main/java/org/keycloak/services/resources/account/AccountRestService.java +++ b/services/src/main/java/org/keycloak/services/resources/account/AccountRestService.java @@ -518,6 +518,11 @@ public class AccountRestService { consentModels.put(client.getClientId(), consent); } + List alwaysDisplayClients = realm.getAlwaysDisplayInConsoleClients(); + for(ClientModel client : alwaysDisplayClients) { + clients.add(client); + } + List apps = new LinkedList(); for (ClientModel client : clients) { if (client.isBearerOnly() || client.getBaseUrl() == null) { diff --git a/services/src/main/java/org/keycloak/storage/ClientStorageManager.java b/services/src/main/java/org/keycloak/storage/ClientStorageManager.java index 8da754f582..c5caf7f65d 100644 --- a/services/src/main/java/org/keycloak/storage/ClientStorageManager.java +++ b/services/src/main/java/org/keycloak/storage/ClientStorageManager.java @@ -220,6 +220,11 @@ public class ClientStorageManager implements ClientProvider { return session.clientLocalStorage().getClientRoles(realm, client); } + @Override + public List getAlwaysDisplayInConsoleClients(RealmModel realm) { + return session.clientLocalStorage().getAlwaysDisplayInConsoleClients(realm); + } + @Override public void close() { diff --git a/services/src/main/java/org/keycloak/storage/openshift/OpenshiftSAClientAdapter.java b/services/src/main/java/org/keycloak/storage/openshift/OpenshiftSAClientAdapter.java index d8748fbb87..085d55afd6 100644 --- a/services/src/main/java/org/keycloak/storage/openshift/OpenshiftSAClientAdapter.java +++ b/services/src/main/java/org/keycloak/storage/openshift/OpenshiftSAClientAdapter.java @@ -107,6 +107,11 @@ public final class OpenshiftSAClientAdapter extends AbstractReadOnlyClientStorag return getConfigOrDefault(() -> defaultConfig.isEnabled(), defaultConfig::setEnabled, true); } + @Override + public boolean isAlwaysDisplayInConsole() { + return getConfigOrDefault(() -> defaultConfig.isAlwaysDisplayInConsole(), defaultConfig::setAlwaysDisplayInConsole, false); + } + @Override public Set getWebOrigins() { return new HashSet<>(getConfigOrDefault(() -> defaultConfig.getWebOrigins(), defaultConfig::setWebOrigins, Collections.emptyList())); diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/HardcodedClientStorageProvider.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/HardcodedClientStorageProvider.java index d9bed02bea..bd5f007724 100644 --- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/HardcodedClientStorageProvider.java +++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/HardcodedClientStorageProvider.java @@ -111,6 +111,11 @@ public class HardcodedClientStorageProvider implements ClientStorageProvider, Cl return true; } + @Override + public boolean isAlwaysDisplayInConsole() { + return false; + } + @Override public Set getWebOrigins() { return Collections.EMPTY_SET; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AbstractRestServiceTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AbstractRestServiceTest.java index 3b4af6d596..2b5c2e9c76 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AbstractRestServiceTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AbstractRestServiceTest.java @@ -61,6 +61,8 @@ public abstract class AbstractRestServiceTest extends AbstractTestRealmKeycloakT protected String offlineClientAppUri = APP_ROOT + "/offline-client"; + protected String alwaysDisplayClientAppUri = APP_ROOT + "/always-display-client"; + @Before public void before() { httpClient = HttpClientBuilder.create().build(); @@ -98,6 +100,15 @@ public abstract class AbstractRestServiceTest extends AbstractTestRealmKeycloakT .directAccessGrants() .secret("secret1").build(); testRealm.getClients().add(offlineApp); + + org.keycloak.representations.idm.ClientRepresentation alwaysDisplayApp = ClientBuilder.create().clientId("always-display-client") + .id(KeycloakModelUtils.generateId()) + .name("Always Display Client") + .baseUrl(alwaysDisplayClientAppUri) + .directAccessGrants() + .alwaysDisplayInConsole(true) + .secret("secret1").build(); + testRealm.getClients().add(alwaysDisplayApp); } protected String getAccountUrl(String resource) { diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountRestServiceTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountRestServiceTest.java index 00f35ac221..0c4a45ff8c 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountRestServiceTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountRestServiceTest.java @@ -301,9 +301,10 @@ public class AccountRestServiceTest extends AbstractRestServiceTest { assertFalse(applications.isEmpty()); Map apps = applications.stream().collect(Collectors.toMap(x -> x.getClientId(), x -> x)); - Assert.assertThat(apps.keySet(), containsInAnyOrder("in-use-client")); + Assert.assertThat(apps.keySet(), containsInAnyOrder("in-use-client", "always-display-client")); assertClientRep(apps.get("in-use-client"), "In Use Client", null, false, true, false, inUseClientAppUri); + assertClientRep(apps.get("always-display-client"), "Always Display Client", null, false, false, false, alwaysDisplayClientAppUri); } @Test @@ -323,7 +324,7 @@ public class AccountRestServiceTest extends AbstractRestServiceTest { assertFalse(applications.isEmpty()); Map apps = applications.stream().collect(Collectors.toMap(x -> x.getClientId(), x -> x)); - Assert.assertThat(apps.keySet(), containsInAnyOrder("offline-client")); + Assert.assertThat(apps.keySet(), containsInAnyOrder("offline-client", "always-display-client")); assertClientRep(apps.get("offline-client"), "Offline Client", null, false, true, true, offlineClientAppUri); } @@ -361,7 +362,7 @@ public class AccountRestServiceTest extends AbstractRestServiceTest { .asResponse(); Map apps = applications.stream().collect(Collectors.toMap(x -> x.getClientId(), x -> x)); - Assert.assertThat(apps.keySet(), containsInAnyOrder(appId)); + Assert.assertThat(apps.keySet(), containsInAnyOrder(appId, "always-display-client")); ClientRepresentation app = apps.get(appId); assertClientRep(app, null, "A third party application", true, false, false, "http://localhost:8180/auth/realms/master/app/auth"); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/AbstractMigrationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/AbstractMigrationTest.java index a1eebf152f..303d4456bd 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/AbstractMigrationTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/AbstractMigrationTest.java @@ -276,6 +276,7 @@ public abstract class AbstractMigrationTest extends AbstractKeycloakTest { protected void testMigrationTo9_0_0() { testAccountConsoleClient(masterRealm); testAccountConsoleClient(migrationRealm); + testAlwaysDisplayInConsole(); } private void testAdminClientUrls(RealmResource realm) { @@ -793,4 +794,10 @@ public abstract class AbstractMigrationTest extends AbstractKeycloakTest { fail(e.getMessage()); } } + + protected void testAlwaysDisplayInConsole() { + for(ClientRepresentation clientRep : masterRealm.clients().findAll()) { + Assert.assertFalse(clientRep.isAlwaysDisplayInConsole()); + } + } } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ClientBuilder.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ClientBuilder.java index 3fef22aa12..ded68ff994 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ClientBuilder.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ClientBuilder.java @@ -186,6 +186,11 @@ public class ClientBuilder { return this; } + public ClientBuilder alwaysDisplayInConsole(Boolean alwaysDisplayInConsole) { + rep.setAlwaysDisplayInConsole(alwaysDisplayInConsole); + return this; + } + public ClientBuilder authorizationServicesEnabled(boolean enable) { rep.setAuthorizationServicesEnabled(enable); return this;