diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/AdminClientUtil.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/AdminClientUtil.java index 3fde9aa553..54385efa1a 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/AdminClientUtil.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/AdminClientUtil.java @@ -56,14 +56,21 @@ public class AdminClientUtil { public static final int NUMBER_OF_CONNECTIONS = 10; public static Keycloak createAdminClient(boolean ignoreUnknownProperties, String authServerContextRoot) throws Exception { - return createAdminClient(ignoreUnknownProperties, authServerContextRoot, MASTER, ADMIN, ADMIN, Constants.ADMIN_CLI_CLIENT_ID, null); + return createAdminClient(ignoreUnknownProperties, authServerContextRoot, MASTER, ADMIN, ADMIN, + Constants.ADMIN_CLI_CLIENT_ID, null, null); } - public static Keycloak createAdminClient(boolean ignoreUnknownProperties, String realmName, String username, String password, String clientId, String clientSecret) throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, KeyManagementException { - return createAdminClient(ignoreUnknownProperties, getAuthServerContextRoot(), realmName, username, password, clientId, clientSecret); + + public static Keycloak createAdminClient(boolean ignoreUnknownProperties, String realmName, String username, + String password, String clientId, String clientSecret) throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, KeyManagementException { + return createAdminClient(ignoreUnknownProperties, getAuthServerContextRoot(), realmName, username, password, + clientId, clientSecret, null); } - public static Keycloak createAdminClient(boolean ignoreUnknownProperties, String authServerContextRoot, String realmName, String username, String password, String clientId, String clientSecret) throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, KeyManagementException { + public static Keycloak createAdminClient(boolean ignoreUnknownProperties, String authServerContextRoot, String realmName, + String username, String password, String clientId, String clientSecret, String scope) + throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, KeyManagementException { + ResteasyClient resteasyClient = createResteasyClient(ignoreUnknownProperties, null); return KeycloakBuilder.builder() @@ -73,10 +80,13 @@ public class AdminClientUtil { .password(password) .clientId(clientId) .clientSecret(clientSecret) - .resteasyClient(resteasyClient).build(); + .resteasyClient(resteasyClient) + .scope(scope).build(); } - public static Keycloak createAdminClientWithClientCredentials(String realmName, String clientId, String clientSecret) throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, KeyManagementException { + public static Keycloak createAdminClientWithClientCredentials(String realmName, String clientId, String clientSecret, String scope) + throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, KeyManagementException { + boolean ignoreUnknownProperties = false; ResteasyClient resteasyClient = createResteasyClient(ignoreUnknownProperties, null); @@ -86,7 +96,8 @@ public class AdminClientUtil { .grantType(OAuth2Constants.CLIENT_CREDENTIALS) .clientId(clientId) .clientSecret(clientSecret) - .resteasyClient(resteasyClient).build(); + .resteasyClient(resteasyClient) + .scope(scope).build(); } public static Keycloak createAdminClient() throws Exception { diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/AdminClientTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/AdminClientTest.java index 6c3ba92bb1..99f063c55c 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/AdminClientTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/AdminClientTest.java @@ -19,25 +19,28 @@ package org.keycloak.testsuite.admin; import java.util.List; - import javax.ws.rs.NotAuthorizedException; - +import javax.ws.rs.core.Response; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.keycloak.admin.client.Keycloak; import org.keycloak.admin.client.resource.ClientResource; +import org.keycloak.admin.client.resource.RealmResource; import org.keycloak.common.constants.ServiceAccountConstants; import org.keycloak.models.AdminRoles; import org.keycloak.models.Constants; import org.keycloak.models.utils.KeycloakModelUtils; +import org.keycloak.representations.AccessTokenResponse; import org.keycloak.representations.idm.ClientRepresentation; +import org.keycloak.representations.idm.ClientScopeRepresentation; import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.testsuite.AbstractKeycloakTest; import org.keycloak.testsuite.AssertEvents; import org.keycloak.testsuite.util.AdminClientUtil; import org.keycloak.testsuite.util.ClientBuilder; +import org.keycloak.testsuite.util.ClientScopeBuilder; import org.keycloak.testsuite.util.RealmBuilder; import org.keycloak.testsuite.util.UserBuilder; @@ -48,9 +51,15 @@ import org.keycloak.testsuite.util.UserBuilder; */ public class AdminClientTest extends AbstractKeycloakTest { + private static String realmName; + private static String userId; private static String userName; + private static String clientUUID; + private static String clientId; + private static String clientSecret; + @Rule public AssertEvents events = new AssertEvents(this); @@ -65,17 +74,19 @@ public class AdminClientTest extends AbstractKeycloakTest { @Override public void addTestRealms(List testRealms) { - - RealmBuilder realm = RealmBuilder.create().name("test") + realmName = "test"; + RealmBuilder realm = RealmBuilder.create().name(realmName) .privateKey("MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=") .publicKey("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB") .testEventListener(); - + clientUUID = KeycloakModelUtils.generateId(); + clientId = "service-account-cl"; + clientSecret = "secret1"; ClientRepresentation enabledAppWithSkipRefreshToken = ClientBuilder.create() - .id(KeycloakModelUtils.generateId()) - .clientId("service-account-cl") - .secret("secret1") + .id(clientUUID) + .clientId(clientId) + .secret(clientSecret) .serviceAccountsEnabled(true) .build(); realm.client(enabledAppWithSkipRefreshToken); @@ -101,54 +112,54 @@ public class AdminClientTest extends AbstractKeycloakTest { @Test public void clientCredentialsAuthSuccess() throws Exception { - try (Keycloak adminClient = AdminClientUtil.createAdminClientWithClientCredentials("test", "service-account-cl", "secret1")) { + try (Keycloak adminClient = AdminClientUtil.createAdminClientWithClientCredentials(realmName, clientId, clientSecret, null)) { // Check possible to load the realm - RealmRepresentation realm = adminClient.realm("test").toRepresentation(); - Assert.assertEquals("test", realm.getRealm()); + RealmRepresentation realm = adminClient.realm(realmName).toRepresentation(); + Assert.assertEquals(realmName, realm.getRealm()); setTimeOffset(1000); // Check still possible to load the realm after original token expired (admin client should automatically re-authenticate) - realm = adminClient.realm("test").toRepresentation(); - Assert.assertEquals("test", realm.getRealm()); + realm = adminClient.realm(realmName).toRepresentation(); + Assert.assertEquals(realmName, realm.getRealm()); } } @Test public void clientCredentialsClientDisabled() throws Exception { - try (Keycloak adminClient = AdminClientUtil.createAdminClientWithClientCredentials("test", "service-account-cl", "secret1")) { + try (Keycloak adminClient = AdminClientUtil.createAdminClientWithClientCredentials(realmName, clientId, clientSecret, null)) { // Check possible to load the realm - RealmRepresentation realm = adminClient.realm("test").toRepresentation(); - Assert.assertEquals("test", realm.getRealm()); + RealmRepresentation realm = adminClient.realm(realmName).toRepresentation(); + Assert.assertEquals(realmName, realm.getRealm()); // Disable client and check it should not be possible to load the realms anymore - setClientEnabled("service-account-cl", false); + setClientEnabled(clientId, false); // Check not possible to invoke anymore try { - realm = adminClient.realm("test").toRepresentation(); + realm = adminClient.realm(realmName).toRepresentation(); Assert.fail("Not expected to successfully get realm"); } catch (NotAuthorizedException nae) { // Expected } } finally { - setClientEnabled("service-account-cl", true); + setClientEnabled(clientId, true); } } @Test public void adminAuthClientDisabled() throws Exception { - try (Keycloak adminClient = AdminClientUtil.createAdminClient(false, "test", "test-user@localhost", "password", Constants.ADMIN_CLI_CLIENT_ID, null)) { + try (Keycloak adminClient = AdminClientUtil.createAdminClient(false, realmName, "test-user@localhost", "password", Constants.ADMIN_CLI_CLIENT_ID, null)) { // Check possible to load the realm - RealmRepresentation realm = adminClient.realm("test").toRepresentation(); - Assert.assertEquals("test", realm.getRealm()); + RealmRepresentation realm = adminClient.realm(realmName).toRepresentation(); + Assert.assertEquals(realmName, realm.getRealm()); // Disable client and check it should not be possible to load the realms anymore setClientEnabled(Constants.ADMIN_CLI_CLIENT_ID, false); // Check not possible to invoke anymore try { - realm = adminClient.realm("test").toRepresentation(); + realm = adminClient.realm(realmName).toRepresentation(); Assert.fail("Not expected to successfully get realm"); } catch (NotAuthorizedException nae) { // Expected @@ -158,10 +169,42 @@ public class AdminClientTest extends AbstractKeycloakTest { } } + @Test + public void scopedClientCredentialsAuthSuccess() throws Exception { + final RealmResource testRealm = adminClient.realm(realmName); + + // we need to create custom scope after import, otherwise the default scopes are missing. + final String scopeName = "myScope"; + final String scopeId = KeycloakModelUtils.generateId(); + createScope(testRealm, scopeName, scopeId); + testRealm.clients().get(clientUUID).addOptionalClientScope(scopeId); + + // with scope + try (Keycloak adminClient = AdminClientUtil.createAdminClientWithClientCredentials(realmName, + clientId, clientSecret, scopeName)) { + final AccessTokenResponse accessToken = adminClient.tokenManager().getAccessToken(); + Assert.assertTrue(accessToken.getScope().contains(scopeName)); + } + // without scope + try (Keycloak adminClient = AdminClientUtil.createAdminClientWithClientCredentials(realmName, + clientId, clientSecret, null)) { + final AccessTokenResponse accessToken = adminClient.tokenManager().getAccessToken(); + Assert.assertFalse(accessToken.getScope().contains(scopeName)); + } + } + private void setClientEnabled(String clientId, boolean enabled) { - ClientResource client = ApiUtil.findClientByClientId(adminClient.realms().realm("test"), clientId); + ClientResource client = ApiUtil.findClientByClientId(adminClient.realms().realm(realmName), clientId); ClientRepresentation clientRep = client.toRepresentation(); clientRep.setEnabled(enabled); client.update(clientRep); } + + private void createScope(RealmResource testRealm, String scopeName, String scopeId) { + final ClientScopeRepresentation testScope = + ClientScopeBuilder.create().name(scopeName).protocol("openid-connect").build(); + testScope.setId(scopeId); + final Response scope = testRealm.clientScopes().create(testScope); + Assert.assertEquals(201, scope.getStatus()); + } }