From 782d145cefc487ac966dcbca41ebffeed6f0c0e4 Mon Sep 17 00:00:00 2001 From: Pedro Igor Date: Wed, 31 Aug 2022 17:48:09 -0300 Subject: [PATCH] Allow updating authz settings via default client registration provider Closes #9008 --- .../DefaultClientRegistrationProvider.java | 10 +++++ .../client/ClientRegistrationTest.java | 39 +++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/services/src/main/java/org/keycloak/services/clientregistration/DefaultClientRegistrationProvider.java b/services/src/main/java/org/keycloak/services/clientregistration/DefaultClientRegistrationProvider.java index a0b484647ab..a3e3bf6be8a 100755 --- a/services/src/main/java/org/keycloak/services/clientregistration/DefaultClientRegistrationProvider.java +++ b/services/src/main/java/org/keycloak/services/clientregistration/DefaultClientRegistrationProvider.java @@ -19,7 +19,9 @@ package org.keycloak.services.clientregistration; import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; +import org.keycloak.models.utils.RepresentationToModel; import org.keycloak.representations.idm.ClientRepresentation; +import org.keycloak.representations.idm.authorization.ResourceServerRepresentation; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; @@ -68,7 +70,9 @@ public class DefaultClientRegistrationProvider extends AbstractClientRegistratio @Produces(MediaType.APPLICATION_JSON) public Response updateDefault(@PathParam("clientId") String clientId, ClientRepresentation client) { DefaultClientRegistrationContext context = new DefaultClientRegistrationContext(session, client, this); + ResourceServerRepresentation authorizationSettings = client.getAuthorizationSettings(); client = update(clientId, context); + updateAuthorizationSettings(client, authorizationSettings); validateClient(client, false); return Response.ok(client).build(); } @@ -78,4 +82,10 @@ public class DefaultClientRegistrationProvider extends AbstractClientRegistratio public void deleteDefault(@PathParam("clientId") String clientId) { delete(clientId); } + + private void updateAuthorizationSettings(ClientRepresentation rep, ResourceServerRepresentation authorizationSettings) { + rep.setAuthorizationSettings(authorizationSettings); + ClientModel client = session.getContext().getRealm().getClientByClientId(rep.getClientId()); + RepresentationToModel.importAuthorizationSettings(rep, client, session); + } } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/ClientRegistrationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/ClientRegistrationTest.java index 6e0e22dc343..7f894a26897 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/ClientRegistrationTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/ClientRegistrationTest.java @@ -33,11 +33,15 @@ import org.keycloak.client.registration.ClientRegistration; import org.keycloak.client.registration.ClientRegistrationException; import org.keycloak.client.registration.HttpErrorException; import org.keycloak.models.Constants; +import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper; import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.OAuth2ErrorRepresentation; import org.keycloak.representations.idm.ProtocolMapperRepresentation; import org.keycloak.representations.idm.UserRepresentation; +import org.keycloak.representations.idm.authorization.PolicyRepresentation; +import org.keycloak.representations.idm.authorization.ResourceRepresentation; +import org.keycloak.representations.idm.authorization.ResourceServerRepresentation; import org.keycloak.testsuite.arquillian.annotation.UncaughtServerErrorExpected; import org.keycloak.util.JsonSerialization; @@ -59,6 +63,7 @@ import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -231,6 +236,40 @@ public class ClientRegistrationTest extends AbstractClientRegistrationTest { ); } + @Test + public void testUpdateAuthorizationSettings() throws ClientRegistrationException { + authManageClients(); + ClientRepresentation clientRep = buildClient(); + clientRep.setAuthorizationServicesEnabled(true); + + ClientRepresentation rep = registerClient(clientRep); + rep = adminClient.realm("test").clients().get(rep.getId()).toRepresentation(); + + assertTrue(rep.getAuthorizationServicesEnabled()); + + ResourceServerRepresentation authzSettings = new ResourceServerRepresentation(); + + authzSettings.setAllowRemoteResourceManagement(false); + authzSettings.setResources(List.of(new ResourceRepresentation("foo", "scope-a", "scope-b"))); + + PolicyRepresentation permission = new PolicyRepresentation(); + + permission.setName(KeycloakModelUtils.generateId()); + permission.setType("resource"); + permission.setResources(Collections.singleton("foo")); + + authzSettings.setPolicies(List.of(permission)); + + rep.setAuthorizationSettings(authzSettings); + + reg.update(rep); + authzSettings = adminClient.realm("test").clients().get(rep.getId()).authorization().exportSettings(); + + assertFalse(authzSettings.getResources().isEmpty()); + assertFalse(authzSettings.getScopes().isEmpty()); + assertFalse(authzSettings.getPolicies().isEmpty()); + } + private void testClientUriValidation(String expectedRootUrlError, String expectedBaseUrlError, String expectedBackchannelLogoutUrlError, String expectedRedirectUrisError, String... testUrls) { testClientUriValidation(true, expectedRootUrlError, expectedBaseUrlError, expectedBackchannelLogoutUrlError, expectedRedirectUrisError, testUrls); testClientUriValidation(false, expectedRootUrlError, expectedBaseUrlError, expectedBackchannelLogoutUrlError, expectedRedirectUrisError, testUrls);