KEYCLOAK-1070 JSON representation and export/import for userConsent

This commit is contained in:
mposolda 2015-04-22 10:40:28 +02:00
parent 11035dbe1b
commit 34e033e351
21 changed files with 204 additions and 70 deletions

View file

@ -0,0 +1,28 @@
package org.keycloak.representations.idm;
import java.util.List;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class UserConsentRepresentation {
protected List<String> grantedRoles; // points to roleIds
protected List<String> grantedProtocolMappers; // points to protocolMapperIds
public List<String> getGrantedRoles() {
return grantedRoles;
}
public void setGrantedRoles(List<String> grantedRoles) {
this.grantedRoles = grantedRoles;
}
public List<String> getGrantedProtocolMappers() {
return grantedProtocolMappers;
}
public void setGrantedProtocolMappers(List<String> grantedProtocolMappers) {
this.grantedProtocolMappers = grantedProtocolMappers;
}
}

View file

@ -27,6 +27,7 @@ public class UserRepresentation {
protected List<FederatedIdentityRepresentation> federatedIdentities; protected List<FederatedIdentityRepresentation> federatedIdentities;
protected List<String> realmRoles; protected List<String> realmRoles;
protected Map<String, List<String>> clientRoles; protected Map<String, List<String>> clientRoles;
protected Map<String, UserConsentRepresentation> clientConsents;
@Deprecated @Deprecated
protected Map<String, List<String>> applicationRoles; protected Map<String, List<String>> applicationRoles;
@ -176,6 +177,14 @@ public class UserRepresentation {
this.clientRoles = clientRoles; this.clientRoles = clientRoles;
} }
public Map<String, UserConsentRepresentation> getClientConsents() {
return clientConsents;
}
public void setClientConsents(Map<String, UserConsentRepresentation> clientConsents) {
this.clientConsents = clientConsents;
}
@Deprecated @Deprecated
public Map<String, List<String>> getApplicationRoles() { public Map<String, List<String>> getApplicationRoles() {
return applicationRoles; return applicationRoles;

View file

@ -8,14 +8,15 @@ import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig; import org.codehaus.jackson.map.SerializationConfig;
import org.keycloak.models.ClientModel; import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleContainerModel; import org.keycloak.models.RoleContainerModel;
import org.keycloak.models.RoleModel; import org.keycloak.models.RoleModel;
import org.keycloak.models.FederatedIdentityModel; import org.keycloak.models.FederatedIdentityModel;
import org.keycloak.models.UserConsentModel;
import org.keycloak.models.UserCredentialValueModel; import org.keycloak.models.UserCredentialValueModel;
import org.keycloak.models.UserModel; import org.keycloak.models.UserModel;
import org.keycloak.models.utils.ModelToRepresentation; import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.representations.idm.ApplicationRepresentation;
import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.RealmRepresentation;
@ -23,6 +24,7 @@ import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.RolesRepresentation; import org.keycloak.representations.idm.RolesRepresentation;
import org.keycloak.representations.idm.ScopeMappingRepresentation; import org.keycloak.representations.idm.ScopeMappingRepresentation;
import org.keycloak.representations.idm.FederatedIdentityRepresentation; import org.keycloak.representations.idm.FederatedIdentityRepresentation;
import org.keycloak.representations.idm.UserConsentRepresentation;
import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.representations.idm.UserRepresentation;
import java.io.IOException; import java.io.IOException;
@ -283,6 +285,35 @@ public class ExportUtils {
userRep.setCredentials(credReps); userRep.setCredentials(credReps);
userRep.setFederationLink(user.getFederationLink()); userRep.setFederationLink(user.getFederationLink());
// Grants
List<UserConsentModel> consents = user.getConsents();
Map<String, UserConsentRepresentation> consentReps = new HashMap<String, UserConsentRepresentation>();
for (UserConsentModel consent : consents) {
String clientId = consent.getClient().getClientId();
List<String> grantedProtocolMappers = new LinkedList<String>();
for (ProtocolMapperModel protocolMapper : consent.getGrantedProtocolMappers()) {
grantedProtocolMappers.add(protocolMapper.getId());
}
List<String> grantedRoles = new LinkedList<String>();
for (RoleModel role : consent.getGrantedRoles()) {
grantedRoles.add(role.getId());
}
if (grantedRoles.size() > 0 || grantedProtocolMappers.size() > 0) {
UserConsentRepresentation consentRep = new UserConsentRepresentation();
if (grantedRoles.size() > 0) consentRep.setGrantedRoles(grantedRoles);
if (grantedProtocolMappers.size() > 0) consentRep.setGrantedProtocolMappers(grantedProtocolMappers);
consentReps.put(clientId, consentRep);
}
}
if (consentReps.size() > 0) {
userRep.setClientConsents(consentReps);
}
return userRep; return userRep;
} }

View file

@ -20,7 +20,7 @@ public class AccessBean {
private List<ClientGrantBean> clientGrants = new LinkedList<ClientGrantBean>(); private List<ClientGrantBean> clientGrants = new LinkedList<ClientGrantBean>();
public AccessBean(RealmModel realm, UserModel user, URI baseUri, String stateChecker) { public AccessBean(RealmModel realm, UserModel user, URI baseUri, String stateChecker) {
List<UserConsentModel> grantedConsents = user.getGrantedConsents(); List<UserConsentModel> grantedConsents = user.getConsents();
for (UserConsentModel consent : grantedConsents) { for (UserConsentModel consent : grantedConsents) {
ClientModel client = consent.getClient(); ClientModel client = consent.getClient();

View file

@ -75,11 +75,11 @@ public interface UserModel {
String getFederationLink(); String getFederationLink();
void setFederationLink(String link); void setFederationLink(String link);
void addGrantedConsent(UserConsentModel consent); void addConsent(UserConsentModel consent);
UserConsentModel getGrantedConsentByClient(String clientId); UserConsentModel getConsentByClient(String clientId);
List<UserConsentModel> getGrantedConsents(); List<UserConsentModel> getConsents();
void updateGrantedConsent(UserConsentModel consent); void updateConsent(UserConsentModel consent);
boolean revokeGrantedConsentForClient(String clientId); boolean revokeConsentForClient(String clientId);
public static enum RequiredAction { public static enum RequiredAction {
VERIFY_EMAIL, UPDATE_PROFILE, CONFIGURE_TOTP, UPDATE_PASSWORD VERIFY_EMAIL, UPDATE_PROFILE, CONFIGURE_TOTP, UPDATE_PASSWORD

View file

@ -16,6 +16,7 @@ import org.keycloak.models.PasswordPolicy;
import org.keycloak.models.ProtocolMapperModel; import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel; import org.keycloak.models.RoleModel;
import org.keycloak.models.UserConsentModel;
import org.keycloak.models.UserCredentialModel; import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserCredentialValueModel; import org.keycloak.models.UserCredentialValueModel;
import org.keycloak.models.UserFederationProviderModel; import org.keycloak.models.UserFederationProviderModel;
@ -34,6 +35,7 @@ import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.RoleRepresentation; import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.ScopeMappingRepresentation; import org.keycloak.representations.idm.ScopeMappingRepresentation;
import org.keycloak.representations.idm.SocialLinkRepresentation; import org.keycloak.representations.idm.SocialLinkRepresentation;
import org.keycloak.representations.idm.UserConsentRepresentation;
import org.keycloak.representations.idm.UserFederationProviderRepresentation; import org.keycloak.representations.idm.UserFederationProviderRepresentation;
import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.util.UriUtils; import org.keycloak.util.UriUtils;
@ -789,6 +791,35 @@ public class RepresentationToModel {
createClientRoleMappings(client, user, entry.getValue()); createClientRoleMappings(client, user, entry.getValue());
} }
} }
if (userRep.getClientConsents() != null) {
for (Map.Entry<String, UserConsentRepresentation> entry : userRep.getClientConsents().entrySet()) {
ClientModel client = clientMap.get(entry.getKey());
if (client == null) {
throw new RuntimeException("Unable to find client consent mappings for client: " + entry.getKey());
}
UserConsentModel consentModel = new UserConsentModel(newRealm, client.getId());
UserConsentRepresentation consentRep = entry.getValue();
if (consentRep.getGrantedRoles() != null) {
for (String roleId : consentRep.getGrantedRoles()) {
if (newRealm.getRoleById(roleId) == null) {
throw new RuntimeException("Unable to find realm role referenced in consent mappings of user " + user.getUsername() + ". Role ID: " + roleId);
}
consentModel.addGrantedRole(roleId);
}
}
if (consentRep.getGrantedProtocolMappers() != null) {
for (String mapperId : consentRep.getGrantedProtocolMappers()) {
if (client.getProtocolMapperById(mapperId) == null) {
throw new RuntimeException("Unable to find protocol mapper referenced in consent mappings of user " + user.getUsername() + ". Protocol mapper ID: " + mapperId);
}
consentModel.addGrantedProtocolMapper(mapperId);;
}
}
user.addConsent(consentModel);
}
}
return user; return user;
} }

View file

@ -188,27 +188,27 @@ public class UserModelDelegate implements UserModel {
} }
@Override @Override
public void addGrantedConsent(UserConsentModel consent) { public void addConsent(UserConsentModel consent) {
delegate.addGrantedConsent(consent); delegate.addConsent(consent);
} }
@Override @Override
public UserConsentModel getGrantedConsentByClient(String clientId) { public UserConsentModel getConsentByClient(String clientId) {
return delegate.getGrantedConsentByClient(clientId); return delegate.getConsentByClient(clientId);
} }
@Override @Override
public List<UserConsentModel> getGrantedConsents() { public List<UserConsentModel> getConsents() {
return delegate.getGrantedConsents(); return delegate.getConsents();
} }
@Override @Override
public void updateGrantedConsent(UserConsentModel consent) { public void updateConsent(UserConsentModel consent) {
delegate.updateGrantedConsent(consent); delegate.updateConsent(consent);
} }
@Override @Override
public boolean revokeGrantedConsentForClient(String clientId) { public boolean revokeConsentForClient(String clientId) {
return delegate.revokeGrantedConsentForClient(clientId); return delegate.revokeConsentForClient(clientId);
} }
} }

View file

@ -277,7 +277,8 @@ public class ClientAdapter implements ClientModel {
throw new RuntimeException("protocol mapper name must be unique per protocol"); throw new RuntimeException("protocol mapper name must be unique per protocol");
} }
ProtocolMapperEntity entity = new ProtocolMapperEntity(); ProtocolMapperEntity entity = new ProtocolMapperEntity();
entity.setId(KeycloakModelUtils.generateId()); String id = model.getId() != null ? model.getId() : KeycloakModelUtils.generateId();
entity.setId(id);
entity.setProtocol(model.getProtocol()); entity.setProtocol(model.getProtocol());
entity.setName(model.getName()); entity.setName(model.getName());
entity.setProtocolMapper(model.getProtocolMapper()); entity.setProtocolMapper(model.getProtocolMapper());

