KEYCLOAK-14919 Dynamic registration - Scope ignored

This commit is contained in:
Takashi Norimatsu 2020-08-15 18:20:02 +09:00 committed by Marek Posolda
parent 107a429238
commit b93a6ed19f
3 changed files with 138 additions and 0 deletions

View file

@ -46,9 +46,11 @@ import org.keycloak.util.JWKSUtils;
import java.net.URI;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@ -63,6 +65,9 @@ public class DescriptionConverter {
client.setRedirectUris(clientOIDC.getRedirectUris());
client.setBaseUrl(clientOIDC.getClientUri());
String scopeParam = clientOIDC.getScope();
if (scopeParam != null) client.setOptionalClientScopes(new ArrayList<>(Arrays.asList(scopeParam.split(" "))));
List<String> oidcResponseTypes = clientOIDC.getResponseTypes();
if (oidcResponseTypes == null || oidcResponseTypes.isEmpty()) {
oidcResponseTypes = Collections.singletonList(OIDCResponseType.CODE);
@ -216,6 +221,9 @@ public class DescriptionConverter {
response.setResponseTypes(getOIDCResponseTypes(client));
response.setGrantTypes(getOIDCGrantTypes(client));
List<String> scopes = client.getOptionalClientScopes();
if (scopes != null) response.setScope(scopes.stream().collect(Collectors.joining(" ")));
OIDCAdvancedConfigWrapper config = OIDCAdvancedConfigWrapper.fromClientRepresentation(client);
if (config.isUserInfoSignatureRequired()) {
response.setUserinfoSignedResponseAlg(config.getUserInfoSignedResponseAlg().toString());

View file

@ -17,6 +17,7 @@
package org.keycloak.testsuite.client;
import org.junit.Assert;
import org.junit.Test;
import org.keycloak.client.registration.Auth;
import org.keycloak.client.registration.ClientRegistration;
@ -24,6 +25,7 @@ import org.keycloak.client.registration.ClientRegistrationException;
import org.keycloak.client.registration.HttpErrorException;
import org.keycloak.models.Constants;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.ClientScopeRepresentation;
import org.keycloak.representations.idm.OAuth2ErrorRepresentation;
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
@ -34,7 +36,12 @@ import org.keycloak.util.JsonSerialization;
import javax.ws.rs.NotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.core.Is.is;
@ -42,6 +49,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer;
@ -445,4 +453,64 @@ public class ClientRegistrationTest extends AbstractClientRegistrationTest {
}
}
@Test
public void registerClientAsAdminWithScope() throws ClientRegistrationException {
authManageClients();
ClientRepresentation client = new ClientRepresentation();
client.setClientId(CLIENT_ID);
client.setSecret(CLIENT_SECRET);
ArrayList<String> optionalClientScopes = new ArrayList<>(Arrays.asList("address","phone"));
client.setOptionalClientScopes(optionalClientScopes);
ClientRepresentation createdClient = reg.create(client);
assertEquals(CLIENT_ID, createdClient.getClientId());
client = adminClient.realm(REALM_NAME).clients().get(createdClient.getId()).toRepresentation();
assertEquals(CLIENT_ID, client.getClientId());
// Remove this client after test
getCleanup().addClientUuid(createdClient.getId());
Set<String> requestedClientScopes = new HashSet<>(optionalClientScopes);
Set<String> registeredClientScopes = new HashSet<>(client.getOptionalClientScopes());
assertTrue(requestedClientScopes.equals(registeredClientScopes));
assertTrue(client.getDefaultClientScopes().isEmpty());
}
@Test
public void registerClientAsAdminWithoutScope() throws ClientRegistrationException {
Set<String> realmDefaultClientScopes = new HashSet<>(adminClient.realm(REALM_NAME).getDefaultDefaultClientScopes()
.stream().map(i->i.getName()).collect(Collectors.toList()));
Set<String> realmOptionalClientScopes = new HashSet<>(adminClient.realm(REALM_NAME).getDefaultOptionalClientScopes()
.stream().map(i->i.getName()).collect(Collectors.toList()));
authManageClients();
ClientRepresentation client = new ClientRepresentation();
client.setClientId(CLIENT_ID);
client.setSecret(CLIENT_SECRET);
ClientRepresentation createdClient = reg.create(client);
assertEquals(CLIENT_ID, createdClient.getClientId());
client = adminClient.realm(REALM_NAME).clients().get(createdClient.getId()).toRepresentation();
assertEquals(CLIENT_ID, client.getClientId());
// Remove this client after test
getCleanup().addClientUuid(createdClient.getId());
assertTrue(realmDefaultClientScopes.equals(new HashSet<>(client.getDefaultClientScopes())));
assertTrue(realmOptionalClientScopes.equals(new HashSet<>(client.getOptionalClientScopes())));
}
@Test
public void registerClientAsAdminWithNotDefinedScope() throws ClientRegistrationException {
authManageClients();
ClientRepresentation client = new ClientRepresentation();
client.setClientId(CLIENT_ID);
client.setSecret(CLIENT_SECRET);
client.setOptionalClientScopes(new ArrayList<>(Arrays.asList("notdefinedscope","phone")));
try {
registerClient(client);
fail("Expected 403");
} catch (ClientRegistrationException e) {
assertEquals(403, ((HttpErrorException) e.getCause()).getStatusLine().getStatusCode());
}
}
}

View file

@ -21,6 +21,7 @@ package org.keycloak.testsuite.client;
import org.junit.Before;
import org.junit.Test;
import org.keycloak.OAuth2Constants;
import org.keycloak.admin.client.resource.ClientResource;
import org.keycloak.admin.client.resource.ClientsResource;
import org.keycloak.authentication.authenticators.client.X509ClientAuthenticator;
import org.keycloak.client.registration.Auth;
@ -44,9 +45,11 @@ import org.keycloak.testsuite.admin.ApiUtil;
import org.keycloak.testsuite.util.KeycloakModelUtils;
import java.util.*;
import java.util.stream.Collectors;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
@ -468,5 +471,64 @@ public class OIDCClientRegistrationTest extends AbstractClientRegistrationTest {
return ApiUtil.findClientByClientId(adminClient.realms().realm(REALM_NAME), clientId).toRepresentation();
}
@Test
public void testClientWithScope() throws Exception {
OIDCClientRepresentation clientRep = null;
OIDCClientRepresentation response = null;
String clientScope = "phone address";
clientRep = createRep();
clientRep.setScope(clientScope);
response = reg.oidc().create(clientRep);
Set<String> clientScopes = new HashSet<>(Arrays.asList(clientScope.split(" ")));
Set<String> registeredClientScopes = new HashSet<>(Arrays.asList(response.getScope().split(" ")));
assertTrue(clientScopes.equals(registeredClientScopes));
ClientResource clientResource = adminClient.realm(REALM_NAME).clients().get(response.getClientId());
assertTrue(clientResource.toRepresentation().getDefaultClientScopes().isEmpty());
}
@Test
public void testClientWithNotDefinedScope() throws Exception {
OIDCClientRepresentation clientRep = null;
OIDCClientRepresentation response = null;
String clientScope = "notdefinedscope address";
clientRep = createRep();
clientRep.setScope(clientScope);
try {
response = reg.oidc().create(clientRep);
fail("Expected 403");
} catch (ClientRegistrationException e) {
assertEquals(403, ((HttpErrorException) e.getCause()).getStatusLine().getStatusCode());
}
}
@Test
public void testClientWithoutScope() throws ClientRegistrationException {
Set<String> realmOptionalClientScopes = new HashSet<>(adminClient.realm(REALM_NAME).getDefaultOptionalClientScopes()
.stream().map(i->i.getName()).collect(Collectors.toList()));
OIDCClientRepresentation clientRep = null;
OIDCClientRepresentation response = null;
clientRep = createRep();
response = reg.oidc().create(clientRep);
Set<String> registeredClientScopes = new HashSet<>(Arrays.asList(response.getScope().split(" ")));
assertTrue(realmOptionalClientScopes.equals(new HashSet<>(registeredClientScopes)));
ClientResource clientResource = adminClient.realm(REALM_NAME).clients().get(response.getClientId());
ClientRepresentation rep = clientResource.toRepresentation();
Set<String> realmDefaultClientScopes = new HashSet<>(adminClient.realm(REALM_NAME).getDefaultDefaultClientScopes()
.stream().map(i->i.getName()).collect(Collectors.toList()));
Set<String> registeredDefaultClientScopes = new HashSet<>(rep.getDefaultClientScopes());
assertTrue(realmDefaultClientScopes.equals(new HashSet<>(registeredDefaultClientScopes)));
}
}