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 c51d7c2163..2df8978d43 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 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 325907d75e..2cbd5cce96 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 1b948e8af3..81b0c74326 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; @@ -124,57 +118,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. * 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 0c0ae39465..fca6e02c17 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 Stian Thorgersen @@ -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 cd2b888d2d..4153a88f20 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 03000ed364..62da9d0a9e 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 8bcb963a29..2847b2ce48 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 2743971f56..5885dd9f11 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 7527e05ef0..c653a5159b 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 audiences = token.getAudience() == null ? Collections.emptyList() : Arrays.asList(token.getAudience()); Collection 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 b50f37e219..8a7382aeca 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 984b2611db..02f1e4a455 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 4feb6aec25..cabe47ab09 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 1f3783c6f6..e63a2009df 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-create-step-1.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-scope-create-step-1.html deleted file mode 100644 index 09d8a6678f..0000000000 --- a/themes/src/main/resources/theme/base/admin/resources/partials/client-scope-create-step-1.html +++ /dev/null @@ -1,46 +0,0 @@ -
- - - -

{{:: 'add-client-scope-step-1' | translate}}

- -
-
-
- -
-
- -
-
- {{:: 'client-scope-template.tooltip' | translate}} -
- -
- - -
- - -
- - {{:: 'audience-client.tooltip' | translate}} -
-
- -
-
- - -
-
-
-
- - \ No newline at end of file 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 2299993793..88c3216d82 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 @@ 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 550aea2f77..1f945fcc2b 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 @@ 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 8a6636b623..72f59e94e5 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 @@
-

{{:: 'add-client-scope-step-2' | translate}}

+

{{:: 'add-client-scope' | translate}}

{{clientScope.name|capitalize}}