parent
1b36251a23
commit
b5f70d8a32
2 changed files with 85 additions and 31 deletions
|
@ -56,14 +56,21 @@ public class AdminClientUtil {
|
||||||
public static final int NUMBER_OF_CONNECTIONS = 10;
|
public static final int NUMBER_OF_CONNECTIONS = 10;
|
||||||
|
|
||||||
public static Keycloak createAdminClient(boolean ignoreUnknownProperties, String authServerContextRoot) throws Exception {
|
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);
|
ResteasyClient resteasyClient = createResteasyClient(ignoreUnknownProperties, null);
|
||||||
|
|
||||||
return KeycloakBuilder.builder()
|
return KeycloakBuilder.builder()
|
||||||
|
@ -73,10 +80,13 @@ public class AdminClientUtil {
|
||||||
.password(password)
|
.password(password)
|
||||||
.clientId(clientId)
|
.clientId(clientId)
|
||||||
.clientSecret(clientSecret)
|
.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;
|
boolean ignoreUnknownProperties = false;
|
||||||
ResteasyClient resteasyClient = createResteasyClient(ignoreUnknownProperties, null);
|
ResteasyClient resteasyClient = createResteasyClient(ignoreUnknownProperties, null);
|
||||||
|
|
||||||
|
@ -86,7 +96,8 @@ public class AdminClientUtil {
|
||||||
.grantType(OAuth2Constants.CLIENT_CREDENTIALS)
|
.grantType(OAuth2Constants.CLIENT_CREDENTIALS)
|
||||||
.clientId(clientId)
|
.clientId(clientId)
|
||||||
.clientSecret(clientSecret)
|
.clientSecret(clientSecret)
|
||||||
.resteasyClient(resteasyClient).build();
|
.resteasyClient(resteasyClient)
|
||||||
|
.scope(scope).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Keycloak createAdminClient() throws Exception {
|
public static Keycloak createAdminClient() throws Exception {
|
||||||
|
|
|
@ -19,25 +19,28 @@
|
||||||
package org.keycloak.testsuite.admin;
|
package org.keycloak.testsuite.admin;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.ws.rs.NotAuthorizedException;
|
import javax.ws.rs.NotAuthorizedException;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.rules.ExpectedException;
|
import org.junit.rules.ExpectedException;
|
||||||
import org.keycloak.admin.client.Keycloak;
|
import org.keycloak.admin.client.Keycloak;
|
||||||
import org.keycloak.admin.client.resource.ClientResource;
|
import org.keycloak.admin.client.resource.ClientResource;
|
||||||
|
import org.keycloak.admin.client.resource.RealmResource;
|
||||||
import org.keycloak.common.constants.ServiceAccountConstants;
|
import org.keycloak.common.constants.ServiceAccountConstants;
|
||||||
import org.keycloak.models.AdminRoles;
|
import org.keycloak.models.AdminRoles;
|
||||||
import org.keycloak.models.Constants;
|
import org.keycloak.models.Constants;
|
||||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
|
import org.keycloak.representations.AccessTokenResponse;
|
||||||
import org.keycloak.representations.idm.ClientRepresentation;
|
import org.keycloak.representations.idm.ClientRepresentation;
|
||||||
|
import org.keycloak.representations.idm.ClientScopeRepresentation;
|
||||||
import org.keycloak.representations.idm.RealmRepresentation;
|
import org.keycloak.representations.idm.RealmRepresentation;
|
||||||
import org.keycloak.testsuite.AbstractKeycloakTest;
|
import org.keycloak.testsuite.AbstractKeycloakTest;
|
||||||
import org.keycloak.testsuite.AssertEvents;
|
import org.keycloak.testsuite.AssertEvents;
|
||||||
import org.keycloak.testsuite.util.AdminClientUtil;
|
import org.keycloak.testsuite.util.AdminClientUtil;
|
||||||
import org.keycloak.testsuite.util.ClientBuilder;
|
import org.keycloak.testsuite.util.ClientBuilder;
|
||||||
|
import org.keycloak.testsuite.util.ClientScopeBuilder;
|
||||||
import org.keycloak.testsuite.util.RealmBuilder;
|
import org.keycloak.testsuite.util.RealmBuilder;
|
||||||
import org.keycloak.testsuite.util.UserBuilder;
|
import org.keycloak.testsuite.util.UserBuilder;
|
||||||
|
|
||||||
|
@ -48,9 +51,15 @@ import org.keycloak.testsuite.util.UserBuilder;
|
||||||
*/
|
*/
|
||||||
public class AdminClientTest extends AbstractKeycloakTest {
|
public class AdminClientTest extends AbstractKeycloakTest {
|
||||||
|
|
||||||
|
private static String realmName;
|
||||||
|
|
||||||
private static String userId;
|
private static String userId;
|
||||||
private static String userName;
|
private static String userName;
|
||||||
|
|
||||||
|
private static String clientUUID;
|
||||||
|
private static String clientId;
|
||||||
|
private static String clientSecret;
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
public AssertEvents events = new AssertEvents(this);
|
public AssertEvents events = new AssertEvents(this);
|
||||||
|
|
||||||
|
@ -65,17 +74,19 @@ public class AdminClientTest extends AbstractKeycloakTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addTestRealms(List<RealmRepresentation> testRealms) {
|
public void addTestRealms(List<RealmRepresentation> testRealms) {
|
||||||
|
realmName = "test";
|
||||||
RealmBuilder realm = RealmBuilder.create().name("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=")
|
.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")
|
.publicKey("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB")
|
||||||
.testEventListener();
|
.testEventListener();
|
||||||
|
|
||||||
|
clientUUID = KeycloakModelUtils.generateId();
|
||||||
|
clientId = "service-account-cl";
|
||||||
|
clientSecret = "secret1";
|
||||||
ClientRepresentation enabledAppWithSkipRefreshToken = ClientBuilder.create()
|
ClientRepresentation enabledAppWithSkipRefreshToken = ClientBuilder.create()
|
||||||
.id(KeycloakModelUtils.generateId())
|
.id(clientUUID)
|
||||||
.clientId("service-account-cl")
|
.clientId(clientId)
|
||||||
.secret("secret1")
|
.secret(clientSecret)
|
||||||
.serviceAccountsEnabled(true)
|
.serviceAccountsEnabled(true)
|
||||||
.build();
|
.build();
|
||||||
realm.client(enabledAppWithSkipRefreshToken);
|
realm.client(enabledAppWithSkipRefreshToken);
|
||||||
|
@ -101,54 +112,54 @@ public class AdminClientTest extends AbstractKeycloakTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void clientCredentialsAuthSuccess() throws Exception {
|
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
|
// Check possible to load the realm
|
||||||
RealmRepresentation realm = adminClient.realm("test").toRepresentation();
|
RealmRepresentation realm = adminClient.realm(realmName).toRepresentation();
|
||||||
Assert.assertEquals("test", realm.getRealm());
|
Assert.assertEquals(realmName, realm.getRealm());
|
||||||
|
|
||||||
setTimeOffset(1000);
|
setTimeOffset(1000);
|
||||||
|
|
||||||
// Check still possible to load the realm after original token expired (admin client should automatically re-authenticate)
|
// Check still possible to load the realm after original token expired (admin client should automatically re-authenticate)
|
||||||
realm = adminClient.realm("test").toRepresentation();
|
realm = adminClient.realm(realmName).toRepresentation();
|
||||||
Assert.assertEquals("test", realm.getRealm());
|
Assert.assertEquals(realmName, realm.getRealm());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void clientCredentialsClientDisabled() throws Exception {
|
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
|
// Check possible to load the realm
|
||||||
RealmRepresentation realm = adminClient.realm("test").toRepresentation();
|
RealmRepresentation realm = adminClient.realm(realmName).toRepresentation();
|
||||||
Assert.assertEquals("test", realm.getRealm());
|
Assert.assertEquals(realmName, realm.getRealm());
|
||||||
|
|
||||||
// Disable client and check it should not be possible to load the realms anymore
|
// 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
|
// Check not possible to invoke anymore
|
||||||
try {
|
try {
|
||||||
realm = adminClient.realm("test").toRepresentation();
|
realm = adminClient.realm(realmName).toRepresentation();
|
||||||
Assert.fail("Not expected to successfully get realm");
|
Assert.fail("Not expected to successfully get realm");
|
||||||
} catch (NotAuthorizedException nae) {
|
} catch (NotAuthorizedException nae) {
|
||||||
// Expected
|
// Expected
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
setClientEnabled("service-account-cl", true);
|
setClientEnabled(clientId, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void adminAuthClientDisabled() throws Exception {
|
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
|
// Check possible to load the realm
|
||||||
RealmRepresentation realm = adminClient.realm("test").toRepresentation();
|
RealmRepresentation realm = adminClient.realm(realmName).toRepresentation();
|
||||||
Assert.assertEquals("test", realm.getRealm());
|
Assert.assertEquals(realmName, realm.getRealm());
|
||||||
|
|
||||||
// Disable client and check it should not be possible to load the realms anymore
|
// Disable client and check it should not be possible to load the realms anymore
|
||||||
setClientEnabled(Constants.ADMIN_CLI_CLIENT_ID, false);
|
setClientEnabled(Constants.ADMIN_CLI_CLIENT_ID, false);
|
||||||
|
|
||||||
// Check not possible to invoke anymore
|
// Check not possible to invoke anymore
|
||||||
try {
|
try {
|
||||||
realm = adminClient.realm("test").toRepresentation();
|
realm = adminClient.realm(realmName).toRepresentation();
|
||||||
Assert.fail("Not expected to successfully get realm");
|
Assert.fail("Not expected to successfully get realm");
|
||||||
} catch (NotAuthorizedException nae) {
|
} catch (NotAuthorizedException nae) {
|
||||||
// Expected
|
// 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) {
|
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();
|
ClientRepresentation clientRep = client.toRepresentation();
|
||||||
clientRep.setEnabled(enabled);
|
clientRep.setEnabled(enabled);
|
||||||
client.update(clientRep);
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue