[KEYCLOAK-10653] Manage Consent via the Account API
This commit is contained in:
parent
3f2a38936c
commit
0ce10a3249
7 changed files with 839 additions and 4 deletions
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2019 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.representations.account;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ConsentRepresentation {
|
||||||
|
|
||||||
|
private List<ConsentScopeRepresentation> scopes;
|
||||||
|
|
||||||
|
private Long createdDate;
|
||||||
|
|
||||||
|
private Long lastUpdatedDate;
|
||||||
|
|
||||||
|
public ConsentRepresentation() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConsentRepresentation(List<ConsentScopeRepresentation> scopes, Long createdDate, Long lastUpdatedDate) {
|
||||||
|
this.scopes = scopes;
|
||||||
|
this.createdDate = createdDate;
|
||||||
|
this.lastUpdatedDate = lastUpdatedDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ConsentScopeRepresentation> getScopes() {
|
||||||
|
return scopes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScopes(List<ConsentScopeRepresentation> scopes) {
|
||||||
|
this.scopes = scopes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getCreatedDate() {
|
||||||
|
return createdDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreatedDate(Long createdDate) {
|
||||||
|
this.createdDate = createdDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getLastUpdatedDate() {
|
||||||
|
return lastUpdatedDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastUpdatedDate(Long lastUpdatedDate) {
|
||||||
|
this.lastUpdatedDate = lastUpdatedDate;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2019 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.representations.account;
|
||||||
|
|
||||||
|
public class ConsentScopeRepresentation {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private String displayTest;
|
||||||
|
|
||||||
|
public ConsentScopeRepresentation() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConsentScopeRepresentation(String id, String name, String displayTest) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.displayTest = displayTest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDisplayTest() {
|
||||||
|
return displayTest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDisplayTest(String displayTest) {
|
||||||
|
this.displayTest = displayTest;
|
||||||
|
}
|
||||||
|
}
|
|
@ -67,6 +67,10 @@ public enum EventType {
|
||||||
REMOVE_TOTP(true),
|
REMOVE_TOTP(true),
|
||||||
REMOVE_TOTP_ERROR(true),
|
REMOVE_TOTP_ERROR(true),
|
||||||
|
|
||||||
|
GRANT_CONSENT(true),
|
||||||
|
GRANT_CONSENT_ERROR(true),
|
||||||
|
UPDATE_CONSENT(true),
|
||||||
|
UPDATE_CONSENT_ERROR(true),
|
||||||
REVOKE_GRANT(true),
|
REVOKE_GRANT(true),
|
||||||
REVOKE_GRANT_ERROR(true),
|
REVOKE_GRANT_ERROR(true),
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,9 @@ public interface AccountRoles {
|
||||||
String MANAGE_ACCOUNT = "manage-account";
|
String MANAGE_ACCOUNT = "manage-account";
|
||||||
String INITIATE_ACTION = "initiate-action";
|
String INITIATE_ACTION = "initiate-action";
|
||||||
String MANAGE_ACCOUNT_LINKS = "manage-account-links";
|
String MANAGE_ACCOUNT_LINKS = "manage-account-links";
|
||||||
|
String VIEW_APPLICATIONS = "view-applications";
|
||||||
|
String VIEW_CONSENT = "view-consent";
|
||||||
|
String MANAGE_CONSENT = "manage-consent";
|
||||||
|
|
||||||
String[] ALL = {VIEW_PROFILE, MANAGE_ACCOUNT};
|
String[] ALL = {VIEW_PROFILE, MANAGE_ACCOUNT};
|
||||||
|
|
||||||
|
|
|
@ -19,17 +19,22 @@ package org.keycloak.services.resources.account;
|
||||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.jboss.resteasy.spi.HttpRequest;
|
||||||
import org.keycloak.common.ClientConnection;
|
import org.keycloak.common.ClientConnection;
|
||||||
|
import org.keycloak.common.Profile;
|
||||||
import org.keycloak.events.Details;
|
import org.keycloak.events.Details;
|
||||||
import org.keycloak.events.EventBuilder;
|
import org.keycloak.events.EventBuilder;
|
||||||
import org.keycloak.events.EventStoreProvider;
|
import org.keycloak.events.EventStoreProvider;
|
||||||
import org.keycloak.events.EventType;
|
import org.keycloak.events.EventType;
|
||||||
import org.keycloak.models.AccountRoles;
|
import org.keycloak.models.AccountRoles;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
|
import org.keycloak.models.ClientScopeModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.UserConsentModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.UserSessionModel;
|
import org.keycloak.models.UserSessionModel;
|
||||||
import org.keycloak.representations.account.ClientRepresentation;
|
import org.keycloak.representations.account.ClientRepresentation;
|
||||||
|
import org.keycloak.representations.account.ConsentRepresentation;
|
||||||
|
import org.keycloak.representations.account.ConsentScopeRepresentation;
|
||||||
import org.keycloak.representations.account.SessionRepresentation;
|
import org.keycloak.representations.account.SessionRepresentation;
|
||||||
import org.keycloak.representations.account.UserRepresentation;
|
import org.keycloak.representations.account.UserRepresentation;
|
||||||
import org.keycloak.services.ErrorResponse;
|
import org.keycloak.services.ErrorResponse;
|
||||||
|
@ -39,16 +44,30 @@ import org.keycloak.services.messages.Messages;
|
||||||
import org.keycloak.services.resources.Cors;
|
import org.keycloak.services.resources.Cors;
|
||||||
import org.keycloak.services.resources.account.resources.ResourcesService;
|
import org.keycloak.services.resources.account.resources.ResourcesService;
|
||||||
import org.keycloak.storage.ReadOnlyException;
|
import org.keycloak.storage.ReadOnlyException;
|
||||||
|
import org.keycloak.theme.Theme;
|
||||||
|
|
||||||
import javax.ws.rs.*;
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.NotFoundException;
|
||||||
|
import javax.ws.rs.OPTIONS;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.PUT;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.QueryParam;
|
||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.HttpHeaders;
|
import javax.ws.rs.core.HttpHeaders;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.keycloak.common.Profile;
|
import java.util.Properties;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
|
@ -70,6 +89,7 @@ public class AccountRestService {
|
||||||
|
|
||||||
private final RealmModel realm;
|
private final RealmModel realm;
|
||||||
private final UserModel user;
|
private final UserModel user;
|
||||||
|
private final Locale locale;
|
||||||
|
|
||||||
public AccountRestService(KeycloakSession session, Auth auth, ClientModel client, EventBuilder event) {
|
public AccountRestService(KeycloakSession session, Auth auth, ClientModel client, EventBuilder event) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
|
@ -78,6 +98,7 @@ public class AccountRestService {
|
||||||
this.user = auth.getUser();
|
this.user = auth.getUser();
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.event = event;
|
this.event = event;
|
||||||
|
this.locale = session.getContext().resolveLocale(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init() {
|
public void init() {
|
||||||
|
@ -296,8 +317,231 @@ public class AccountRestService {
|
||||||
return new ResourcesService(session, user, auth, request);
|
return new ResourcesService(session, user, auth, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Federated identities
|
// TODO Federated identities
|
||||||
// TODO Applications
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @param clientId client id to search for
|
||||||
|
* @return application with the provided id
|
||||||
|
*/
|
||||||
|
@Path("/applications/{clientId}")
|
||||||
|
@GET
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public Response getApplication(final @PathParam("clientId") String clientId) {
|
||||||
|
checkAccountApiEnabled();
|
||||||
|
auth.require(AccountRoles.VIEW_APPLICATIONS);
|
||||||
|
ClientModel client = realm.getClientByClientId(clientId);
|
||||||
|
if (client == 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ClientRepresentation modelToRepresentation(ClientModel model) {
|
||||||
|
ClientRepresentation representation = new ClientRepresentation();
|
||||||
|
representation.setClientId(model.getClientId());
|
||||||
|
representation.setClientName(getTranslationOrDefault(model.getName()));
|
||||||
|
return representation;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ConsentRepresentation modelToRepresentation(UserConsentModel model) {
|
||||||
|
List<ConsentScopeRepresentation> scopes = model.getGrantedClientScopes().stream()
|
||||||
|
.map(m -> new ConsentScopeRepresentation(m.getId(), m.getName(), getTranslationOrDefault(m.getConsentScreenText())))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
return new ConsentRepresentation(scopes, 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);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Properties messages = session.theme().getTheme(Theme.Type.ACCOUNT).getMessages(locale);
|
||||||
|
return messages.getProperty(key, defaultValue);
|
||||||
|
} catch (IOException e) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the consent for the client with the given client id.
|
||||||
|
*
|
||||||
|
* @param clientId client id to return the consent for
|
||||||
|
* @return consent of the client
|
||||||
|
*/
|
||||||
|
@Path("/applications/{clientId}/consent")
|
||||||
|
@GET
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public Response getConsent(final @PathParam("clientId") String clientId) {
|
||||||
|
checkAccountApiEnabled();
|
||||||
|
auth.requireOneOf(AccountRoles.VIEW_CONSENT, AccountRoles.MANAGE_CONSENT);
|
||||||
|
|
||||||
|
ClientModel client = realm.getClientByClientId(clientId);
|
||||||
|
if (client == null) {
|
||||||
|
return Cors.add(request, Response.status(Response.Status.NOT_FOUND).entity("No client with clientId: " + clientId + " found.")).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
UserConsentModel consent = session.users().getConsentByClient(realm, user.getId(), client.getId());
|
||||||
|
if (consent == null) {
|
||||||
|
return Cors.add(request, Response.noContent()).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Cors.add(request, Response.ok(modelToRepresentation(consent))).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the consent for the client with the given client id.
|
||||||
|
*
|
||||||
|
* @param clientId client id to delete a consent for
|
||||||
|
* @return returns 202 if deleted
|
||||||
|
*/
|
||||||
|
@Path("/applications/{clientId}/consent")
|
||||||
|
@DELETE
|
||||||
|
public Response revokeConsent(final @PathParam("clientId") String clientId) {
|
||||||
|
checkAccountApiEnabled();
|
||||||
|
auth.require(AccountRoles.MANAGE_CONSENT);
|
||||||
|
|
||||||
|
event.event(EventType.REVOKE_GRANT);
|
||||||
|
ClientModel client = realm.getClientByClientId(clientId);
|
||||||
|
if (client == null) {
|
||||||
|
event.event(EventType.REVOKE_GRANT_ERROR);
|
||||||
|
String msg = String.format("No client with clientId: %s found.", clientId);
|
||||||
|
event.error(msg);
|
||||||
|
return Cors.add(request, Response.status(Response.Status.NOT_FOUND).entity(msg)).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
session.users().revokeConsentForClient(realm, user.getId(), client.getId());
|
||||||
|
event.success();
|
||||||
|
|
||||||
|
return Cors.add(request, Response.accepted()).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates or updates the consent of the given, requested consent for
|
||||||
|
* the client with the given client id. Returns the appropriate REST response.
|
||||||
|
*
|
||||||
|
* @param clientId client id to set a consent for
|
||||||
|
* @param consent requested consent for the client
|
||||||
|
* @return the created or updated consent
|
||||||
|
*/
|
||||||
|
@Path("/applications/{clientId}/consent")
|
||||||
|
@POST
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public Response grantConsent(final @PathParam("clientId") String clientId,
|
||||||
|
final ConsentRepresentation consent) {
|
||||||
|
return upsert(clientId, consent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates or updates the consent of the given, requested consent for
|
||||||
|
* the client with the given client id. Returns the appropriate REST response.
|
||||||
|
*
|
||||||
|
* @param clientId client id to set a consent for
|
||||||
|
* @param consent requested consent for the client
|
||||||
|
* @return the created or updated consent
|
||||||
|
*/
|
||||||
|
@Path("/applications/{clientId}/consent")
|
||||||
|
@PUT
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public Response updateConsent(final @PathParam("clientId") String clientId,
|
||||||
|
final ConsentRepresentation consent) {
|
||||||
|
return upsert(clientId, consent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates or updates the consent of the given, requested consent for
|
||||||
|
* the client with the given client id. Returns the appropriate REST response.
|
||||||
|
*
|
||||||
|
* @param clientId client id to set a consent for
|
||||||
|
* @param consent requested consent for the client
|
||||||
|
* @return response to return to the caller
|
||||||
|
*/
|
||||||
|
private Response upsert(String clientId, ConsentRepresentation consent) {
|
||||||
|
checkAccountApiEnabled();
|
||||||
|
auth.require(AccountRoles.MANAGE_CONSENT);
|
||||||
|
|
||||||
|
event.event(EventType.GRANT_CONSENT);
|
||||||
|
ClientModel client = realm.getClientByClientId(clientId);
|
||||||
|
if (client == null) {
|
||||||
|
event.event(EventType.GRANT_CONSENT_ERROR);
|
||||||
|
String msg = String.format("No client with clientId: %s found.", clientId);
|
||||||
|
event.error(msg);
|
||||||
|
return Cors.add(request, Response.status(Response.Status.NOT_FOUND).entity(msg)).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
UserConsentModel grantedConsent = createConsent(client, consent);
|
||||||
|
if (session.users().getConsentByClient(realm, user.getId(), client.getId()) == null) {
|
||||||
|
session.users().addConsent(realm, user.getId(), grantedConsent);
|
||||||
|
} else {
|
||||||
|
session.users().updateConsent(realm, user.getId(), grantedConsent);
|
||||||
|
}
|
||||||
|
event.success();
|
||||||
|
grantedConsent = session.users().getConsentByClient(realm, user.getId(), client.getId());
|
||||||
|
return Cors.add(request, Response.ok(modelToRepresentation(grantedConsent))).build();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
return Cors.add(request, Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage())).build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new consent model object from the requested consent object
|
||||||
|
* for the given client model.
|
||||||
|
*
|
||||||
|
* @param client client to create a consent for
|
||||||
|
* @param requested list of client scopes that the new consent should contain
|
||||||
|
* @return newly created consent model
|
||||||
|
* @throws IllegalArgumentException throws an exception if the scope id is not available
|
||||||
|
*/
|
||||||
|
private UserConsentModel createConsent(ClientModel client, ConsentRepresentation requested) throws IllegalArgumentException {
|
||||||
|
UserConsentModel consent = new UserConsentModel(client);
|
||||||
|
Map<String, ClientScopeModel> availableGrants = realm.getClientScopes().stream().collect(Collectors.toMap(ClientScopeModel::getId, s -> s));
|
||||||
|
|
||||||
|
if (client.isConsentRequired()) {
|
||||||
|
availableGrants.put(client.getId(), client);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ConsentScopeRepresentation scopeRepresentation : requested.getScopes()) {
|
||||||
|
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());
|
||||||
|
event.error(msg);
|
||||||
|
throw new IllegalArgumentException(msg);
|
||||||
|
} else {
|
||||||
|
consent.addGrantedClientScope(scopeModel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return consent;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO Logs
|
// TODO Logs
|
||||||
|
|
||||||
private static void checkAccountApiEnabled() {
|
private static void checkAccountApiEnabled() {
|
||||||
|
|
|
@ -87,6 +87,9 @@ public abstract class AbstractRestServiceTest extends AbstractTestRealmKeycloakT
|
||||||
public void configureTestRealm(RealmRepresentation testRealm) {
|
public void configureTestRealm(RealmRepresentation testRealm) {
|
||||||
testRealm.getUsers().add(UserBuilder.create().username("no-account-access").password("password").build());
|
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-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-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());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getAccountUrl(String resource) {
|
protected String getAccountUrl(String resource) {
|
||||||
|
|
|
@ -19,8 +19,12 @@ package org.keycloak.testsuite.account;
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.keycloak.broker.provider.util.SimpleHttp;
|
import org.keycloak.broker.provider.util.SimpleHttp;
|
||||||
|
import org.keycloak.representations.account.ClientRepresentation;
|
||||||
|
import org.keycloak.representations.account.ConsentRepresentation;
|
||||||
|
import org.keycloak.representations.account.ConsentScopeRepresentation;
|
||||||
import org.keycloak.representations.account.SessionRepresentation;
|
import org.keycloak.representations.account.SessionRepresentation;
|
||||||
import org.keycloak.representations.account.UserRepresentation;
|
import org.keycloak.representations.account.UserRepresentation;
|
||||||
|
import org.keycloak.representations.idm.ClientScopeRepresentation;
|
||||||
import org.keycloak.representations.idm.ErrorRepresentation;
|
import org.keycloak.representations.idm.ErrorRepresentation;
|
||||||
import org.keycloak.representations.idm.RealmRepresentation;
|
import org.keycloak.representations.idm.RealmRepresentation;
|
||||||
import org.keycloak.services.messages.Messages;
|
import org.keycloak.services.messages.Messages;
|
||||||
|
@ -333,4 +337,459 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
||||||
sessions = SimpleHttp.doGet(getAccountUrl("sessions"), httpClient).auth(tokenUtil.getToken()).asJson(new TypeReference<List<SessionRepresentation>>() {});
|
sessions = SimpleHttp.doGet(getAccountUrl("sessions"), httpClient).auth(tokenUtil.getToken()).asJson(new TypeReference<List<SessionRepresentation>>() {});
|
||||||
assertEquals(1, sessions.size());
|
assertEquals(1, sessions.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void listApplications() throws IOException {
|
||||||
|
assumeFeatureEnabled(ACCOUNT_API);
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void listApplicationsWithoutPermission() throws IOException {
|
||||||
|
assumeFeatureEnabled(ACCOUNT_API);
|
||||||
|
|
||||||
|
TokenUtil token = new TokenUtil("view-account-access", "password");
|
||||||
|
SimpleHttp.Response response = SimpleHttp
|
||||||
|
.doGet(getAccountUrl("applications"), httpClient)
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.auth(token.getToken())
|
||||||
|
.asResponse();
|
||||||
|
assertEquals(403, response.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getWebConsoleApplication() throws IOException {
|
||||||
|
assumeFeatureEnabled(ACCOUNT_API);
|
||||||
|
|
||||||
|
TokenUtil token = new TokenUtil("view-applications-access", "password");
|
||||||
|
String appId = "security-admin-console";
|
||||||
|
ClientRepresentation webConsole = SimpleHttp
|
||||||
|
.doGet(getAccountUrl("applications/" + appId), httpClient)
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.auth(token.getToken())
|
||||||
|
.asJson(ClientRepresentation.class);
|
||||||
|
assertEquals(appId, webConsole.getClientId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getWebConsoleApplicationWithoutPermission() throws IOException {
|
||||||
|
assumeFeatureEnabled(ACCOUNT_API);
|
||||||
|
|
||||||
|
TokenUtil token = new TokenUtil("view-account-access", "password");
|
||||||
|
String appId = "security-admin-console";
|
||||||
|
SimpleHttp.Response response = SimpleHttp
|
||||||
|
.doGet(getAccountUrl("applications/" + appId), httpClient)
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.auth(token.getToken())
|
||||||
|
.asResponse();
|
||||||
|
assertEquals(403, response.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getNotExistingApplication() throws IOException {
|
||||||
|
assumeFeatureEnabled(ACCOUNT_API);
|
||||||
|
|
||||||
|
TokenUtil token = new TokenUtil("view-applications-access", "password");
|
||||||
|
String appId = "not-existing";
|
||||||
|
SimpleHttp.Response response = SimpleHttp
|
||||||
|
.doGet(getAccountUrl("applications/" + appId), httpClient)
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.auth(token.getToken())
|
||||||
|
.asResponse();
|
||||||
|
assertEquals(404, response.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createConsentForClient() throws IOException {
|
||||||
|
assumeFeatureEnabled(ACCOUNT_API);
|
||||||
|
|
||||||
|
TokenUtil token = new TokenUtil("manage-consent-access", "password");
|
||||||
|
String appId = "security-admin-console";
|
||||||
|
|
||||||
|
ClientScopeRepresentation clientScopeRepresentation = testRealm().clientScopes().findAll().get(0);
|
||||||
|
ConsentScopeRepresentation consentScopeRepresentation = new ConsentScopeRepresentation();
|
||||||
|
consentScopeRepresentation.setId(clientScopeRepresentation.getId());
|
||||||
|
|
||||||
|
ConsentRepresentation requestedConsent = new ConsentRepresentation();
|
||||||
|
requestedConsent.setScopes(Collections.singletonList(consentScopeRepresentation));
|
||||||
|
|
||||||
|
ConsentRepresentation consentRepresentation = SimpleHttp
|
||||||
|
.doPost(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.json(requestedConsent)
|
||||||
|
.auth(token.getToken())
|
||||||
|
.asJson(ConsentRepresentation.class);
|
||||||
|
assertTrue(consentRepresentation.getCreatedDate() > 0);
|
||||||
|
assertTrue(consentRepresentation.getLastUpdatedDate() > 0);
|
||||||
|
assertEquals(1, consentRepresentation.getScopes().size());
|
||||||
|
assertEquals(consentScopeRepresentation.getId(), consentRepresentation.getScopes().get(0).getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void updateConsentForClient() throws IOException {
|
||||||
|
assumeFeatureEnabled(ACCOUNT_API);
|
||||||
|
|
||||||
|
TokenUtil token = new TokenUtil("manage-consent-access", "password");
|
||||||
|
String appId = "security-admin-console";
|
||||||
|
|
||||||
|
ClientScopeRepresentation clientScopeRepresentation = testRealm().clientScopes().findAll().get(0);
|
||||||
|
ConsentScopeRepresentation consentScopeRepresentation = new ConsentScopeRepresentation();
|
||||||
|
consentScopeRepresentation.setId(clientScopeRepresentation.getId());
|
||||||
|
|
||||||
|
ConsentRepresentation requestedConsent = new ConsentRepresentation();
|
||||||
|
requestedConsent.setScopes(Collections.singletonList(consentScopeRepresentation));
|
||||||
|
|
||||||
|
ConsentRepresentation consentRepresentation = SimpleHttp
|
||||||
|
.doPost(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.json(requestedConsent)
|
||||||
|
.auth(token.getToken())
|
||||||
|
.asJson(ConsentRepresentation.class);
|
||||||
|
assertTrue(consentRepresentation.getCreatedDate() > 0);
|
||||||
|
assertTrue(consentRepresentation.getLastUpdatedDate() > 0);
|
||||||
|
assertEquals(1, consentRepresentation.getScopes().size());
|
||||||
|
assertEquals(consentScopeRepresentation.getId(), consentRepresentation.getScopes().get(0).getId());
|
||||||
|
|
||||||
|
clientScopeRepresentation = testRealm().clientScopes().findAll().get(1);
|
||||||
|
consentScopeRepresentation = new ConsentScopeRepresentation();
|
||||||
|
consentScopeRepresentation.setId(clientScopeRepresentation.getId());
|
||||||
|
|
||||||
|
requestedConsent = new ConsentRepresentation();
|
||||||
|
requestedConsent.setScopes(Collections.singletonList(consentScopeRepresentation));
|
||||||
|
|
||||||
|
ConsentRepresentation consentRepresentation2 = SimpleHttp
|
||||||
|
.doPost(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.json(requestedConsent)
|
||||||
|
.auth(token.getToken())
|
||||||
|
.asJson(ConsentRepresentation.class);
|
||||||
|
assertTrue(consentRepresentation2.getCreatedDate() > 0);
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createConsentForNotExistingClient() throws IOException {
|
||||||
|
assumeFeatureEnabled(ACCOUNT_API);
|
||||||
|
|
||||||
|
TokenUtil token = new TokenUtil("manage-consent-access", "password");
|
||||||
|
String appId = "not-existing";
|
||||||
|
|
||||||
|
ClientScopeRepresentation clientScopeRepresentation = testRealm().clientScopes().findAll().get(0);
|
||||||
|
ConsentScopeRepresentation consentScopeRepresentation = new ConsentScopeRepresentation();
|
||||||
|
consentScopeRepresentation.setId(clientScopeRepresentation.getId());
|
||||||
|
|
||||||
|
ConsentRepresentation requestedConsent = new ConsentRepresentation();
|
||||||
|
requestedConsent.setScopes(Collections.singletonList(consentScopeRepresentation));
|
||||||
|
|
||||||
|
SimpleHttp.Response response = SimpleHttp
|
||||||
|
.doPost(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.json(requestedConsent)
|
||||||
|
.auth(token.getToken())
|
||||||
|
.asResponse();
|
||||||
|
|
||||||
|
assertEquals(404, response.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createConsentForClientWithoutPermission() throws IOException {
|
||||||
|
assumeFeatureEnabled(ACCOUNT_API);
|
||||||
|
|
||||||
|
TokenUtil token = new TokenUtil("view-consent-access", "password");
|
||||||
|
String appId = "security-admin-console";
|
||||||
|
|
||||||
|
ClientScopeRepresentation clientScopeRepresentation = testRealm().clientScopes().findAll().get(0);
|
||||||
|
ConsentScopeRepresentation consentScopeRepresentation = new ConsentScopeRepresentation();
|
||||||
|
consentScopeRepresentation.setId(clientScopeRepresentation.getId());
|
||||||
|
|
||||||
|
ConsentRepresentation requestedConsent = new ConsentRepresentation();
|
||||||
|
requestedConsent.setScopes(Collections.singletonList(consentScopeRepresentation));
|
||||||
|
|
||||||
|
SimpleHttp.Response response = SimpleHttp
|
||||||
|
.doPost(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.json(requestedConsent)
|
||||||
|
.auth(token.getToken())
|
||||||
|
.asResponse();
|
||||||
|
|
||||||
|
assertEquals(403, response.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createConsentForClientWithPut() throws IOException {
|
||||||
|
assumeFeatureEnabled(ACCOUNT_API);
|
||||||
|
|
||||||
|
TokenUtil token = new TokenUtil("manage-consent-access", "password");
|
||||||
|
String appId = "security-admin-console";
|
||||||
|
|
||||||
|
ClientScopeRepresentation clientScopeRepresentation = testRealm().clientScopes().findAll().get(0);
|
||||||
|
ConsentScopeRepresentation consentScopeRepresentation = new ConsentScopeRepresentation();
|
||||||
|
consentScopeRepresentation.setId(clientScopeRepresentation.getId());
|
||||||
|
|
||||||
|
ConsentRepresentation requestedConsent = new ConsentRepresentation();
|
||||||
|
requestedConsent.setScopes(Collections.singletonList(consentScopeRepresentation));
|
||||||
|
|
||||||
|
ConsentRepresentation consentRepresentation = SimpleHttp
|
||||||
|
.doPut(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.json(requestedConsent)
|
||||||
|
.auth(token.getToken())
|
||||||
|
.asJson(ConsentRepresentation.class);
|
||||||
|
assertTrue(consentRepresentation.getCreatedDate() > 0);
|
||||||
|
assertTrue(consentRepresentation.getLastUpdatedDate() > 0);
|
||||||
|
assertEquals(1, consentRepresentation.getScopes().size());
|
||||||
|
assertEquals(consentScopeRepresentation.getId(), consentRepresentation.getScopes().get(0).getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void updateConsentForClientWithPut() throws IOException {
|
||||||
|
assumeFeatureEnabled(ACCOUNT_API);
|
||||||
|
|
||||||
|
TokenUtil token = new TokenUtil("manage-consent-access", "password");
|
||||||
|
String appId = "security-admin-console";
|
||||||
|
|
||||||
|
ClientScopeRepresentation clientScopeRepresentation = testRealm().clientScopes().findAll().get(0);
|
||||||
|
ConsentScopeRepresentation consentScopeRepresentation = new ConsentScopeRepresentation();
|
||||||
|
consentScopeRepresentation.setId(clientScopeRepresentation.getId());
|
||||||
|
|
||||||
|
ConsentRepresentation requestedConsent = new ConsentRepresentation();
|
||||||
|
requestedConsent.setScopes(Collections.singletonList(consentScopeRepresentation));
|
||||||
|
|
||||||
|
ConsentRepresentation consentRepresentation = SimpleHttp
|
||||||
|
.doPut(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.json(requestedConsent)
|
||||||
|
.auth(token.getToken())
|
||||||
|
.asJson(ConsentRepresentation.class);
|
||||||
|
assertTrue(consentRepresentation.getCreatedDate() > 0);
|
||||||
|
assertTrue(consentRepresentation.getLastUpdatedDate() > 0);
|
||||||
|
assertEquals(1, consentRepresentation.getScopes().size());
|
||||||
|
assertEquals(consentScopeRepresentation.getId(), consentRepresentation.getScopes().get(0).getId());
|
||||||
|
|
||||||
|
clientScopeRepresentation = testRealm().clientScopes().findAll().get(1);
|
||||||
|
consentScopeRepresentation = new ConsentScopeRepresentation();
|
||||||
|
consentScopeRepresentation.setId(clientScopeRepresentation.getId());
|
||||||
|
|
||||||
|
requestedConsent = new ConsentRepresentation();
|
||||||
|
requestedConsent.setScopes(Collections.singletonList(consentScopeRepresentation));
|
||||||
|
|
||||||
|
ConsentRepresentation consentRepresentation2 = SimpleHttp
|
||||||
|
.doPut(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.json(requestedConsent)
|
||||||
|
.auth(token.getToken())
|
||||||
|
.asJson(ConsentRepresentation.class);
|
||||||
|
assertTrue(consentRepresentation2.getCreatedDate() > 0);
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createConsentForNotExistingClientWithPut() throws IOException {
|
||||||
|
assumeFeatureEnabled(ACCOUNT_API);
|
||||||
|
|
||||||
|
TokenUtil token = new TokenUtil("manage-consent-access", "password");
|
||||||
|
String appId = "not-existing";
|
||||||
|
|
||||||
|
ClientScopeRepresentation clientScopeRepresentation = testRealm().clientScopes().findAll().get(0);
|
||||||
|
ConsentScopeRepresentation consentScopeRepresentation = new ConsentScopeRepresentation();
|
||||||
|
consentScopeRepresentation.setId(clientScopeRepresentation.getId());
|
||||||
|
|
||||||
|
ConsentRepresentation requestedConsent = new ConsentRepresentation();
|
||||||
|
requestedConsent.setScopes(Collections.singletonList(consentScopeRepresentation));
|
||||||
|
|
||||||
|
SimpleHttp.Response response = SimpleHttp
|
||||||
|
.doPut(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.json(requestedConsent)
|
||||||
|
.auth(token.getToken())
|
||||||
|
.asResponse();
|
||||||
|
|
||||||
|
assertEquals(404, response.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createConsentForClientWithoutPermissionWithPut() throws IOException {
|
||||||
|
assumeFeatureEnabled(ACCOUNT_API);
|
||||||
|
|
||||||
|
TokenUtil token = new TokenUtil("view-consent-access", "password");
|
||||||
|
String appId = "security-admin-console";
|
||||||
|
|
||||||
|
ClientScopeRepresentation clientScopeRepresentation = testRealm().clientScopes().findAll().get(0);
|
||||||
|
ConsentScopeRepresentation consentScopeRepresentation = new ConsentScopeRepresentation();
|
||||||
|
consentScopeRepresentation.setId(clientScopeRepresentation.getId());
|
||||||
|
|
||||||
|
ConsentRepresentation requestedConsent = new ConsentRepresentation();
|
||||||
|
requestedConsent.setScopes(Collections.singletonList(consentScopeRepresentation));
|
||||||
|
|
||||||
|
SimpleHttp.Response response = SimpleHttp
|
||||||
|
.doPut(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.json(requestedConsent)
|
||||||
|
.auth(token.getToken())
|
||||||
|
.asResponse();
|
||||||
|
|
||||||
|
assertEquals(403, response.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getConsentForClient() throws IOException {
|
||||||
|
assumeFeatureEnabled(ACCOUNT_API);
|
||||||
|
|
||||||
|
TokenUtil token = new TokenUtil("manage-consent-access", "password");
|
||||||
|
String appId = "security-admin-console";
|
||||||
|
|
||||||
|
ClientScopeRepresentation clientScopeRepresentation = testRealm().clientScopes().findAll().get(0);
|
||||||
|
ConsentScopeRepresentation consentScopeRepresentation = new ConsentScopeRepresentation();
|
||||||
|
consentScopeRepresentation.setId(clientScopeRepresentation.getId());
|
||||||
|
|
||||||
|
ConsentRepresentation requestedConsent = new ConsentRepresentation();
|
||||||
|
requestedConsent.setScopes(Collections.singletonList(consentScopeRepresentation));
|
||||||
|
|
||||||
|
ConsentRepresentation consentRepresentation1 = SimpleHttp
|
||||||
|
.doPost(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.json(requestedConsent)
|
||||||
|
.auth(token.getToken())
|
||||||
|
.asJson(ConsentRepresentation.class);
|
||||||
|
assertTrue(consentRepresentation1.getCreatedDate() > 0);
|
||||||
|
assertTrue(consentRepresentation1.getLastUpdatedDate() > 0);
|
||||||
|
assertEquals(1, consentRepresentation1.getScopes().size());
|
||||||
|
assertEquals(consentScopeRepresentation.getId(), consentRepresentation1.getScopes().get(0).getId());
|
||||||
|
|
||||||
|
ConsentRepresentation consentRepresentation2 = SimpleHttp
|
||||||
|
.doGet(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.auth(token.getToken())
|
||||||
|
.asJson(ConsentRepresentation.class);
|
||||||
|
assertEquals(consentRepresentation1.getLastUpdatedDate(), consentRepresentation2.getLastUpdatedDate());
|
||||||
|
assertEquals(consentRepresentation1.getCreatedDate(), consentRepresentation2.getCreatedDate());
|
||||||
|
assertEquals(consentRepresentation1.getScopes().get(0).getId(), consentRepresentation2.getScopes().get(0).getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getConsentForNotExistingClient() throws IOException {
|
||||||
|
assumeFeatureEnabled(ACCOUNT_API);
|
||||||
|
|
||||||
|
TokenUtil token = new TokenUtil("view-consent-access", "password");
|
||||||
|
String appId = "not-existing";
|
||||||
|
SimpleHttp.Response response = SimpleHttp
|
||||||
|
.doGet(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.auth(token.getToken())
|
||||||
|
.asResponse();
|
||||||
|
assertEquals(404, response.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getNotExistingConsentForClient() throws IOException {
|
||||||
|
assumeFeatureEnabled(ACCOUNT_API);
|
||||||
|
|
||||||
|
TokenUtil token = new TokenUtil("view-consent-access", "password");
|
||||||
|
String appId = "security-admin-console";
|
||||||
|
SimpleHttp.Response response = SimpleHttp
|
||||||
|
.doGet(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.auth(token.getToken())
|
||||||
|
.asResponse();
|
||||||
|
assertEquals(204, response.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getConsentWithoutPermission() throws IOException {
|
||||||
|
assumeFeatureEnabled(ACCOUNT_API);
|
||||||
|
|
||||||
|
TokenUtil token = new TokenUtil("view-applications-access", "password");
|
||||||
|
String appId = "security-admin-console";
|
||||||
|
SimpleHttp.Response response = SimpleHttp
|
||||||
|
.doGet(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.auth(token.getToken())
|
||||||
|
.asResponse();
|
||||||
|
assertEquals(403, response.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void deleteConsentForClient() throws IOException {
|
||||||
|
assumeFeatureEnabled(ACCOUNT_API);
|
||||||
|
|
||||||
|
TokenUtil token = new TokenUtil("manage-consent-access", "password");
|
||||||
|
String appId = "security-admin-console";
|
||||||
|
|
||||||
|
ClientScopeRepresentation clientScopeRepresentation = testRealm().clientScopes().findAll().get(0);
|
||||||
|
ConsentScopeRepresentation consentScopeRepresentation = new ConsentScopeRepresentation();
|
||||||
|
consentScopeRepresentation.setId(clientScopeRepresentation.getId());
|
||||||
|
|
||||||
|
ConsentRepresentation requestedConsent = new ConsentRepresentation();
|
||||||
|
requestedConsent.setScopes(Collections.singletonList(consentScopeRepresentation));
|
||||||
|
|
||||||
|
ConsentRepresentation consentRepresentation = SimpleHttp
|
||||||
|
.doPost(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.json(requestedConsent)
|
||||||
|
.auth(token.getToken())
|
||||||
|
.asJson(ConsentRepresentation.class);
|
||||||
|
assertTrue(consentRepresentation.getCreatedDate() > 0);
|
||||||
|
assertTrue(consentRepresentation.getLastUpdatedDate() > 0);
|
||||||
|
assertEquals(1, consentRepresentation.getScopes().size());
|
||||||
|
assertEquals(consentScopeRepresentation.getId(), consentRepresentation.getScopes().get(0).getId());
|
||||||
|
|
||||||
|
SimpleHttp.Response response = SimpleHttp
|
||||||
|
.doDelete(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.auth(token.getToken())
|
||||||
|
.asResponse();
|
||||||
|
assertEquals(202, response.getStatus());
|
||||||
|
|
||||||
|
response = SimpleHttp
|
||||||
|
.doDelete(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.auth(token.getToken())
|
||||||
|
.asResponse();
|
||||||
|
assertEquals(202, response.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void deleteConsentForNotExistingClient() throws IOException {
|
||||||
|
assumeFeatureEnabled(ACCOUNT_API);
|
||||||
|
|
||||||
|
TokenUtil token = new TokenUtil("manage-consent-access", "password");
|
||||||
|
String appId = "not-existing";
|
||||||
|
SimpleHttp.Response response = SimpleHttp
|
||||||
|
.doDelete(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.auth(token.getToken())
|
||||||
|
.asResponse();
|
||||||
|
assertEquals(404, response.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void deleteConsentWithoutPermission() throws IOException {
|
||||||
|
assumeFeatureEnabled(ACCOUNT_API);
|
||||||
|
|
||||||
|
TokenUtil token = new TokenUtil("view-consent-access", "password");
|
||||||
|
String appId = "security-admin-console";
|
||||||
|
SimpleHttp.Response response = SimpleHttp
|
||||||
|
.doDelete(getAccountUrl("applications/" + appId + "/consent"), httpClient)
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.auth(token.getToken())
|
||||||
|
.asResponse();
|
||||||
|
assertEquals(403, response.getStatus());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue