[KEYCLOAK-5628] Added application endpoint
This commit is contained in:
parent
66f5d1259f
commit
f9fa5b551d
7 changed files with 298 additions and 91 deletions
|
@ -97,6 +97,9 @@ public final class StringPropertyReplacer
|
|||
*/
|
||||
public static String replaceProperties(final String string, final Properties props)
|
||||
{
|
||||
if(string == null) {
|
||||
return null;
|
||||
}
|
||||
final char[] chars = string.toCharArray();
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
boolean properties = false;
|
||||
|
|
|
@ -6,6 +6,12 @@ package org.keycloak.representations.account;
|
|||
public class ClientRepresentation {
|
||||
private String clientId;
|
||||
private String clientName;
|
||||
private String description;
|
||||
private boolean userConsentRequired;
|
||||
private boolean inUse;
|
||||
private boolean offlineAccess;
|
||||
private String baseUrl;
|
||||
private ConsentRepresentation consent;
|
||||
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
|
@ -22,4 +28,52 @@ public class ClientRepresentation {
|
|||
public void setClientName(String clientName) {
|
||||
this.clientName = clientName;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public boolean isUserConsentRequired() {
|
||||
return userConsentRequired;
|
||||
}
|
||||
|
||||
public void setUserConsentRequired(boolean userConsentRequired) {
|
||||
this.userConsentRequired = userConsentRequired;
|
||||
}
|
||||
|
||||
public boolean isInUse() {
|
||||
return inUse;
|
||||
}
|
||||
|
||||
public void setInUse(boolean inUse) {
|
||||
this.inUse = inUse;
|
||||
}
|
||||
|
||||
public boolean isOfflineAccess() {
|
||||
return offlineAccess;
|
||||
}
|
||||
|
||||
public void setOfflineAccess(boolean offlineAccess) {
|
||||
this.offlineAccess = offlineAccess;
|
||||
}
|
||||
|
||||
public String getBaseUrl() {
|
||||
return baseUrl;
|
||||
}
|
||||
|
||||
public void setBaseUrl(String baseUrl) {
|
||||
this.baseUrl = baseUrl;
|
||||
}
|
||||
|
||||
public ConsentRepresentation getConsent() {
|
||||
return consent;
|
||||
}
|
||||
|
||||
public void setConsent(ConsentRepresentation consent) {
|
||||
this.consent = consent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ import java.util.List;
|
|||
|
||||
public class ConsentRepresentation {
|
||||
|
||||
private List<ConsentScopeRepresentation> scopes;
|
||||
private List<ConsentScopeRepresentation> grantedScopes;
|
||||
|
||||
private Long createdDate;
|
||||
|
||||
|
@ -30,18 +30,18 @@ public class ConsentRepresentation {
|
|||
public ConsentRepresentation() {
|
||||
}
|
||||
|
||||
public ConsentRepresentation(List<ConsentScopeRepresentation> scopes, Long createdDate, Long lastUpdatedDate) {
|
||||
this.scopes = scopes;
|
||||
public ConsentRepresentation(List<ConsentScopeRepresentation> grantedScopes, Long createdDate, Long lastUpdatedDate) {
|
||||
this.grantedScopes = grantedScopes;
|
||||
this.createdDate = createdDate;
|
||||
this.lastUpdatedDate = lastUpdatedDate;
|
||||
}
|
||||
|
||||
public List<ConsentScopeRepresentation> getScopes() {
|
||||
return scopes;
|
||||
public List<ConsentScopeRepresentation> getGrantedScopes() {
|
||||
return grantedScopes;
|
||||
}
|
||||
|
||||
public void setScopes(List<ConsentScopeRepresentation> scopes) {
|
||||
this.scopes = scopes;
|
||||
public void setGrantedScopes(List<ConsentScopeRepresentation> grantedScopes) {
|
||||
this.grantedScopes = grantedScopes;
|
||||
}
|
||||
|
||||
public Long getCreatedDate() {
|
||||
|
|
|
@ -19,17 +19,20 @@ package org.keycloak.services.resources.account;
|
|||
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||
import org.jboss.resteasy.spi.HttpRequest;
|
||||
import org.keycloak.common.ClientConnection;
|
||||
import org.keycloak.common.util.StringPropertyReplacer;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.events.EventBuilder;
|
||||
import org.keycloak.events.EventStoreProvider;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.models.AccountRoles;
|
||||
import org.keycloak.models.AuthenticatedClientSessionModel;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.ClientScopeModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserConsentModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.representations.account.ClientRepresentation;
|
||||
import org.keycloak.representations.account.ConsentRepresentation;
|
||||
import org.keycloak.representations.account.ConsentScopeRepresentation;
|
||||
|
@ -56,10 +59,15 @@ import javax.ws.rs.core.HttpHeaders;
|
|||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.keycloak.common.Profile;
|
||||
|
@ -242,28 +250,6 @@ public class AccountRestService {
|
|||
|
||||
// TODO Federated identities
|
||||
|
||||
/**
|
||||
* Returns the list of available applications in the specified
|
||||
* realm.
|
||||
*
|
||||
* @return list of applications in that realm
|
||||
*/
|
||||
@Path("/applications")
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response getApplications() {
|
||||
checkAccountApiEnabled();
|
||||
auth.require(AccountRoles.VIEW_APPLICATIONS);
|
||||
|
||||
List<ClientModel> clients = realm.getClients();
|
||||
|
||||
List<ClientRepresentation> clientRepresentations = clients.stream()
|
||||
.map(this::modelToRepresentation)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return Cors.add(request, Response.ok(clientRepresentations)).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the applications with the given id in the specified realm.
|
||||
*
|
||||
|
@ -275,42 +261,56 @@ public class AccountRestService {
|
|||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response getApplication(final @PathParam("clientId") String clientId) {
|
||||
checkAccountApiEnabled();
|
||||
auth.require(AccountRoles.VIEW_APPLICATIONS);
|
||||
auth.requireOneOf(AccountRoles.MANAGE_ACCOUNT, AccountRoles.VIEW_APPLICATIONS);
|
||||
ClientModel client = realm.getClientByClientId(clientId);
|
||||
if (client == null) {
|
||||
if (client == null || client.isBearerOnly() || client.getBaseUrl() == null) {
|
||||
return Cors.add(request, Response.status(Response.Status.NOT_FOUND).entity("No client with clientId: " + clientId + " found.")).build();
|
||||
}
|
||||
|
||||
return Cors.add(request, Response.ok(modelToRepresentation(client))).build();
|
||||
List<String> inUseClients = new LinkedList<>();
|
||||
if(!session.sessions().getUserSessions(realm, client).isEmpty()) {
|
||||
inUseClients.add(clientId);
|
||||
}
|
||||
|
||||
List<String> offlineClients = new LinkedList<>();
|
||||
if(session.sessions().getOfflineSessionsCount(realm, client) > 0) {
|
||||
offlineClients.add(clientId);
|
||||
}
|
||||
|
||||
UserConsentModel consentModel = session.users().getConsentByClient(realm, user.getId(), client.getId());
|
||||
Map<String, UserConsentModel> consentModels = Collections.singletonMap(client.getClientId(), consentModel);
|
||||
|
||||
return Cors.add(request, Response.ok(modelToRepresentation(client, inUseClients, offlineClients, consentModels))).build();
|
||||
}
|
||||
|
||||
private ClientRepresentation modelToRepresentation(ClientModel model) {
|
||||
private ClientRepresentation modelToRepresentation(ClientModel model, List<String> inUseClients, List<String> offlineClients, Map<String, UserConsentModel> consents) {
|
||||
ClientRepresentation representation = new ClientRepresentation();
|
||||
representation.setClientId(model.getClientId());
|
||||
representation.setClientName(getTranslationOrDefault(model.getName()));
|
||||
representation.setClientName(StringPropertyReplacer.replaceProperties(model.getName(), getProperties()));
|
||||
representation.setDescription(model.getDescription());
|
||||
representation.setUserConsentRequired(model.isConsentRequired());
|
||||
representation.setInUse(inUseClients.contains(model.getClientId()));
|
||||
representation.setOfflineAccess(offlineClients.contains(model.getClientId()));
|
||||
representation.setBaseUrl(model.getBaseUrl());
|
||||
UserConsentModel consentModel = consents.get(client.getClientId());
|
||||
if(consentModel != null) {
|
||||
representation.setConsent(modelToRepresentation(consentModel));
|
||||
}
|
||||
return representation;
|
||||
}
|
||||
|
||||
private ConsentRepresentation modelToRepresentation(UserConsentModel model) {
|
||||
List<ConsentScopeRepresentation> scopes = model.getGrantedClientScopes().stream()
|
||||
.map(m -> new ConsentScopeRepresentation(m.getId(), m.getName(), getTranslationOrDefault(m.getConsentScreenText())))
|
||||
List<ConsentScopeRepresentation> grantedScopes = model.getGrantedClientScopes().stream()
|
||||
.map(m -> new ConsentScopeRepresentation(m.getId(), m.getName(), StringPropertyReplacer.replaceProperties(m.getConsentScreenText(), getProperties())))
|
||||
.collect(Collectors.toList());
|
||||
return new ConsentRepresentation(scopes, model.getCreatedDate(), model.getLastUpdatedDate());
|
||||
return new ConsentRepresentation(grantedScopes, model.getCreatedDate(), model.getLastUpdatedDate());
|
||||
}
|
||||
|
||||
private String getTranslationOrDefault(String key) {
|
||||
if (key == null) {
|
||||
return null;
|
||||
}
|
||||
String defaultValue = key;
|
||||
if (key.startsWith("${")) {
|
||||
key = key.substring(2, key.length() - 1);
|
||||
}
|
||||
private Properties getProperties() {
|
||||
try {
|
||||
Properties messages = session.theme().getTheme(Theme.Type.ACCOUNT).getMessages(locale);
|
||||
return messages.getProperty(key, defaultValue);
|
||||
return session.theme().getTheme(Theme.Type.ACCOUNT).getMessages(locale);
|
||||
} catch (IOException e) {
|
||||
return key;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -325,7 +325,7 @@ public class AccountRestService {
|
|||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response getConsent(final @PathParam("clientId") String clientId) {
|
||||
checkAccountApiEnabled();
|
||||
auth.requireOneOf(AccountRoles.VIEW_CONSENT, AccountRoles.MANAGE_CONSENT);
|
||||
auth.requireOneOf(AccountRoles.MANAGE_ACCOUNT, AccountRoles.VIEW_CONSENT, AccountRoles.MANAGE_CONSENT);
|
||||
|
||||
ClientModel client = realm.getClientByClientId(clientId);
|
||||
if (client == null) {
|
||||
|
@ -350,7 +350,7 @@ public class AccountRestService {
|
|||
@DELETE
|
||||
public Response revokeConsent(final @PathParam("clientId") String clientId) {
|
||||
checkAccountApiEnabled();
|
||||
auth.require(AccountRoles.MANAGE_CONSENT);
|
||||
auth.requireOneOf(AccountRoles.MANAGE_ACCOUNT, AccountRoles.MANAGE_CONSENT);
|
||||
|
||||
event.event(EventType.REVOKE_GRANT);
|
||||
ClientModel client = realm.getClientByClientId(clientId);
|
||||
|
@ -420,7 +420,7 @@ public class AccountRestService {
|
|||
*/
|
||||
private Response upsert(String clientId, ConsentRepresentation consent) {
|
||||
checkAccountApiEnabled();
|
||||
auth.require(AccountRoles.MANAGE_CONSENT);
|
||||
auth.requireOneOf(AccountRoles.MANAGE_ACCOUNT, AccountRoles.MANAGE_CONSENT);
|
||||
|
||||
event.event(EventType.GRANT_CONSENT);
|
||||
ClientModel client = realm.getClientByClientId(clientId);
|
||||
|
@ -463,7 +463,7 @@ public class AccountRestService {
|
|||
availableGrants.put(client.getId(), client);
|
||||
}
|
||||
|
||||
for (ConsentScopeRepresentation scopeRepresentation : requested.getScopes()) {
|
||||
for (ConsentScopeRepresentation scopeRepresentation : requested.getGrantedScopes()) {
|
||||
ClientScopeModel scopeModel = availableGrants.get(scopeRepresentation.getId());
|
||||
if (scopeModel == null) {
|
||||
String msg = String.format("Scope id %s does not exist for client %s.", scopeRepresentation, consent.getClient().getName());
|
||||
|
@ -481,6 +481,54 @@ public class AccountRestService {
|
|||
return new LinkedAccountsResource(session, request, client, auth, event, user);
|
||||
}
|
||||
|
||||
@Path("/applications")
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@NoCache
|
||||
public Response applications() {
|
||||
checkAccountApiEnabled();
|
||||
auth.requireOneOf(AccountRoles.MANAGE_ACCOUNT, AccountRoles.VIEW_APPLICATIONS);
|
||||
|
||||
Set<ClientModel> clients = new HashSet<ClientModel>();
|
||||
List<String> inUseClients = new LinkedList<String>();
|
||||
List<UserSessionModel> sessions = session.sessions().getUserSessions(realm, user);
|
||||
for(UserSessionModel s : sessions) {
|
||||
for (AuthenticatedClientSessionModel a : s.getAuthenticatedClientSessions().values()) {
|
||||
ClientModel client = a.getClient();
|
||||
clients.add(client);
|
||||
inUseClients.add(client.getClientId());
|
||||
}
|
||||
}
|
||||
|
||||
List<String> offlineClients = new LinkedList<String>();
|
||||
List<UserSessionModel> offlineSessions = session.sessions().getOfflineUserSessions(realm, user);
|
||||
for(UserSessionModel s : offlineSessions) {
|
||||
for(AuthenticatedClientSessionModel a : s.getAuthenticatedClientSessions().values()) {
|
||||
ClientModel client = a.getClient();
|
||||
clients.add(client);
|
||||
offlineClients.add(client.getClientId());
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, UserConsentModel> consentModels = new HashMap<String, UserConsentModel>();
|
||||
List<UserConsentModel> consents = session.users().getConsents(realm, user.getId());
|
||||
for (UserConsentModel consent : consents) {
|
||||
ClientModel client = consent.getClient();
|
||||
clients.add(client);
|
||||
consentModels.put(client.getClientId(), consent);
|
||||
}
|
||||
|
||||
List<ClientRepresentation> apps = new LinkedList<ClientRepresentation>();
|
||||
for (ClientModel client : clients) {
|
||||
if (client.isBearerOnly() || client.getBaseUrl() == null) {
|
||||
continue;
|
||||
}
|
||||
apps.add(modelToRepresentation(client, inUseClients, offlineClients, consentModels));
|
||||
}
|
||||
|
||||
return Cors.add(request, Response.ok(apps)).auth().allowedOrigins(auth.getToken()).build();
|
||||
}
|
||||
|
||||
// TODO Logs
|
||||
|
||||
private static void checkAccountApiEnabled() {
|
||||
|
|
|
@ -19,8 +19,8 @@ package org.keycloak.testsuite.account;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.keycloak.common.Profile.Feature.ACCOUNT_API;
|
||||
import static org.keycloak.testsuite.util.OAuthClient.APP_ROOT;
|
||||
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -32,12 +32,14 @@ import org.junit.Before;
|
|||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.broker.provider.util.SimpleHttp;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.representations.account.SessionRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.testsuite.AbstractTestRealmKeycloakTest;
|
||||
import org.keycloak.testsuite.AssertEvents;
|
||||
import org.keycloak.testsuite.arquillian.annotation.DisableFeature;
|
||||
import org.keycloak.testsuite.arquillian.annotation.EnableFeature;
|
||||
import org.keycloak.testsuite.util.ClientBuilder;
|
||||
import org.keycloak.testsuite.util.TokenUtil;
|
||||
import org.keycloak.testsuite.util.UserBuilder;
|
||||
|
||||
|
@ -55,6 +57,10 @@ public abstract class AbstractRestServiceTest extends AbstractTestRealmKeycloakT
|
|||
|
||||
protected CloseableHttpClient httpClient;
|
||||
|
||||
protected String inUseClientAppUri = APP_ROOT + "/in-use-client";
|
||||
|
||||
protected String offlineClientAppUri = APP_ROOT + "/offline-client";
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
httpClient = HttpClientBuilder.create().build();
|
||||
|
@ -73,9 +79,25 @@ public abstract class AbstractRestServiceTest extends AbstractTestRealmKeycloakT
|
|||
public void configureTestRealm(RealmRepresentation testRealm) {
|
||||
testRealm.getUsers().add(UserBuilder.create().username("no-account-access").password("password").build());
|
||||
testRealm.getUsers().add(UserBuilder.create().username("view-account-access").role("account", "view-profile").password("password").build());
|
||||
testRealm.getUsers().add(UserBuilder.create().username("view-applications-access").role("account", "view-applications").password("password").build());
|
||||
testRealm.getUsers().add(UserBuilder.create().username("view-applications-access").addRoles("user", "offline_access").role("account", "view-applications").role("account", "manage-consent").password("password").build());
|
||||
testRealm.getUsers().add(UserBuilder.create().username("view-consent-access").role("account", "view-consent").password("password").build());
|
||||
testRealm.getUsers().add(UserBuilder.create().username("manage-consent-access").role("account", "manage-consent").password("password").build());
|
||||
|
||||
org.keycloak.representations.idm.ClientRepresentation inUseApp = ClientBuilder.create().clientId("in-use-client")
|
||||
.id(KeycloakModelUtils.generateId())
|
||||
.name("In Use Client")
|
||||
.baseUrl(inUseClientAppUri)
|
||||
.directAccessGrants()
|
||||
.secret("secret1").build();
|
||||
testRealm.getClients().add(inUseApp);
|
||||
|
||||
org.keycloak.representations.idm.ClientRepresentation offlineApp = ClientBuilder.create().clientId("offline-client")
|
||||
.id(KeycloakModelUtils.generateId())
|
||||
.name("Offline Client")
|
||||
.baseUrl(offlineClientAppUri)
|
||||
.directAccessGrants()
|
||||
.secret("secret1").build();
|
||||
testRealm.getClients().add(offlineApp);
|
||||
}
|
||||
|
||||
protected String getAccountUrl(String resource) {
|
||||
|
|
|
@ -17,7 +17,9 @@
|
|||
package org.keycloak.testsuite.account;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.broker.provider.util.SimpleHttp;
|
||||
import org.keycloak.representations.account.ClientRepresentation;
|
||||
import org.keycloak.representations.account.ConsentRepresentation;
|
||||
|
@ -30,7 +32,7 @@ import org.keycloak.representations.idm.RealmRepresentation;
|
|||
import org.keycloak.services.messages.Messages;
|
||||
import org.keycloak.services.resources.account.AccountCredentialResource;
|
||||
import org.keycloak.services.resources.account.AccountCredentialResource.PasswordUpdate;
|
||||
import org.keycloak.testsuite.arquillian.annotation.EnableFeature;
|
||||
import org.keycloak.testsuite.util.OAuthClient;
|
||||
import org.keycloak.testsuite.util.TokenUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -38,16 +40,15 @@ import java.util.Collections;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.keycloak.common.Profile.Feature.ACCOUNT_API;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class AccountRestServiceTest extends AbstractRestServiceTest {
|
||||
|
||||
@Test
|
||||
public void testGetProfile() throws IOException {
|
||||
UserRepresentation user = SimpleHttp.doGet(getAccountUrl(null), httpClient).auth(tokenUtil.getToken()).asJson(UserRepresentation.class);
|
||||
|
@ -285,7 +286,11 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void listApplications() throws IOException {
|
||||
public void listApplications() throws Exception {
|
||||
oauth.clientId("in-use-client");
|
||||
OAuthClient.AccessTokenResponse tokenResponse = oauth.doGrantAccessTokenRequest("secret1", "view-applications-access", "password");
|
||||
Assert.assertNull(tokenResponse.getErrorDescription());
|
||||
|
||||
TokenUtil token = new TokenUtil("view-applications-access", "password");
|
||||
List<ClientRepresentation> applications = SimpleHttp
|
||||
.doGet(getAccountUrl("applications"), httpClient)
|
||||
|
@ -294,11 +299,86 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
|||
.asJson(new TypeReference<List<ClientRepresentation>>() {
|
||||
});
|
||||
assertFalse(applications.isEmpty());
|
||||
|
||||
Map<String, ClientRepresentation> apps = applications.stream().collect(Collectors.toMap(x -> x.getClientId(), x -> x));
|
||||
Assert.assertThat(apps.keySet(), containsInAnyOrder("in-use-client"));
|
||||
|
||||
assertClientRep(apps.get("in-use-client"), "In Use Client", null, false, true, false, inUseClientAppUri);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listApplicationsOfflineAccess() throws Exception {
|
||||
oauth.scope(OAuth2Constants.OFFLINE_ACCESS);
|
||||
oauth.clientId("offline-client");
|
||||
OAuthClient.AccessTokenResponse offlineTokenResponse = oauth.doGrantAccessTokenRequest("secret1", "view-applications-access", "password");
|
||||
Assert.assertNull(offlineTokenResponse.getErrorDescription());
|
||||
|
||||
TokenUtil token = new TokenUtil("view-applications-access", "password");
|
||||
List<ClientRepresentation> applications = SimpleHttp
|
||||
.doGet(getAccountUrl("applications"), httpClient)
|
||||
.header("Accept", "application/json")
|
||||
.auth(token.getToken())
|
||||
.asJson(new TypeReference<List<ClientRepresentation>>() {
|
||||
});
|
||||
assertFalse(applications.isEmpty());
|
||||
|
||||
Map<String, ClientRepresentation> apps = applications.stream().collect(Collectors.toMap(x -> x.getClientId(), x -> x));
|
||||
Assert.assertThat(apps.keySet(), containsInAnyOrder("offline-client"));
|
||||
|
||||
assertClientRep(apps.get("offline-client"), "Offline Client", null, false, true, true, offlineClientAppUri);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listApplicationsThirdParty() throws Exception {
|
||||
String appId = "third-party";
|
||||
TokenUtil token = new TokenUtil("view-applications-access", "password");
|
||||
|
||||
ClientScopeRepresentation clientScopeRepresentation = testRealm().clientScopes().findAll().get(0);
|
||||
ConsentScopeRepresentation consentScopeRepresentation = new ConsentScopeRepresentation();
|
||||
consentScopeRepresentation.setId(clientScopeRepresentation.getId());
|
||||
|
||||
ConsentRepresentation requestedConsent = new ConsentRepresentation();
|
||||
requestedConsent.setGrantedScopes(Collections.singletonList(consentScopeRepresentation));
|
||||
SimpleHttp
|
||||
.doPost(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||
.header("Accept", "application/json")
|
||||
.json(requestedConsent)
|
||||
.auth(token.getToken())
|
||||
.asJson(ConsentRepresentation.class);
|
||||
|
||||
List<ClientRepresentation> applications = SimpleHttp
|
||||
.doGet(getAccountUrl("applications"), httpClient)
|
||||
.header("Accept", "application/json")
|
||||
.auth(token.getToken())
|
||||
.asJson(new TypeReference<List<ClientRepresentation>>() {
|
||||
});
|
||||
assertFalse(applications.isEmpty());
|
||||
|
||||
SimpleHttp
|
||||
.doDelete(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||
.header("Accept", "application/json")
|
||||
.auth(token.getToken())
|
||||
.asResponse();
|
||||
|
||||
Map<String, ClientRepresentation> apps = applications.stream().collect(Collectors.toMap(x -> x.getClientId(), x -> x));
|
||||
Assert.assertThat(apps.keySet(), containsInAnyOrder(appId));
|
||||
|
||||
assertClientRep(apps.get(appId), null, "A third party application", true, false, false, "http://localhost:8180/auth/realms/master/app/auth");
|
||||
}
|
||||
|
||||
private void assertClientRep(ClientRepresentation clientRep, String name, String description, boolean userConsentRequired, boolean inUse, boolean offlineAccess, String baseUrl) {
|
||||
assertNotNull(clientRep);
|
||||
assertEquals(name, clientRep.getClientName());
|
||||
assertEquals(description, clientRep.getDescription());
|
||||
assertEquals(userConsentRequired, clientRep.isUserConsentRequired());
|
||||
assertEquals(inUse, clientRep.isInUse());
|
||||
assertEquals(offlineAccess, clientRep.isOfflineAccess());
|
||||
assertEquals(baseUrl, clientRep.getBaseUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listApplicationsWithoutPermission() throws IOException {
|
||||
TokenUtil token = new TokenUtil("view-account-access", "password");
|
||||
TokenUtil token = new TokenUtil("no-account-access", "password");
|
||||
SimpleHttp.Response response = SimpleHttp
|
||||
.doGet(getAccountUrl("applications"), httpClient)
|
||||
.header("Accept", "application/json")
|
||||
|
@ -321,7 +401,7 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
|||
|
||||
@Test
|
||||
public void getWebConsoleApplicationWithoutPermission() throws IOException {
|
||||
TokenUtil token = new TokenUtil("view-account-access", "password");
|
||||
TokenUtil token = new TokenUtil("no-account-access", "password");
|
||||
String appId = "security-admin-console";
|
||||
SimpleHttp.Response response = SimpleHttp
|
||||
.doGet(getAccountUrl("applications/" + appId), httpClient)
|
||||
|
@ -353,7 +433,7 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
|||
consentScopeRepresentation.setId(clientScopeRepresentation.getId());
|
||||
|
||||
ConsentRepresentation requestedConsent = new ConsentRepresentation();
|
||||
requestedConsent.setScopes(Collections.singletonList(consentScopeRepresentation));
|
||||
requestedConsent.setGrantedScopes(Collections.singletonList(consentScopeRepresentation));
|
||||
|
||||
ConsentRepresentation consentRepresentation = SimpleHttp
|
||||
.doPost(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||
|
@ -363,8 +443,8 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
|||
.asJson(ConsentRepresentation.class);
|
||||
assertTrue(consentRepresentation.getCreatedDate() > 0);
|
||||
assertTrue(consentRepresentation.getLastUpdatedDate() > 0);
|
||||
assertEquals(1, consentRepresentation.getScopes().size());
|
||||
assertEquals(consentScopeRepresentation.getId(), consentRepresentation.getScopes().get(0).getId());
|
||||
assertEquals(1, consentRepresentation.getGrantedScopes().size());
|
||||
assertEquals(consentScopeRepresentation.getId(), consentRepresentation.getGrantedScopes().get(0).getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -377,7 +457,7 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
|||
consentScopeRepresentation.setId(clientScopeRepresentation.getId());
|
||||
|
||||
ConsentRepresentation requestedConsent = new ConsentRepresentation();
|
||||
requestedConsent.setScopes(Collections.singletonList(consentScopeRepresentation));
|
||||
requestedConsent.setGrantedScopes(Collections.singletonList(consentScopeRepresentation));
|
||||
|
||||
ConsentRepresentation consentRepresentation = SimpleHttp
|
||||
.doPost(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||
|
@ -387,15 +467,15 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
|||
.asJson(ConsentRepresentation.class);
|
||||
assertTrue(consentRepresentation.getCreatedDate() > 0);
|
||||
assertTrue(consentRepresentation.getLastUpdatedDate() > 0);
|
||||
assertEquals(1, consentRepresentation.getScopes().size());
|
||||
assertEquals(consentScopeRepresentation.getId(), consentRepresentation.getScopes().get(0).getId());
|
||||
assertEquals(1, consentRepresentation.getGrantedScopes().size());
|
||||
assertEquals(consentScopeRepresentation.getId(), consentRepresentation.getGrantedScopes().get(0).getId());
|
||||
|
||||
clientScopeRepresentation = testRealm().clientScopes().findAll().get(1);
|
||||
consentScopeRepresentation = new ConsentScopeRepresentation();
|
||||
consentScopeRepresentation.setId(clientScopeRepresentation.getId());
|
||||
|
||||
requestedConsent = new ConsentRepresentation();
|
||||
requestedConsent.setScopes(Collections.singletonList(consentScopeRepresentation));
|
||||
requestedConsent.setGrantedScopes(Collections.singletonList(consentScopeRepresentation));
|
||||
|
||||
ConsentRepresentation consentRepresentation2 = SimpleHttp
|
||||
.doPost(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||
|
@ -407,8 +487,8 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
|||
assertEquals(consentRepresentation.getCreatedDate(), consentRepresentation2.getCreatedDate());
|
||||
assertTrue(consentRepresentation2.getLastUpdatedDate() > 0);
|
||||
assertTrue(consentRepresentation2.getLastUpdatedDate() > consentRepresentation.getLastUpdatedDate());
|
||||
assertEquals(1, consentRepresentation2.getScopes().size());
|
||||
assertEquals(consentScopeRepresentation.getId(), consentRepresentation2.getScopes().get(0).getId());
|
||||
assertEquals(1, consentRepresentation2.getGrantedScopes().size());
|
||||
assertEquals(consentScopeRepresentation.getId(), consentRepresentation2.getGrantedScopes().get(0).getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -421,7 +501,7 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
|||
consentScopeRepresentation.setId(clientScopeRepresentation.getId());
|
||||
|
||||
ConsentRepresentation requestedConsent = new ConsentRepresentation();
|
||||
requestedConsent.setScopes(Collections.singletonList(consentScopeRepresentation));
|
||||
requestedConsent.setGrantedScopes(Collections.singletonList(consentScopeRepresentation));
|
||||
|
||||
SimpleHttp.Response response = SimpleHttp
|
||||
.doPost(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||
|
@ -443,7 +523,7 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
|||
consentScopeRepresentation.setId(clientScopeRepresentation.getId());
|
||||
|
||||
ConsentRepresentation requestedConsent = new ConsentRepresentation();
|
||||
requestedConsent.setScopes(Collections.singletonList(consentScopeRepresentation));
|
||||
requestedConsent.setGrantedScopes(Collections.singletonList(consentScopeRepresentation));
|
||||
|
||||
SimpleHttp.Response response = SimpleHttp
|
||||
.doPost(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||
|
@ -465,7 +545,7 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
|||
consentScopeRepresentation.setId(clientScopeRepresentation.getId());
|
||||
|
||||
ConsentRepresentation requestedConsent = new ConsentRepresentation();
|
||||
requestedConsent.setScopes(Collections.singletonList(consentScopeRepresentation));
|
||||
requestedConsent.setGrantedScopes(Collections.singletonList(consentScopeRepresentation));
|
||||
|
||||
ConsentRepresentation consentRepresentation = SimpleHttp
|
||||
.doPut(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||
|
@ -475,8 +555,8 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
|||
.asJson(ConsentRepresentation.class);
|
||||
assertTrue(consentRepresentation.getCreatedDate() > 0);
|
||||
assertTrue(consentRepresentation.getLastUpdatedDate() > 0);
|
||||
assertEquals(1, consentRepresentation.getScopes().size());
|
||||
assertEquals(consentScopeRepresentation.getId(), consentRepresentation.getScopes().get(0).getId());
|
||||
assertEquals(1, consentRepresentation.getGrantedScopes().size());
|
||||
assertEquals(consentScopeRepresentation.getId(), consentRepresentation.getGrantedScopes().get(0).getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -489,7 +569,7 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
|||
consentScopeRepresentation.setId(clientScopeRepresentation.getId());
|
||||
|
||||
ConsentRepresentation requestedConsent = new ConsentRepresentation();
|
||||
requestedConsent.setScopes(Collections.singletonList(consentScopeRepresentation));
|
||||
requestedConsent.setGrantedScopes(Collections.singletonList(consentScopeRepresentation));
|
||||
|
||||
ConsentRepresentation consentRepresentation = SimpleHttp
|
||||
.doPut(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||
|
@ -499,15 +579,15 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
|||
.asJson(ConsentRepresentation.class);
|
||||
assertTrue(consentRepresentation.getCreatedDate() > 0);
|
||||
assertTrue(consentRepresentation.getLastUpdatedDate() > 0);
|
||||
assertEquals(1, consentRepresentation.getScopes().size());
|
||||
assertEquals(consentScopeRepresentation.getId(), consentRepresentation.getScopes().get(0).getId());
|
||||
assertEquals(1, consentRepresentation.getGrantedScopes().size());
|
||||
assertEquals(consentScopeRepresentation.getId(), consentRepresentation.getGrantedScopes().get(0).getId());
|
||||
|
||||
clientScopeRepresentation = testRealm().clientScopes().findAll().get(1);
|
||||
consentScopeRepresentation = new ConsentScopeRepresentation();
|
||||
consentScopeRepresentation.setId(clientScopeRepresentation.getId());
|
||||
|
||||
requestedConsent = new ConsentRepresentation();
|
||||
requestedConsent.setScopes(Collections.singletonList(consentScopeRepresentation));
|
||||
requestedConsent.setGrantedScopes(Collections.singletonList(consentScopeRepresentation));
|
||||
|
||||
ConsentRepresentation consentRepresentation2 = SimpleHttp
|
||||
.doPut(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||
|
@ -519,8 +599,8 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
|||
assertEquals(consentRepresentation.getCreatedDate(), consentRepresentation2.getCreatedDate());
|
||||
assertTrue(consentRepresentation2.getLastUpdatedDate() > 0);
|
||||
assertTrue(consentRepresentation2.getLastUpdatedDate() > consentRepresentation.getLastUpdatedDate());
|
||||
assertEquals(1, consentRepresentation2.getScopes().size());
|
||||
assertEquals(consentScopeRepresentation.getId(), consentRepresentation2.getScopes().get(0).getId());
|
||||
assertEquals(1, consentRepresentation2.getGrantedScopes().size());
|
||||
assertEquals(consentScopeRepresentation.getId(), consentRepresentation2.getGrantedScopes().get(0).getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -533,7 +613,7 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
|||
consentScopeRepresentation.setId(clientScopeRepresentation.getId());
|
||||
|
||||
ConsentRepresentation requestedConsent = new ConsentRepresentation();
|
||||
requestedConsent.setScopes(Collections.singletonList(consentScopeRepresentation));
|
||||
requestedConsent.setGrantedScopes(Collections.singletonList(consentScopeRepresentation));
|
||||
|
||||
SimpleHttp.Response response = SimpleHttp
|
||||
.doPut(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||
|
@ -555,7 +635,7 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
|||
consentScopeRepresentation.setId(clientScopeRepresentation.getId());
|
||||
|
||||
ConsentRepresentation requestedConsent = new ConsentRepresentation();
|
||||
requestedConsent.setScopes(Collections.singletonList(consentScopeRepresentation));
|
||||
requestedConsent.setGrantedScopes(Collections.singletonList(consentScopeRepresentation));
|
||||
|
||||
SimpleHttp.Response response = SimpleHttp
|
||||
.doPut(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||
|
@ -577,7 +657,7 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
|||
consentScopeRepresentation.setId(clientScopeRepresentation.getId());
|
||||
|
||||
ConsentRepresentation requestedConsent = new ConsentRepresentation();
|
||||
requestedConsent.setScopes(Collections.singletonList(consentScopeRepresentation));
|
||||
requestedConsent.setGrantedScopes(Collections.singletonList(consentScopeRepresentation));
|
||||
|
||||
ConsentRepresentation consentRepresentation1 = SimpleHttp
|
||||
.doPost(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||
|
@ -587,8 +667,8 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
|||
.asJson(ConsentRepresentation.class);
|
||||
assertTrue(consentRepresentation1.getCreatedDate() > 0);
|
||||
assertTrue(consentRepresentation1.getLastUpdatedDate() > 0);
|
||||
assertEquals(1, consentRepresentation1.getScopes().size());
|
||||
assertEquals(consentScopeRepresentation.getId(), consentRepresentation1.getScopes().get(0).getId());
|
||||
assertEquals(1, consentRepresentation1.getGrantedScopes().size());
|
||||
assertEquals(consentScopeRepresentation.getId(), consentRepresentation1.getGrantedScopes().get(0).getId());
|
||||
|
||||
ConsentRepresentation consentRepresentation2 = SimpleHttp
|
||||
.doGet(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||
|
@ -597,7 +677,7 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
|||
.asJson(ConsentRepresentation.class);
|
||||
assertEquals(consentRepresentation1.getLastUpdatedDate(), consentRepresentation2.getLastUpdatedDate());
|
||||
assertEquals(consentRepresentation1.getCreatedDate(), consentRepresentation2.getCreatedDate());
|
||||
assertEquals(consentRepresentation1.getScopes().get(0).getId(), consentRepresentation2.getScopes().get(0).getId());
|
||||
assertEquals(consentRepresentation1.getGrantedScopes().get(0).getId(), consentRepresentation2.getGrantedScopes().get(0).getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -626,7 +706,7 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
|||
|
||||
@Test
|
||||
public void getConsentWithoutPermission() throws IOException {
|
||||
TokenUtil token = new TokenUtil("view-applications-access", "password");
|
||||
TokenUtil token = new TokenUtil("no-account-access", "password");
|
||||
String appId = "security-admin-console";
|
||||
SimpleHttp.Response response = SimpleHttp
|
||||
.doGet(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||
|
@ -646,7 +726,7 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
|||
consentScopeRepresentation.setId(clientScopeRepresentation.getId());
|
||||
|
||||
ConsentRepresentation requestedConsent = new ConsentRepresentation();
|
||||
requestedConsent.setScopes(Collections.singletonList(consentScopeRepresentation));
|
||||
requestedConsent.setGrantedScopes(Collections.singletonList(consentScopeRepresentation));
|
||||
|
||||
ConsentRepresentation consentRepresentation = SimpleHttp
|
||||
.doPost(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||
|
@ -656,8 +736,8 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
|||
.asJson(ConsentRepresentation.class);
|
||||
assertTrue(consentRepresentation.getCreatedDate() > 0);
|
||||
assertTrue(consentRepresentation.getLastUpdatedDate() > 0);
|
||||
assertEquals(1, consentRepresentation.getScopes().size());
|
||||
assertEquals(consentScopeRepresentation.getId(), consentRepresentation.getScopes().get(0).getId());
|
||||
assertEquals(1, consentRepresentation.getGrantedScopes().size());
|
||||
assertEquals(consentScopeRepresentation.getId(), consentRepresentation.getGrantedScopes().get(0).getId());
|
||||
|
||||
SimpleHttp.Response response = SimpleHttp
|
||||
.doDelete(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||
|
@ -686,7 +766,6 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
|||
assertEquals(404, response.getStatus());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void deleteConsentWithoutPermission() throws IOException {
|
||||
TokenUtil token = new TokenUtil("view-consent-access", "password");
|
||||
|
|
|
@ -214,6 +214,7 @@
|
|||
},
|
||||
{
|
||||
"clientId" : "third-party",
|
||||
"description" : "A third party application",
|
||||
"enabled": true,
|
||||
"consentRequired": true,
|
||||
|
||||
|
|
Loading…
Reference in a new issue