View file

@ -432,29 +432,29 @@ public class UserAdapter implements UserModel, Comparable {
} }
@Override @Override
public void addGrantedConsent(UserConsentModel consent) { public void addConsent(UserConsentModel consent) {
// TODO // TODO
} }
@Override @Override
public UserConsentModel getGrantedConsentByClient(String clientId) { public UserConsentModel getConsentByClient(String clientId) {
// TODO // TODO
return null; return null;
} }
@Override @Override
public List<UserConsentModel> getGrantedConsents() { public List<UserConsentModel> getConsents() {
// TODO // TODO
return null; return null;
} }
@Override @Override
public void updateGrantedConsent(UserConsentModel consent) { public void updateConsent(UserConsentModel consent) {
// TODO // TODO
} }
@Override @Override
public boolean revokeGrantedConsentForClient(String clientId) { public boolean revokeConsentForClient(String clientId) {
// TODO // TODO
return false; return false;
} }

View file

@ -277,34 +277,34 @@ public class UserAdapter implements UserModel {
} }
@Override @Override
public void addGrantedConsent(UserConsentModel consent) { public void addConsent(UserConsentModel consent) {
getDelegateForUpdate(); getDelegateForUpdate();
updated.addGrantedConsent(consent); updated.addConsent(consent);
} }
@Override @Override
public UserConsentModel getGrantedConsentByClient(String clientId) { public UserConsentModel getConsentByClient(String clientId) {
// TODO: caching? // TODO: caching?
getDelegateForUpdate(); getDelegateForUpdate();
return updated.getGrantedConsentByClient(clientId); return updated.getConsentByClient(clientId);
} }
@Override @Override
public List<UserConsentModel> getGrantedConsents() { public List<UserConsentModel> getConsents() {
// TODO: caching? // TODO: caching?
getDelegateForUpdate(); getDelegateForUpdate();
return updated.getGrantedConsents(); return updated.getConsents();
} }
@Override @Override
public void updateGrantedConsent(UserConsentModel consent) { public void updateConsent(UserConsentModel consent) {
getDelegateForUpdate(); getDelegateForUpdate();
updated.updateGrantedConsent(consent); updated.updateConsent(consent);
} }
@Override @Override
public boolean revokeGrantedConsentForClient(String clientId) { public boolean revokeConsentForClient(String clientId) {
getDelegateForUpdate(); getDelegateForUpdate();
return updated.revokeGrantedConsentForClient(clientId); return updated.revokeConsentForClient(clientId);
} }
} }

