keycloak-memoizeit

Changes

themes/src/main/resources/theme/base/admin/resources/partials/client-scope-create-step-1.html 46(+0 -46)

Details

diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ClientScopesResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ClientScopesResource.java
index c51d7c2..2df8978 100755
--- a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ClientScopesResource.java
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/ClientScopesResource.java
@@ -17,7 +17,6 @@
 
 package org.keycloak.admin.client.resource;
 
-import org.jboss.resteasy.annotations.cache.NoCache;
 import org.keycloak.representations.idm.ClientScopeRepresentation;
 
 import javax.ws.rs.Consumes;
@@ -26,7 +25,6 @@ import javax.ws.rs.POST;
 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.MediaType;
 import javax.ws.rs.core.Response;
 import java.util.List;
@@ -47,18 +45,4 @@ public interface ClientScopesResource {
     @Produces(MediaType.APPLICATION_JSON)
     List<ClientScopeRepresentation> findAll();
 
-
-    /**
-     * Generate new client scope for specified service client. The "Frontend" clients, who will use this client scope, will be able to
-     * send their access token to authenticate against specified service client
-     *
-     * @param clientId Client ID of service client (typically bearer-only client)
-     * @return
-     */
-    @Path("generate-audience-client-scope")
-    @POST
-    @NoCache
-    Response generateAudienceClientScope(final @QueryParam("clientId") String clientId);
-
-
 }
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/installation/KeycloakOIDCClientInstallation.java b/services/src/main/java/org/keycloak/protocol/oidc/installation/KeycloakOIDCClientInstallation.java
index 325907d..2cbd5cc 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/installation/KeycloakOIDCClientInstallation.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/installation/KeycloakOIDCClientInstallation.java
@@ -103,17 +103,20 @@ public class KeycloakOIDCClientInstallation implements ClientInstallationProvide
     }
 
 
