KEYCLOAK-18311 fix creation of roles during client registration

This commit is contained in:
vramik 2021-07-09 12:46:01 +02:00 committed by Hynek Mlnařík
parent 1baab67f3b
commit 00017b44a3
3 changed files with 56 additions and 5 deletions

View file

@ -20,6 +20,7 @@ package org.keycloak.models;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import org.keycloak.provider.ProviderEvent; import org.keycloak.provider.ProviderEvent;
@ -98,14 +99,21 @@ public interface RoleContainerModel {
/** /**
* @deprecated Default roles are now managed by {@link org.keycloak.models.RealmModel#getDefaultRole()}. This method will be removed. * @deprecated Default roles are now managed by {@link org.keycloak.models.RealmModel#getDefaultRole()}. This method will be removed.
* @return List of default roles names or empty list if there are none. Never returns {@code null}.
*/ */
@Deprecated @Deprecated
default List<String> getDefaultRoles() { default List<String> getDefaultRoles() {
return getDefaultRolesStream().collect(Collectors.toList()); Stream<String> defaultRolesStream = getDefaultRolesStream();
if (defaultRolesStream != null) {
return defaultRolesStream.collect(Collectors.toList());
} else {
return Collections.emptyList();
}
} }
/** /**
* @deprecated Default roles are now managed by {@link org.keycloak.models.RealmModel#getDefaultRole()}. This method will be removed. * @deprecated Default roles are now managed by {@link org.keycloak.models.RealmModel#getDefaultRole()}. This method will be removed.
* @return Stream of default roles names or empty stream if there are none. Never returns {@code null}.
*/ */
@Deprecated @Deprecated
Stream<String> getDefaultRolesStream(); Stream<String> getDefaultRolesStream();

View file

@ -17,6 +17,7 @@
package org.keycloak.services.clientregistration; package org.keycloak.services.clientregistration;
import java.util.stream.Stream;
import org.keycloak.events.EventBuilder; import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType; import org.keycloak.events.EventType;
import org.keycloak.models.ClientInitialAccessModel; import org.keycloak.models.ClientInitialAccessModel;
@ -65,6 +66,12 @@ public abstract class AbstractClientRegistrationProvider implements ClientRegist
RealmModel realm = session.getContext().getRealm(); RealmModel realm = session.getContext().getRealm();
ClientModel clientModel = ClientManager.createClient(session, realm, client); ClientModel clientModel = ClientManager.createClient(session, realm, client);
if (client.getDefaultRoles() != null) {
for (String name : client.getDefaultRoles()) {
clientModel.addDefaultRole(name);
}
}
if (clientModel.isServiceAccountsEnabled()) { if (clientModel.isServiceAccountsEnabled()) {
new ClientManager(new RealmManager(session)).enableServiceAccount(clientModel); new ClientManager(new RealmManager(session)).enableServiceAccount(clientModel);
} }
@ -90,6 +97,11 @@ public abstract class AbstractClientRegistrationProvider implements ClientRegist
client.setDirectAccessGrantsEnabled(false); client.setDirectAccessGrantsEnabled(false);
Stream<String> defaultRolesNames = clientModel.getDefaultRolesStream();
if (defaultRolesNames != null) {
client.setDefaultRoles(defaultRolesNames.toArray(String[]::new));
}
event.client(client.getClientId()).success(); event.client(client.getClientId()).success();
return client; return client;
} catch (ModelDuplicateException e) { } catch (ModelDuplicateException e) {
@ -114,6 +126,11 @@ public abstract class AbstractClientRegistrationProvider implements ClientRegist
rep.setRegistrationAccessToken(registrationAccessToken); rep.setRegistrationAccessToken(registrationAccessToken);
} }
Stream<String> defaultRolesNames = client.getDefaultRolesStream();
if (defaultRolesNames != null) {
rep.setDefaultRoles(defaultRolesNames.toArray(String[]::new));
}
event.client(client.getClientId()).success(); event.client(client.getClientId()).success();
return rep; return rep;
} }
@ -133,8 +150,17 @@ public abstract class AbstractClientRegistrationProvider implements ClientRegist
RepresentationToModel.updateClient(rep, client); RepresentationToModel.updateClient(rep, client);
RepresentationToModel.updateClientProtocolMappers(rep, client); RepresentationToModel.updateClientProtocolMappers(rep, client);
if (rep.getDefaultRoles() != null) {
client.updateDefaultRoles(rep.getDefaultRoles());
}
rep = ModelToRepresentation.toRepresentation(client, session); rep = ModelToRepresentation.toRepresentation(client, session);
Stream<String> defaultRolesNames = client.getDefaultRolesStream();
if (defaultRolesNames != null) {
rep.setDefaultRoles(defaultRolesNames.toArray(String[]::new));
}
if (auth.isRegistrationAccessToken()) { if (auth.isRegistrationAccessToken()) {
String registrationAccessToken = ClientRegistrationTokenUtils.updateRegistrationAccessToken(session, client, auth.getRegistrationAuth()); String registrationAccessToken = ClientRegistrationTokenUtils.updateRegistrationAccessToken(session, client, auth.getRegistrationAuth());
rep.setRegistrationAccessToken(registrationAccessToken); rep.setRegistrationAccessToken(registrationAccessToken);

View file

@ -17,7 +17,7 @@
package org.keycloak.testsuite.client; package org.keycloak.testsuite.client;
import org.junit.Assert; import org.hamcrest.Matchers;
import org.junit.Test; import org.junit.Test;
import org.keycloak.client.registration.Auth; import org.keycloak.client.registration.Auth;
import org.keycloak.client.registration.ClientRegistration; import org.keycloak.client.registration.ClientRegistration;
@ -26,7 +26,6 @@ import org.keycloak.client.registration.HttpErrorException;
import org.keycloak.models.Constants; import org.keycloak.models.Constants;
import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper; import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper;
import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.ClientScopeRepresentation;
import org.keycloak.representations.idm.OAuth2ErrorRepresentation; import org.keycloak.representations.idm.OAuth2ErrorRepresentation;
import org.keycloak.representations.idm.ProtocolMapperRepresentation; import org.keycloak.representations.idm.ProtocolMapperRepresentation;
import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.representations.idm.UserRepresentation;
@ -46,13 +45,13 @@ import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.core.Is.is; import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import org.keycloak.protocol.oidc.OIDCLoginProtocol; import org.keycloak.protocol.oidc.OIDCLoginProtocol;
@ -90,7 +89,7 @@ public class ClientRegistrationTest extends AbstractClientRegistrationTest {
// Remove this client after test // Remove this client after test
getCleanup().addClientUuid(createdClient.getId()); getCleanup().addClientUuid(createdClient.getId());
return client; return createdClient;
} }
@Test @Test
@ -174,6 +173,24 @@ public class ClientRegistrationTest extends AbstractClientRegistrationTest {
assertEquals(name, createdClient.getName()); assertEquals(name, createdClient.getName());
} }
@Test
public void clientWithDefaultRoles() throws ClientRegistrationException {
authCreateClients();
ClientRepresentation client = buildClient();
client.setDefaultRoles(new String[]{"test-default-role"});
ClientRepresentation createdClient = registerClient(client);
assertThat(createdClient.getDefaultRoles(), Matchers.arrayContaining("test-default-role"));
authManageClients();
ClientRepresentation obtainedClient = reg.get(CLIENT_ID);
assertThat(obtainedClient.getDefaultRoles(), Matchers.arrayContaining("test-default-role"));
client.setDefaultRoles(new String[]{"test-default-role1","test-default-role2"});
ClientRepresentation updatedClient = reg.update(client);
assertThat(updatedClient.getDefaultRoles(), Matchers.arrayContainingInAnyOrder("test-default-role1","test-default-role2"));
}
@Test @Test
public void testInvalidUrlClientValidation() { public void testInvalidUrlClientValidation() {
testClientUriValidation("Root URL is not a valid URL", testClientUriValidation("Root URL is not a valid URL",