View file

@ -378,7 +378,7 @@ public class ClientAdapter implements ClientModel {
if (getProtocolMapperByName(model.getProtocol(), model.getName()) != null) { if (getProtocolMapperByName(model.getProtocol(), model.getName()) != null) {
throw new RuntimeException("protocol mapper name must be unique per protocol"); throw new RuntimeException("protocol mapper name must be unique per protocol");
} }
String id = KeycloakModelUtils.generateId(); String id = model.getId() != null ? model.getId() : KeycloakModelUtils.generateId();
ProtocolMapperEntity entity = new ProtocolMapperEntity(); ProtocolMapperEntity entity = new ProtocolMapperEntity();
entity.setId(id); entity.setId(id);
entity.setName(model.getName()); entity.setName(model.getName());

View file

@ -480,7 +480,7 @@ public class UserAdapter implements UserModel {
} }
@Override @Override
public void addGrantedConsent(UserConsentModel consent) { public void addConsent(UserConsentModel consent) {
String clientId = consent.getClient().getId(); String clientId = consent.getClient().getId();
UserConsentEntity consentEntity = getGrantedConsentEntity(clientId); UserConsentEntity consentEntity = getGrantedConsentEntity(clientId);
@ -499,13 +499,13 @@ public class UserAdapter implements UserModel {
} }
@Override @Override
public UserConsentModel getGrantedConsentByClient(String clientId) { public UserConsentModel getConsentByClient(String clientId) {
UserConsentEntity entity = getGrantedConsentEntity(clientId); UserConsentEntity entity = getGrantedConsentEntity(clientId);
return toConsentModel(entity); return toConsentModel(entity);
} }
@Override @Override
public List<UserConsentModel> getGrantedConsents() { public List<UserConsentModel> getConsents() {
TypedQuery<UserConsentEntity> query = em.createNamedQuery("userConsentsByUser", UserConsentEntity.class); TypedQuery<UserConsentEntity> query = em.createNamedQuery("userConsentsByUser", UserConsentEntity.class);
query.setParameter("userId", getId()); query.setParameter("userId", getId());
List<UserConsentEntity> results = query.getResultList(); List<UserConsentEntity> results = query.getResultList();
@ -519,7 +519,7 @@ public class UserAdapter implements UserModel {
} }
@Override @Override
public void updateGrantedConsent(UserConsentModel consent) { public void updateConsent(UserConsentModel consent) {
String clientId = consent.getClient().getId(); String clientId = consent.getClient().getId();
UserConsentEntity consentEntity = getGrantedConsentEntity(clientId); UserConsentEntity consentEntity = getGrantedConsentEntity(clientId);
@ -531,7 +531,7 @@ public class UserAdapter implements UserModel {
} }
@Override @Override
public boolean revokeGrantedConsentForClient(String clientId) { public boolean revokeConsentForClient(String clientId) {
UserConsentEntity consentEntity = getGrantedConsentEntity(clientId); UserConsentEntity consentEntity = getGrantedConsentEntity(clientId);
if (consentEntity == null) return false; if (consentEntity == null) return false;

View file

@ -305,7 +305,8 @@ public class ClientAdapter extends AbstractMongoAdapter<MongoClientEntity> imple
throw new RuntimeException("protocol mapper name must be unique per protocol"); throw new RuntimeException("protocol mapper name must be unique per protocol");
} }
ProtocolMapperEntity entity = new ProtocolMapperEntity(); ProtocolMapperEntity entity = new ProtocolMapperEntity();
entity.setId(KeycloakModelUtils.generateId()); String id = model.getId() != null ? model.getId() : KeycloakModelUtils.generateId();
entity.setId(id);
entity.setProtocol(model.getProtocol()); entity.setProtocol(model.getProtocol());
entity.setName(model.getName()); entity.setName(model.getName());
entity.setProtocolMapper(model.getProtocolMapper()); entity.setProtocolMapper(model.getProtocolMapper());

View file

@ -417,7 +417,7 @@ public class UserAdapter extends AbstractMongoAdapter<MongoUserEntity> implement
} }
@Override @Override
public void addGrantedConsent(UserConsentModel consent) { public void addConsent(UserConsentModel consent) {
String clientId = consent.getClient().getId(); String clientId = consent.getClient().getId();
if (getConsentEntityByClientId(clientId) != null) { if (getConsentEntityByClientId(clientId) != null) {
throw new ModelDuplicateException("Consent already exists for client [" + clientId + "] and user [" + user.getId() + "]"); throw new ModelDuplicateException("Consent already exists for client [" + clientId + "] and user [" + user.getId() + "]");
@ -431,13 +431,13 @@ public class UserAdapter extends AbstractMongoAdapter<MongoUserEntity> implement
} }
@Override @Override
public UserConsentModel getGrantedConsentByClient(String clientId) { public UserConsentModel getConsentByClient(String clientId) {
UserConsentEntity consentEntity = getConsentEntityByClientId(clientId); UserConsentEntity consentEntity = getConsentEntityByClientId(clientId);
return consentEntity!=null ? toConsentModel(consentEntity) : null; return consentEntity!=null ? toConsentModel(consentEntity) : null;
} }
@Override @Override
public List<UserConsentModel> getGrantedConsents() { public List<UserConsentModel> getConsents() {
List<UserConsentModel> result = new ArrayList<UserConsentModel>(); List<UserConsentModel> result = new ArrayList<UserConsentModel>();
DBObject query = new QueryBuilder() DBObject query = new QueryBuilder()
@ -488,7 +488,7 @@ public class UserAdapter extends AbstractMongoAdapter<MongoUserEntity> implement
} }
@Override @Override
public void updateGrantedConsent(UserConsentModel consent) { public void updateConsent(UserConsentModel consent) {
String clientId = consent.getClient().getId(); String clientId = consent.getClient().getId();
MongoUserConsentEntity consentEntity = getConsentEntityByClientId(clientId); MongoUserConsentEntity consentEntity = getConsentEntityByClientId(clientId);
if (consentEntity == null) { if (consentEntity == null) {
@ -500,7 +500,7 @@ public class UserAdapter extends AbstractMongoAdapter<MongoUserEntity> implement
} }
@Override @Override
public boolean revokeGrantedConsentForClient(String clientId) { public boolean revokeConsentForClient(String clientId) {
MongoUserConsentEntity entity = getConsentEntityByClientId(clientId); MongoUserConsentEntity entity = getConsentEntityByClientId(clientId);
if (entity == null) { if (entity == null) {
return false; return false;

View file

@ -420,7 +420,7 @@ public class AuthenticationManager {
if (client.isConsentRequired()) { if (client.isConsentRequired()) {
accessCode.setAction(ClientSessionModel.Action.OAUTH_GRANT); accessCode.setAction(ClientSessionModel.Action.OAUTH_GRANT);
UserConsentModel grantedConsent = user.getGrantedConsentByClient(client.getId()); UserConsentModel grantedConsent = user.getConsentByClient(client.getId());
List<RoleModel> realmRoles = new LinkedList<RoleModel>(); List<RoleModel> realmRoles = new LinkedList<RoleModel>();
MultivaluedMap<String, RoleModel> resourceRoles = new MultivaluedMapImpl<String, RoleModel>(); MultivaluedMap<String, RoleModel> resourceRoles = new MultivaluedMapImpl<String, RoleModel>();

View file

@ -76,7 +76,6 @@ import javax.ws.rs.core.Variant;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.net.URI; import java.net.URI;
import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -512,7 +511,7 @@ public class AccountService {
// Revoke grant in UserModel // Revoke grant in UserModel
UserModel user = auth.getUser(); UserModel user = auth.getUser();
user.revokeGrantedConsentForClient(client.getId()); user.revokeConsentForClient(client.getId());
// Logout clientSessions for this user and client // Logout clientSessions for this user and client
List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, user); List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, user);

View file

@ -609,10 +609,10 @@ public class LoginActionsService {
return protocol.consentDenied(clientSession); return protocol.consentDenied(clientSession);
} }
UserConsentModel grantedConsent = user.getGrantedConsentByClient(client.getId()); UserConsentModel grantedConsent = user.getConsentByClient(client.getId());
if (grantedConsent == null) { if (grantedConsent == null) {
grantedConsent = new UserConsentModel(realm, client.getId()); grantedConsent = new UserConsentModel(realm, client.getId());
user.addGrantedConsent(grantedConsent); user.addConsent(grantedConsent);
} }
for (String roleId : clientSession.getRoles()) { for (String roleId : clientSession.getRoles()) {
grantedConsent.addGrantedRole(roleId); grantedConsent.addGrantedRole(roleId);
@ -623,7 +623,7 @@ public class LoginActionsService {
grantedConsent.addGrantedProtocolMapper(protocolMapper.getId()); grantedConsent.addGrantedProtocolMapper(protocolMapper.getId());
} }
} }
user.updateGrantedConsent(grantedConsent); user.updateConsent(grantedConsent);
event.success(); event.success();

View file

@ -9,6 +9,7 @@ import org.keycloak.models.RoleModel;
import org.keycloak.models.utils.ModelToRepresentation; import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.models.utils.RepresentationToModel; import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
import org.keycloak.services.managers.ClientManager; import org.keycloak.services.managers.ClientManager;
import java.util.Iterator; import java.util.Iterator;
@ -63,6 +64,9 @@ public class ClientModelTest extends AbstractModelTest {
public void json() { public void json() {
ClientRepresentation representation = ModelToRepresentation.toRepresentation(client); ClientRepresentation representation = ModelToRepresentation.toRepresentation(client);
representation.setId(null); representation.setId(null);
for (ProtocolMapperRepresentation protocolMapper : representation.getProtocolMappers()) {
protocolMapper.setId(null);
}
RealmModel realm = realmManager.createRealm("copy"); RealmModel realm = realmManager.createRealm("copy");
ClientModel copy = RepresentationToModel.createClient(session, realm, representation, true); ClientModel copy = RepresentationToModel.createClient(session, realm, representation, true);

View file

@ -14,6 +14,7 @@ import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.models.RequiredCredentialModel; import org.keycloak.models.RequiredCredentialModel;
import org.keycloak.models.RoleModel; import org.keycloak.models.RoleModel;
import org.keycloak.models.UserConsentModel;
import org.keycloak.models.UserFederationProvider; import org.keycloak.models.UserFederationProvider;
import org.keycloak.models.UserFederationProviderFactory; import org.keycloak.models.UserFederationProviderFactory;
import org.keycloak.models.UserFederationProviderModel; import org.keycloak.models.UserFederationProviderModel;
@ -238,6 +239,23 @@ public class ImportTest extends AbstractModelTest {
String includeInIdToken = gssCredentialMapper.getConfig().get(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN); String includeInIdToken = gssCredentialMapper.getConfig().get(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
Assert.assertTrue(includeInAccessToken.equalsIgnoreCase("true")); Assert.assertTrue(includeInAccessToken.equalsIgnoreCase("true"));
Assert.assertTrue(includeInIdToken == null || Boolean.parseBoolean(includeInIdToken) == false); Assert.assertTrue(includeInIdToken == null || Boolean.parseBoolean(includeInIdToken) == false);
// Test user consents
admin = session.users().getUserByUsername("admin", realm);
Assert.assertEquals(2, admin.getConsents().size());
UserConsentModel appAdminConsent = admin.getConsentByClient(application.getId());
Assert.assertEquals(2, appAdminConsent.getGrantedRoles().size());
Assert.assertTrue(appAdminConsent.getGrantedProtocolMappers() == null || appAdminConsent.getGrantedProtocolMappers().isEmpty());
Assert.assertTrue(appAdminConsent.isRoleGranted(realm.getRole("admin")));
Assert.assertTrue(appAdminConsent.isRoleGranted(application.getRole("app-admin")));
UserConsentModel otherAppAdminConsent = admin.getConsentByClient(otherApp.getId());
Assert.assertEquals(1, otherAppAdminConsent.getGrantedRoles().size());
Assert.assertEquals(1, otherAppAdminConsent.getGrantedProtocolMappers().size());
Assert.assertTrue(otherAppAdminConsent.isRoleGranted(realm.getRole("admin")));
Assert.assertFalse(otherAppAdminConsent.isRoleGranted(application.getRole("app-admin")));
Assert.assertTrue(otherAppAdminConsent.isProtocolMapperGranted(gssCredentialMapper));
} }
@Test @Test

View file

@ -50,7 +50,7 @@ public class UserConsentModelTest extends AbstractModelTest {
johnFooGrant.addGrantedRole(realmRole.getId()); johnFooGrant.addGrantedRole(realmRole.getId());
johnFooGrant.addGrantedRole(barClientRole.getId()); johnFooGrant.addGrantedRole(barClientRole.getId());
johnFooGrant.addGrantedProtocolMapper(fooMapper.getId()); johnFooGrant.addGrantedProtocolMapper(fooMapper.getId());
john.addGrantedConsent(johnFooGrant); john.addConsent(johnFooGrant);
UserConsentModel johnBarGrant = new UserConsentModel(realm, barClient.getId()); UserConsentModel johnBarGrant = new UserConsentModel(realm, barClient.getId());
johnBarGrant.addGrantedProtocolMapper(barMapper.getId()); johnBarGrant.addGrantedProtocolMapper(barMapper.getId());
@ -58,17 +58,17 @@ public class UserConsentModelTest extends AbstractModelTest {
// Update should fail as grant doesn't yet exists // Update should fail as grant doesn't yet exists
try { try {
john.updateGrantedConsent(johnBarGrant); john.updateConsent(johnBarGrant);
Assert.fail("Not expected to end here"); Assert.fail("Not expected to end here");
} catch (ModelException expected) { } catch (ModelException expected) {
} }
john.addGrantedConsent(johnBarGrant); john.addConsent(johnBarGrant);
UserConsentModel maryFooGrant = new UserConsentModel(realm, fooClient.getId()); UserConsentModel maryFooGrant = new UserConsentModel(realm, fooClient.getId());
maryFooGrant.addGrantedRole(realmRole.getId()); maryFooGrant.addGrantedRole(realmRole.getId());
maryFooGrant.addGrantedProtocolMapper(fooMapper.getId()); maryFooGrant.addGrantedProtocolMapper(fooMapper.getId());
mary.addGrantedConsent(maryFooGrant); mary.addConsent(maryFooGrant);
commit(); commit();
} }
@ -82,27 +82,27 @@ public class UserConsentModelTest extends AbstractModelTest {
UserModel john = session.users().getUserByUsername("john", realm); UserModel john = session.users().getUserByUsername("john", realm);
UserModel mary = session.users().getUserByUsername("mary", realm); UserModel mary = session.users().getUserByUsername("mary", realm);
UserConsentModel johnFooConsent = john.getGrantedConsentByClient(fooClient.getId()); UserConsentModel johnFooConsent = john.getConsentByClient(fooClient.getId());
Assert.assertEquals(johnFooConsent.getGrantedRoles().size(), 2); Assert.assertEquals(johnFooConsent.getGrantedRoles().size(), 2);
Assert.assertEquals(johnFooConsent.getGrantedProtocolMappers().size(), 1); Assert.assertEquals(johnFooConsent.getGrantedProtocolMappers().size(), 1);
Assert.assertTrue(isRoleGranted(realm, "realm-role", johnFooConsent)); Assert.assertTrue(isRoleGranted(realm, "realm-role", johnFooConsent));
Assert.assertTrue(isRoleGranted(barClient, "bar-client-role", johnFooConsent)); Assert.assertTrue(isRoleGranted(barClient, "bar-client-role", johnFooConsent));
Assert.assertTrue(isMapperGranted(fooClient, "foo", johnFooConsent)); Assert.assertTrue(isMapperGranted(fooClient, "foo", johnFooConsent));
UserConsentModel johnBarConsent = john.getGrantedConsentByClient(barClient.getId()); UserConsentModel johnBarConsent = john.getConsentByClient(barClient.getId());
Assert.assertEquals(johnBarConsent.getGrantedRoles().size(), 1); Assert.assertEquals(johnBarConsent.getGrantedRoles().size(), 1);
Assert.assertEquals(johnBarConsent.getGrantedProtocolMappers().size(), 1); Assert.assertEquals(johnBarConsent.getGrantedProtocolMappers().size(), 1);
Assert.assertTrue(isRoleGranted(realm, "realm-role", johnBarConsent)); Assert.assertTrue(isRoleGranted(realm, "realm-role", johnBarConsent));
Assert.assertTrue(isMapperGranted(barClient, "bar", johnBarConsent)); Assert.assertTrue(isMapperGranted(barClient, "bar", johnBarConsent));
UserConsentModel maryConsent = mary.getGrantedConsentByClient(fooClient.getId()); UserConsentModel maryConsent = mary.getConsentByClient(fooClient.getId());
Assert.assertEquals(maryConsent.getGrantedRoles().size(), 1); Assert.assertEquals(maryConsent.getGrantedRoles().size(), 1);
Assert.assertEquals(maryConsent.getGrantedProtocolMappers().size(), 1); Assert.assertEquals(maryConsent.getGrantedProtocolMappers().size(), 1);
Assert.assertTrue(isRoleGranted(realm, "realm-role", maryConsent)); Assert.assertTrue(isRoleGranted(realm, "realm-role", maryConsent));
Assert.assertFalse(isRoleGranted(barClient, "bar-client-role", maryConsent)); Assert.assertFalse(isRoleGranted(barClient, "bar-client-role", maryConsent));
Assert.assertTrue(isMapperGranted(fooClient, "foo", maryConsent)); Assert.assertTrue(isMapperGranted(fooClient, "foo", maryConsent));
Assert.assertNull(mary.getGrantedConsentByClient(barClient.getId())); Assert.assertNull(mary.getConsentByClient(barClient.getId()));
} }
@Test @Test
@ -113,10 +113,10 @@ public class UserConsentModelTest extends AbstractModelTest {
UserModel john = session.users().getUserByUsername("john", realm); UserModel john = session.users().getUserByUsername("john", realm);
UserModel mary = session.users().getUserByUsername("mary", realm); UserModel mary = session.users().getUserByUsername("mary", realm);
List<UserConsentModel> johnConsents = john.getGrantedConsents(); List<UserConsentModel> johnConsents = john.getConsents();
Assert.assertEquals(2, johnConsents.size()); Assert.assertEquals(2, johnConsents.size());
List<UserConsentModel> maryConsents = mary.getGrantedConsents(); List<UserConsentModel> maryConsents = mary.getConsents();
Assert.assertEquals(1, maryConsents.size()); Assert.assertEquals(1, maryConsents.size());
UserConsentModel maryConsent = maryConsents.get(0); UserConsentModel maryConsent = maryConsents.get(0);
Assert.assertEquals(maryConsent.getClient().getId(), fooClient.getId()); Assert.assertEquals(maryConsent.getClient().getId(), fooClient.getId());
@ -132,7 +132,7 @@ public class UserConsentModelTest extends AbstractModelTest {
ClientModel fooClient = realm.getClientByClientId("foo-client"); ClientModel fooClient = realm.getClientByClientId("foo-client");
UserModel john = session.users().getUserByUsername("john", realm); UserModel john = session.users().getUserByUsername("john", realm);
UserConsentModel johnConsent = john.getGrantedConsentByClient(fooClient.getId()); UserConsentModel johnConsent = john.getConsentByClient(fooClient.getId());
// Remove foo protocol mapper from johnConsent // Remove foo protocol mapper from johnConsent
ProtocolMapperModel protMapperModel = fooClient.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, "foo"); ProtocolMapperModel protMapperModel = fooClient.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, "foo");
@ -145,14 +145,14 @@ public class UserConsentModelTest extends AbstractModelTest {
RoleModel newRealmRole = realm.addRole("new-realm-role"); RoleModel newRealmRole = realm.addRole("new-realm-role");
johnConsent.addGrantedRole(newRealmRole.getId()); johnConsent.addGrantedRole(newRealmRole.getId());
john.updateGrantedConsent(johnConsent); john.updateConsent(johnConsent);
commit(); commit();
realm = realmManager.getRealm("original"); realm = realmManager.getRealm("original");
fooClient = realm.getClientByClientId("foo-client"); fooClient = realm.getClientByClientId("foo-client");
john = session.users().getUserByUsername("john", realm); john = session.users().getUserByUsername("john", realm);
johnConsent = john.getGrantedConsentByClient(fooClient.getId()); johnConsent = john.getConsentByClient(fooClient.getId());
Assert.assertEquals(johnConsent.getGrantedRoles().size(), 2); Assert.assertEquals(johnConsent.getGrantedRoles().size(), 2);
Assert.assertEquals(johnConsent.getGrantedProtocolMappers().size(), 0); Assert.assertEquals(johnConsent.getGrantedProtocolMappers().size(), 0);
@ -167,13 +167,13 @@ public class UserConsentModelTest extends AbstractModelTest {
ClientModel fooClient = realm.getClientByClientId("foo-client"); ClientModel fooClient = realm.getClientByClientId("foo-client");
UserModel john = session.users().getUserByUsername("john", realm); UserModel john = session.users().getUserByUsername("john", realm);
john.revokeGrantedConsentForClient(fooClient.getId()); john.revokeConsentForClient(fooClient.getId());
commit(); commit();
realm = realmManager.getRealm("original"); realm = realmManager.getRealm("original");
john = session.users().getUserByUsername("john", realm); john = session.users().getUserByUsername("john", realm);
Assert.assertNull(john.getGrantedConsentByClient(fooClient.getId())); Assert.assertNull(john.getConsentByClient(fooClient.getId()));
} }
@Test @Test
@ -196,7 +196,7 @@ public class UserConsentModelTest extends AbstractModelTest {
realm = realmManager.getRealm("original"); realm = realmManager.getRealm("original");
fooClient = realm.getClientByClientId("foo-client"); fooClient = realm.getClientByClientId("foo-client");
UserModel john = session.users().getUserByUsername("john", realm); UserModel john = session.users().getUserByUsername("john", realm);
UserConsentModel johnConsent = john.getGrantedConsentByClient(fooClient.getId()); UserConsentModel johnConsent = john.getConsentByClient(fooClient.getId());
Assert.assertEquals(johnConsent.getGrantedRoles().size(), 2); Assert.assertEquals(johnConsent.getGrantedRoles().size(), 2);
Assert.assertEquals(johnConsent.getGrantedProtocolMappers().size(), 0); Assert.assertEquals(johnConsent.getGrantedProtocolMappers().size(), 0);
@ -215,7 +215,7 @@ public class UserConsentModelTest extends AbstractModelTest {
ClientModel fooClient = realm.getClientByClientId("foo-client"); ClientModel fooClient = realm.getClientByClientId("foo-client");
ClientModel barClient = realm.getClientByClientId("bar-client"); ClientModel barClient = realm.getClientByClientId("bar-client");
UserModel john = session.users().getUserByUsername("john", realm); UserModel john = session.users().getUserByUsername("john", realm);
UserConsentModel johnConsent = john.getGrantedConsentByClient(fooClient.getId()); UserConsentModel johnConsent = john.getConsentByClient(fooClient.getId());
Assert.assertEquals(johnConsent.getGrantedRoles().size(), 1); Assert.assertEquals(johnConsent.getGrantedRoles().size(), 1);
Assert.assertEquals(johnConsent.getGrantedProtocolMappers().size(), 1); Assert.assertEquals(johnConsent.getGrantedProtocolMappers().size(), 1);
@ -237,13 +237,13 @@ public class UserConsentModelTest extends AbstractModelTest {
UserModel john = session.users().getUserByUsername("john", realm); UserModel john = session.users().getUserByUsername("john", realm);
UserConsentModel johnFooConsent = john.getGrantedConsentByClient(fooClient.getId()); UserConsentModel johnFooConsent = john.getConsentByClient(fooClient.getId());
Assert.assertEquals(johnFooConsent.getGrantedRoles().size(), 1); Assert.assertEquals(johnFooConsent.getGrantedRoles().size(), 1);
Assert.assertEquals(johnFooConsent.getGrantedProtocolMappers().size(), 1); Assert.assertEquals(johnFooConsent.getGrantedProtocolMappers().size(), 1);
Assert.assertTrue(isRoleGranted(realm, "realm-role", johnFooConsent)); Assert.assertTrue(isRoleGranted(realm, "realm-role", johnFooConsent));
Assert.assertTrue(isMapperGranted(fooClient, "foo", johnFooConsent)); Assert.assertTrue(isMapperGranted(fooClient, "foo", johnFooConsent));
Assert.assertNull(john.getGrantedConsentByClient(barClient.getId())); Assert.assertNull(john.getConsentByClient(barClient.getId()));
} }
private boolean isRoleGranted(RoleContainerModel roleContainer, String roleName, UserConsentModel consentModel) { private boolean isRoleGranted(RoleContainerModel roleContainer, String roleName, UserConsentModel consentModel) {

View file

@ -74,6 +74,15 @@
"applicationRoles": { "applicationRoles": {
"Application": [ "app-admin" ], "Application": [ "app-admin" ],
"OtherApp": [ "otherapp-admin" ] "OtherApp": [ "otherapp-admin" ]
},
"clientConsents": {
"Application": {
"grantedRoles": [ "456", "789" ]
},
"OtherApp": {
"grantedProtocolMappers": [ "123" ],
"grantedRoles": [ "456" ]
}
} }
}, },
{ {
@ -113,6 +122,7 @@
"enabled": true, "enabled": true,
"protocolMappers" : [ "protocolMappers" : [
{ {
"id": "123",
"name" : "gss delegation credential", "name" : "gss delegation credential",
"protocol" : "openid-connect", "protocol" : "openid-connect",
"protocolMapper" : "oidc-usersessionmodel-note-mapper", "protocolMapper" : "oidc-usersessionmodel-note-mapper",
@ -138,12 +148,14 @@
"roles" : { "roles" : {
"realm" : [ "realm" : [
{ {
"id": "456",
"name": "admin" "name": "admin"
} }
], ],
"application" : { "application" : {
"Application" : [ "Application" : [
{ {
"id": "789",
"name": "app-admin" "name": "app-admin"
}, },
{ {