-    // Check if there is audience client scope created for particular client. If yes, admin wants verifying token audience
     static boolean showVerifyTokenAudience(ClientModel client) {
-        String clientId = client.getClientId();
-        ClientScopeModel clientScope = KeycloakModelUtils.getClientScopeByName(client.getRealm(), clientId);
-        if (clientScope == null) {
-            return false;
+        // We want to verify-token-audience if service client has any client roles
+        if (client.getRoles().size() > 0) {
+            return true;
         }
 
-        for (ProtocolMapperModel protocolMapper : clientScope.getProtocolMappers()) {
-            if (AudienceProtocolMapper.PROVIDER_ID.equals(protocolMapper.getProtocolMapper()) && (clientId.equals(protocolMapper.getConfig().get(AudienceProtocolMapper.INCLUDED_CLIENT_AUDIENCE)))) {
-                return true;
+        // Check if there is client scope with audience protocol mapper created for particular client. If yes, admin wants verifying token audience
+        String clientId = client.getClientId();
+
+        for (ClientScopeModel clientScope : client.getRealm().getClientScopes()) {
+            for (ProtocolMapperModel protocolMapper : clientScope.getProtocolMappers()) {
+                if (AudienceProtocolMapper.PROVIDER_ID.equals(protocolMapper.getProtocolMapper()) && (clientId.equals(protocolMapper.getConfig().get(AudienceProtocolMapper.INCLUDED_CLIENT_AUDIENCE)))) {
+                    return true;
+                }
             }
         }
 
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientScopesResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientScopesResource.java
index 1b948e8..81b0c74 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientScopesResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientScopesResource.java
@@ -22,17 +22,12 @@ import org.jboss.resteasy.spi.NotFoundException;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
 import org.keycloak.events.admin.OperationType;
 import org.keycloak.events.admin.ResourceType;
-import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientScopeModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.ModelDuplicateException;
-import org.keycloak.models.ProtocolMapperModel;
 import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
 import org.keycloak.models.utils.ModelToRepresentation;
 import org.keycloak.models.utils.RepresentationToModel;
-import org.keycloak.protocol.oidc.OIDCLoginProtocol;
-import org.keycloak.protocol.oidc.mappers.AudienceProtocolMapper;
 import org.keycloak.representations.idm.ClientScopeRepresentation;
 import org.keycloak.services.ErrorResponse;
 import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
@@ -43,7 +38,6 @@ import javax.ws.rs.POST;
 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;
@@ -125,57 +119,6 @@ public class ClientScopesResource {
     }
 
     /**
-     * Generate new client scope for specified service client. The "Frontend" clients, who will use this client scope, will be able to
-     * send their access token to authenticate against specified service client
-     *
-     * @param clientId Client ID of service client (typically bearer-only client)
-     * @return
-     */
-    @Path("generate-audience-client-scope")
-    @POST
-    @NoCache
-    public Response generateAudienceClientScope(final @QueryParam("clientId") String clientId) {
-        auth.clients().requireManageClientScopes();
-
-        logger.debugf("Generating audience scope for service client: " + clientId);
-
-        String clientScopeName = clientId;
-        try {
-            ClientModel serviceClient = realm.getClientByClientId(clientId);
-            if (serviceClient == null) {
-                logger.warnf("Referenced service client '%s' doesn't exists", clientId);
-                return ErrorResponse.exists("Referenced service client doesn't exists");
-            }
-
-            ClientScopeModel clientScopeModel = realm.addClientScope(clientScopeName);
-            clientScopeModel.setDescription("Client scope useful for frontend clients, which want to call service " + clientId);
-            clientScopeModel.setProtocol(serviceClient.getProtocol()==null ? OIDCLoginProtocol.LOGIN_PROTOCOL : serviceClient.getProtocol());
-            clientScopeModel.setDisplayOnConsentScreen(true);
-
-            String consentText = serviceClient.getName() != null ? serviceClient.getName() : serviceClient.getClientId();
-            consentText = consentText.substring(0, 1).toUpperCase() + consentText.substring(1);
-            clientScopeModel.setConsentScreenText(consentText);
-
-            clientScopeModel.setIncludeInTokenScope(true);
-
-            // Add audience protocol mapper
-            ProtocolMapperModel audienceMapper = AudienceProtocolMapper.createClaimMapper("Audience for " + clientId, clientId, null,true, false);
-            clientScopeModel.addProtocolMapper(audienceMapper);
-
-            // Add scope to client roles
-            for (RoleModel role : serviceClient.getRoles()) {
-                clientScopeModel.addScopeMapping(role);
-            }
-
-            adminEvent.operation(OperationType.CREATE).resourcePath(session.getContext().getUri()).success();
-
-            return Response.created(session.getContext().getUri().getAbsolutePathBuilder().path(clientScopeModel.getId()).build()).build();
-        } catch (ModelDuplicateException e) {
-            return ErrorResponse.exists("Client Scope " + clientScopeName + " already exists");
-        }
-    }
-
-    /**
      * Base path for managing a specific client scope.
      *
      * @param id id of client scope (not name)
diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProvider.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProvider.java
index 0c0ae39..fca6e02 100644
--- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProvider.java
+++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProvider.java
@@ -20,7 +20,6 @@ package org.keycloak.testsuite.rest;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.BadRequestException;
 import org.jboss.resteasy.spi.HttpRequest;
-import org.keycloak.common.util.MultivaluedHashMap;
 import org.keycloak.common.util.Time;
 import org.keycloak.component.ComponentModel;
 import org.keycloak.events.Event;
@@ -34,9 +33,11 @@ import org.keycloak.events.admin.OperationType;
 import org.keycloak.events.admin.ResourceType;
 import org.keycloak.models.AuthenticationFlowModel;
 import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientScopeModel;
 import org.keycloak.models.FederatedIdentityModel;
 import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.LDAPConstants;
+import org.keycloak.models.ModelDuplicateException;
+import org.keycloak.models.ProtocolMapperModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RealmProvider;
 import org.keycloak.models.UserCredentialModel;
@@ -45,6 +46,8 @@ import org.keycloak.models.UserProvider;
 import org.keycloak.models.UserSessionModel;
 import org.keycloak.models.sessions.infinispan.changes.sessions.LastSessionRefreshStoreFactory;
 import org.keycloak.models.utils.ModelToRepresentation;
+import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.protocol.oidc.mappers.AudienceProtocolMapper;
 import org.keycloak.provider.ProviderFactory;
 import org.keycloak.representations.idm.AdminEventRepresentation;
 import org.keycloak.representations.idm.AuthDetailsRepresentation;
@@ -52,12 +55,9 @@ import org.keycloak.representations.idm.AuthenticationFlowRepresentation;
 import org.keycloak.representations.idm.EventRepresentation;
 import org.keycloak.representations.idm.UserRepresentation;
 import org.keycloak.services.managers.AuthenticationManager;
-import org.keycloak.services.managers.RealmManager;
 import org.keycloak.services.resource.RealmResourceProvider;
 import org.keycloak.services.scheduled.ClearExpiredUserSessions;
 import org.keycloak.storage.UserStorageProvider;
-import org.keycloak.storage.UserStorageProviderModel;
-import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
 import org.keycloak.testsuite.components.TestProvider;
 import org.keycloak.testsuite.components.TestProviderFactory;
 import org.keycloak.testsuite.events.EventsListenerProvider;
@@ -99,7 +99,6 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.TimerTask;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -126,11 +125,7 @@ public class TestingResourceProvider implements RealmResourceProvider {
     @Path("/remove-user-session")
     @Produces(MediaType.APPLICATION_JSON)
     public Response removeUserSession(@QueryParam("realm") final String name, @QueryParam("session") final String sessionId) {
-        RealmManager realmManager = new RealmManager(session);
-        RealmModel realm = realmManager.getRealmByName(name);
-        if (realm == null) {
-            throw new NotFoundException("Realm not found");
-        }
+        RealmModel realm = getRealmByName(name);
 
         UserSessionModel sessionModel = session.sessions().getUserSession(realm, sessionId);
         if (sessionModel == null) {
@@ -145,11 +140,7 @@ public class TestingResourceProvider implements RealmResourceProvider {
     @Path("/remove-user-sessions")
     @Produces(MediaType.APPLICATION_JSON)
     public Response removeUserSessions(@QueryParam("realm") final String realmName) {
-        RealmManager realmManager = new RealmManager(session);
-        RealmModel realm = realmManager.getRealmByName(realmName);
-        if (realm == null) {
-            throw new NotFoundException("Realm not found");
-        }
+        RealmModel realm = getRealmByName(realmName);
 
         session.sessions().removeUserSessions(realm);
         return Response.ok().build();
@@ -159,12 +150,7 @@ public class TestingResourceProvider implements RealmResourceProvider {
     @Path("/get-last-session-refresh")
     @Produces(MediaType.APPLICATION_JSON)
     public Integer getLastSessionRefresh(@QueryParam("realm") final String name, @QueryParam("session") final String sessionId, @QueryParam("offline") boolean offline) {
-
-        RealmManager realmManager = new RealmManager(session);
-        RealmModel realm = realmManager.getRealmByName(name);
-        if (realm == null) {
-            throw new NotFoundException("Realm not found");
-        }
+        RealmModel realm = getRealmByName(name);
 
         UserSessionModel sessionModel = offline ? session.sessions().getOfflineUserSession(realm, sessionId) : session.sessions().getUserSession(realm, sessionId);
         if (sessionModel == null) {
@@ -178,11 +164,7 @@ public class TestingResourceProvider implements RealmResourceProvider {
     @Path("/remove-expired")
     @Produces(MediaType.APPLICATION_JSON)
     public Response removeExpired(@QueryParam("realm") final String name) {
-        RealmManager realmManager = new RealmManager(session);
-        RealmModel realm = realmManager.getRealmByName(name);
-        if (realm == null) {
-            throw new NotFoundException("Realm not found");
-        }
+        RealmModel realm = getRealmByName(name);
 
         session.sessions().removeExpired(realm);
         session.authenticationSessions().removeExpired(realm);
@@ -196,11 +178,7 @@ public class TestingResourceProvider implements RealmResourceProvider {
     @Produces(MediaType.APPLICATION_JSON)
     public Integer getClientSessionsCountInUserSession(@QueryParam("realm") final String name, @QueryParam("session") final String sessionId) {
 
-        RealmManager realmManager = new RealmManager(session);
-        RealmModel realm = realmManager.getRealmByName(name);
-        if (realm == null) {
-            throw new NotFoundException("Realm not found");
-        }
+        RealmModel realm = getRealmByName(name);
 
         UserSessionModel sessionModel = session.sessions().getUserSession(realm, sessionId);
         if (sessionModel == null) {
@@ -753,6 +731,42 @@ public class TestingResourceProvider implements RealmResourceProvider {
     }
 
 
+    /**
+     * Generate new client scope for specified service client. The "Frontend" clients, who will use this client scope, will be able to
+     * send their access token to authenticate against specified service client
+     *
+     * @param clientId Client ID of service client (typically bearer-only client)
+     * @return ID of the newly generated clientScope
+     */
+    @Path("generate-audience-client-scope")
+    @POST
+    @NoCache
+    public String generateAudienceClientScope(@QueryParam("realm") final String realmName, final @QueryParam("clientId") String clientId) {
+        try {
+            RealmModel realm = getRealmByName(realmName);
+            ClientModel serviceClient = realm.getClientByClientId(clientId);
+            if (serviceClient == null) {
+                throw new NotFoundException("Referenced service client doesn't exists");
+            }
+
+            ClientScopeModel clientScopeModel = realm.addClientScope(clientId);
+            clientScopeModel.setProtocol(serviceClient.getProtocol()==null ? OIDCLoginProtocol.LOGIN_PROTOCOL : serviceClient.getProtocol());
+            clientScopeModel.setDisplayOnConsentScreen(true);
+            clientScopeModel.setConsentScreenText(clientId);
+            clientScopeModel.setIncludeInTokenScope(true);
+
+            // Add audience protocol mapper
+            ProtocolMapperModel audienceMapper = AudienceProtocolMapper.createClaimMapper("Audience for " + clientId, clientId, null,true, false);
+            clientScopeModel.addProtocolMapper(audienceMapper);
+
+            return clientScopeModel.getId();
+        } catch (ModelDuplicateException e) {
+            throw new BadRequestException("Client Scope " + clientId + " already exists");
+        }
+    }
+
+
+
     @POST
     @Path("/run-on-server")
     @Consumes(MediaType.TEXT_PLAIN_UTF_8)
@@ -810,7 +824,11 @@ public class TestingResourceProvider implements RealmResourceProvider {
 
     private RealmModel getRealmByName(String realmName) {
         RealmProvider realmProvider = session.getProvider(RealmProvider.class);
-        return realmProvider.getRealmByName(realmName);
+        RealmModel realm = realmProvider.getRealmByName(realmName);
+        if (realm == null) {
+            throw new NotFoundException("Realm not found");
+        }
+        return realm;
     }
 
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestingResource.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestingResource.java
index cd2b888..4153a88 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestingResource.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestingResource.java
@@ -275,6 +275,11 @@ public interface TestingResource {
     @Produces(MediaType.APPLICATION_JSON)
     Response restorePeriodicTasks();
 
+    @Path("generate-audience-client-scope")
+    @POST
+    @NoCache
+    String generateAudienceClientScope(@QueryParam("realm") final String realmName, final @QueryParam("clientId") String clientId);
+
     @GET
     @Path("/uncaught-error")
     @Produces(MediaType.TEXT_HTML_UTF_8)
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/jaas/LoginModulesTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/jaas/LoginModulesTest.java
index 03000ed..62da9d0 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/jaas/LoginModulesTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/jaas/LoginModulesTest.java
@@ -33,7 +33,6 @@ import javax.security.auth.login.AppConfigurationEntry;
 import javax.security.auth.login.Configuration;
 import javax.security.auth.login.LoginContext;
 import javax.security.auth.login.LoginException;
-import javax.ws.rs.core.Response;
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -68,9 +67,8 @@ public class LoginModulesTest extends AbstractKeycloakTest {
         }
 
         // Generate audience client scope
-        Response resp = adminClient.realm("demo").clientScopes().generateAudienceClientScope("customer-db-audience-required");
-        String clientScopeId = ApiUtil.getCreatedId(resp);
-        resp.close();
+        String clientScopeId = testingClient.testing().generateAudienceClientScope("demo", "customer-db-audience-required");
+
         ClientResource client = ApiUtil.findClientByClientId(adminClient.realm("demo"), "customer-portal");
         client.addOptionalClientScope(clientScopeId);
     }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/DemoServletsAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/DemoServletsAdapterTest.java
index 8bcb963..2847b2c 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/DemoServletsAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/DemoServletsAdapterTest.java
@@ -831,9 +831,8 @@ public class DemoServletsAdapterTest extends AbstractServletsAdapterTest {
     @Test
     public void testVerifyTokenAudience() {
         // Generate audience client scope
-        Response resp = adminClient.realm("demo").clientScopes().generateAudienceClientScope("customer-db-audience-required");
-        String clientScopeId = ApiUtil.getCreatedId(resp);
-        resp.close();
+        String clientScopeId = testingClient.testing().generateAudienceClientScope("demo", "customer-db-audience-required");
+
         ClientResource client = ApiUtil.findClientByClientId(adminClient.realm("demo"), "customer-portal");
         client.addOptionalClientScope(clientScopeId);
 
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/InstallationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/InstallationTest.java
index 2743971..5885dd9 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/InstallationTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/InstallationTest.java
@@ -17,20 +17,15 @@
 
 package org.keycloak.testsuite.admin.client;
 
-import javax.ws.rs.core.Response;
-
 import org.junit.After;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
 import org.keycloak.admin.client.resource.ClientResource;
 import org.keycloak.events.admin.OperationType;
 import org.keycloak.events.admin.ResourceType;
-import org.keycloak.testsuite.ProfileAssume;
 import org.keycloak.testsuite.admin.ApiUtil;
 import org.keycloak.testsuite.arquillian.AuthServerTestEnricher;
 import org.keycloak.testsuite.util.AdminEventPaths;
-import org.keycloak.testsuite.util.WaitUtils;
 
 import static org.junit.Assert.assertThat;
 import static org.hamcrest.Matchers.*;
@@ -109,10 +104,7 @@ public class InstallationTest extends AbstractClientTest {
     @Test
     public void testOidcBearerOnlyJsonWithAudienceClientScope() {
         // Generate audience client scope
-        Response resp = testRealmResource().clientScopes().generateAudienceClientScope(OIDC_NAME_BEARER_ONLY_NAME);
-        String clientScopeId = ApiUtil.getCreatedId(resp);
-        resp.close();
-        assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, AdminEventPaths.clientScopeGenerateAudienceClientScopePath(), null, ResourceType.CLIENT_SCOPE);
+        String clientScopeId = testingClient.testing().generateAudienceClientScope("test", OIDC_NAME_BEARER_ONLY_NAME);
 
         String json = oidcBearerOnlyClient.getInstallationProvider("keycloak-oidc-keycloak-json");
         assertOidcInstallationConfig(json);
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/AudienceTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/AudienceTest.java
index 7527e05..c653a51 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/AudienceTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/AudienceTest.java
@@ -179,55 +179,6 @@ public class AudienceTest extends AbstractOIDCScopeTest {
     }
 
 
-    @Test
-    public void testAudienceClientScopeGeneration() throws Exception {
-        // Generate the "Audience" client scope for the "service-client" as an audience
-        Response resp = testRealm().clientScopes().generateAudienceClientScope("service-client");
-        String audienceScopeId = ApiUtil.getCreatedId(resp);
-        resp.close();
-
-        // Login and check audiences in the token. It's no audience for "service-client" yet and no clientRoles of "service-client" in the token
-        oauth.scope("openid service-client");
-        oauth.doLogin("john", "password");
-        EventRepresentation loginEvent = events.expectLogin()
-                .user(userId)
-                .assertEvent();
-        Tokens tokens = sendTokenRequest(loginEvent, userId,"openid profile email", "test-app");
-        assertAudiences(tokens.accessToken);
-        assertAudiences(tokens.idToken, "test-app");
-        Assert.assertFalse(tokens.accessToken.getResourceAccess().containsKey("service-client"));
-
-        // Logout
-        oauth.doLogout(tokens.refreshToken, "password");
-        events.expectLogout(tokens.idToken.getSessionState())
-                .client("test-app")
-                .user(userId)
-                .removeDetail(Details.REDIRECT_URI).assertEvent();
-
-
-        // Add clientScope to the test-app client
-        ClientResource testApp = ApiUtil.findClientByClientId(testRealm(), "test-app");
-        testApp.addOptionalClientScope(audienceScopeId);
-
-        // Login again and check audiences in the token. Now there is audience for "service-client" and clientRoles of "service-client" in the token
-        oauth.scope("openid service-client");
-        oauth.doLogin("john", "password");
-        loginEvent = events.expectLogin()
-                .user(userId)
-                .assertEvent();
-        tokens = sendTokenRequest(loginEvent, userId,"openid profile email service-client", "test-app");
-        assertAudiences(tokens.accessToken, "service-client");
-        assertAudiences(tokens.idToken, "test-app");
-        Assert.assertTrue(tokens.accessToken.getResourceAccess().containsKey("service-client"));
-        Assert.assertNames(tokens.accessToken.getResourceAccess().get("service-client").getRoles(), "role1");
-
-        // Revert
-        testApp.removeOptionalClientScope(audienceScopeId);
-        testRealm().clientScopes().get(audienceScopeId).remove();
-    }
-
-
-
     private void assertAudiences(JsonWebToken token, String... expectedAudience) {
         Collection<String> audiences = token.getAudience() == null ? Collections.emptyList() : Arrays.asList(token.getAudience());
         Collection<String> expectedAudiences = Arrays.asList(expectedAudience);
diff --git a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
index b50f37e..8a7382a 100644
--- a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
+++ b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
@@ -837,12 +837,6 @@ client-storage=Client Storage
 no-client-storage-providers-configured=No client storage providers configured
 client-stores.tooltip=Keycloak can retrieve clients and their details from external stores.
 
-add-client-scope-step-1=Add Client Scope - Step 1
-add-client-scope-step-2=Add Client Scope - Step 2
-client-scope-template=Client Scope Template
-client-scope-template.tooltip=Choose if you want to use some client scope template. Template allows you to easily create client scope with some pre-set options and protocol mappers. It is similar to the Archetype concept in Maven.
-audience-client=Audience
-audience-client.tooltip=Used audience (service client). Newly created client scope will contain audience protocol mapper and role scopes of all client roles of chosen service client. This is useful if you want to invoke the specified audience (service client) from your frontend clients.
 client-scope.name.tooltip=Name of the client scope. Must be unique in the realm. Name shouldn't contain space characters as it's used as value of scope parameter
 client-scope.description.tooltip=Description of the client scope
 client-scope.protocol.tooltip=Which SSO protocol configuration is being supplied by this client scope
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/app.js b/themes/src/main/resources/theme/base/admin/resources/js/app.js
index 984b261..02f1e4a 100755
--- a/themes/src/main/resources/theme/base/admin/resources/js/app.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/app.js
@@ -1458,19 +1458,7 @@ module.config([ '$routeProvider', function($routeProvider) {
             },
             controller : 'ClientDetailCtrl'
         })
-        .when('/create/client-scope/step-1/:realm', {
-            templateUrl : resourceUrl + '/partials/client-scope-create-step-1.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                clients : function(ClientListLoader) {
-                    return ClientListLoader();
-                }
-            },
-            controller : 'ClientScopeCreateStep1Ctrl'
-        })
-        .when('/create/client-scope/step-2/:realm', {
+        .when('/create/client-scope/:realm', {
             templateUrl : resourceUrl + '/partials/client-scope-detail.html',
             resolve : {
                 realm : function(RealmLoader) {
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js b/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
index 4feb6ae..cabe47a 100755
--- a/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
@@ -2626,85 +2626,6 @@ module.controller('ClientScopesRealmDefaultCtrl', function($scope, realm, Realm,
     };
 });
 
-module.controller('ClientScopeCreateStep1Ctrl', function($scope, realm, clients, $route, ClientScopeGenerateAudienceClientScope, Client, $location, $modal, Dialog, Notifications) {
-    console.log('ClientScopeCreateStep1Ctrl');
-
-    $scope.realm = realm;
-    $scope.clientScopeTemplate = "none";
-
-    $scope.serviceClients = [];
-    for (var i = 0; i < clients.length; i++) {
-        if (clients[i].bearerOnly) {
-            $scope.serviceClients.push(clients[i]);
-        }
-    }
-
-    $scope.clientScopeTemplates = [
-        { name: "No template", value:  "none"  },
-        { name: "Audience template", value: "audience" }
-    ];
-
-    $scope.audienceClientUiSelect = {
-        minimumInputLength: 1,
-        delay: 500,
-        allowClear: true,
-        query: function (query) {
-            var data = {results: []};
-            if ('' == query.term.trim()) {
-                query.callback(data);
-                return;
-            }
-            Client.query({realm: $route.current.params.realm, search: query.term.trim(), max: 20}, function(response) {
-                for (i = 0; i < response.length; i++) {
-                    if (response[i].clientId.indexOf(query.term) != -1) {
-                        data.results.push(response[i]);
-                    }
-                }
-                query.callback(data);
-            });
-        },
-        formatResult: function(object, container, query) {
-            object.text = object.clientId;
-            return object.clientId;
-        }
-    };
-
-    $scope.selectedAudienceClient = null;
-
-    $scope.selectAudienceClient = function(audienceClient) {
-
-        if (!audienceClient || !audienceClient.id) {
-            $scope.selectedAudienceClient = null;
-            $scope.audienceClientId = '';
-            return;
-        }
-
-        $scope.audienceClientId = audienceClient.clientId;
-    }
-
-    $scope.next = function() {
-        if ($scope.clientScopeTemplate !== 'audience') {
-            $location.url("/create/client-scope/step-2/" + realm.realm);
-        } else {
-            if (!$scope.audienceClientId) {
-                Notifications.error("You must select audience (service client)");
-            } else {
-                ClientScopeGenerateAudienceClientScope.save({ realm: realm.realm, clientId : $scope.audienceClientId }, function (data, headers) {
-                    $scope.changed = false;
-                    var l = headers().location;
-                    var id = l.substring(l.lastIndexOf("/") + 1);
-                    $location.url("/realms/" + realm.realm + "/client-scopes/" + id);
-                    Notifications.success("The client scope has been created.");
-                });
-            }
-        }
-    };
-
-    $scope.cancel = function() {
-        $location.url("/realms/" + realm.realm + "/client-scopes");
-    };
-});
-
 module.controller('ClientScopeDetailCtrl', function($scope, realm, clientScope, $route, serverInfo, ClientScope, $location, $modal, Dialog, Notifications) {
     $scope.protocols = serverInfo.listProviderIds('login-protocol');
 
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/services.js b/themes/src/main/resources/theme/base/admin/resources/js/services.js
index 1f3783c..e63a200 100755
--- a/themes/src/main/resources/theme/base/admin/resources/js/services.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/services.js
@@ -1210,13 +1210,6 @@ module.factory('Client', function($resource) {
     });
 });
 
-module.factory('ClientScopeGenerateAudienceClientScope', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/client-scopes/generate-audience-client-scope?clientId=:clientId', {
-        realm : '@realm',
-        clientId : "@clientId"
-    });
-});
-
 module.factory('ClientScope', function($resource) {
     return $resource(authUrl + '/admin/realms/:realm/client-scopes/:clientScope', {
         realm : '@realm',
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-scope-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-scope-detail.html
index 2299993..88c3216 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-scope-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-scope-detail.html
@@ -2,8 +2,7 @@
 
     <ol class="breadcrumb">
         <li><a href="#/realms/{{realm.realm}}/client-scopes">{{:: 'client-scopes' | translate}}</a></li>
-        <li data-ng-show="create"><a href="#/create/client-scope/step-1/{{realm.realm}}">{{:: 'add-client-scope-step-1' | translate}}</a></li>
-        <li data-ng-show="create">{{:: 'add-client-scope-step-2' | translate}}</li>
+        <li data-ng-show="create">{{:: 'add-client-scope' | translate}}</li>
         <li data-ng-hide="create">{{clientScope.name}}</li>
     </ol>
 
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-scope-list.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-scope-list.html
index 550aea2..1f945fc 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-scope-list.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-scope-list.html
@@ -29,7 +29,7 @@
                     </div>
 
                     <div class="pull-right" data-ng-show="access.manageClients">
-                        <a id="createClient" class="btn btn-default" href="#/create/client-scope/step-1/{{realm.realm}}">{{:: 'create' | translate}}</a>
+                        <a id="createClient" class="btn btn-default" href="#/create/client-scope/{{realm.realm}}">{{:: 'create' | translate}}</a>
                     </div>
                 </div>
             </th>
diff --git a/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-client-scope.html b/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-client-scope.html
index 8a6636b..72f59e9 100755
--- a/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-client-scope.html
+++ b/themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-client-scope.html
@@ -1,6 +1,6 @@
 <div data-ng-controller="ClientScopeTabCtrl">
 
-    <h1 data-ng-show="create">{{:: 'add-client-scope-step-2' | translate}}</h1>
+    <h1 data-ng-show="create">{{:: 'add-client-scope' | translate}}</h1>
     <h1 data-ng-hide="create">
         {{clientScope.name|capitalize}}
         <i id="removeClientScope" class="pficon pficon-delete clickable" data-ng-show="access.manageClients" data-ng-click="removeClientScope()"></i>