keycloak-memoizeit

fix conflicts

4/13/2015 10:59:59 AM

Changes

distribution/modules/src/main/resources/modules/org/keycloak/keycloak-picketlink-api/main/module.xml 21(+0 -21)

distribution/modules/src/main/resources/modules/org/keycloak/keycloak-picketlink-ldap/main/module.xml 21(+0 -21)

forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/oauth-clients.js 611(+0 -611)

forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-list.html 59(+0 -59)

forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-mappers.html 47(+0 -47)

forms/common-themes/src/main/resources/theme/base/admin/resources/partials/application-revocation.html 31(+0 -31)

forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-claims.html 19(+0 -19)

forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-credentials.html 29(+0 -29)

forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-detail.html 116(+0 -116)

forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-identity-provider.html 31(+0 -31)

forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-installation.html 26(+0 -26)

forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-mappers-add.html 49(+0 -49)

forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-protocol-mapper-detail.html 108(+0 -108)

forms/common-themes/src/main/resources/theme/base/admin/resources/partials/oauth-client-scope-mappings.html 124(+0 -124)

forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-navigation-application.html 13(+0 -13)

forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-navigation-oauth-client.html 9(+0 -9)

integration/admin-client/src/main/java/org/keycloak/admin/client/resource/OAuthClientResource.java 57(+0 -57)

integration/admin-client/src/main/java/org/keycloak/admin/client/resource/OAuthClientsResource.java 30(+0 -30)

model/api/src/main/java/org/keycloak/models/ApplicationModel.java 56(+0 -56)

model/api/src/main/java/org/keycloak/models/entities/ApplicationEntity.java 79(+0 -79)

model/api/src/main/java/org/keycloak/models/entities/OAuthClientEntity.java 16(+0 -16)

model/api/src/main/java/org/keycloak/models/OAuthClientModel.java 10(+0 -10)

model/file/src/main/java/org/keycloak/models/file/adapter/ApplicationAdapter.java 322(+0 -322)

model/file/src/main/java/org/keycloak/models/file/adapter/OAuthClientAdapter.java 45(+0 -45)

model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ApplicationAdapter.java 247(+0 -247)

model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java 152(+0 -152)

model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedOAuthClient.java 17(+0 -17)

model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/OAuthClientAdapter.java 56(+0 -56)

model/jpa/src/main/java/org/keycloak/models/jpa/ApplicationAdapter.java 308(+0 -308)

model/jpa/src/main/java/org/keycloak/models/jpa/entities/ApplicationEntity.java 116(+0 -116)

model/jpa/src/main/java/org/keycloak/models/jpa/entities/OAuthClientEntity.java 29(+0 -29)

model/jpa/src/main/java/org/keycloak/models/jpa/OAuthClientAdapter.java 52(+0 -52)

model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ApplicationAdapter.java 275(+0 -275)

model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/OAuthClientAdapter.java 48(+0 -48)

model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoOAuthClientEntity.java 23(+0 -23)

picketlink/keycloak-picketlink-api/pom.xml 55(+0 -55)

picketlink/keycloak-picketlink-api/src/main/java/org/keycloak/picketlink/PartitionManagerProvider.java 14(+0 -14)

picketlink/keycloak-picketlink-api/src/main/java/org/keycloak/picketlink/PartitionManagerProviderFactory.java 9(+0 -9)

picketlink/keycloak-picketlink-api/src/main/java/org/keycloak/picketlink/PartitionManagerSpi.java 25(+0 -25)

picketlink/keycloak-picketlink-api/src/main/resources/META-INF/services/org.keycloak.provider.Spi 1(+0 -1)

picketlink/keycloak-picketlink-ldap/pom.xml 66(+0 -66)

picketlink/keycloak-picketlink-ldap/src/main/java/org/keycloak/picketlink/idm/KeycloakEventBridge.java 63(+0 -63)

picketlink/keycloak-picketlink-ldap/src/main/java/org/keycloak/picketlink/idm/LDAPKeycloakCredentialHandler.java 51(+0 -51)

picketlink/keycloak-picketlink-ldap/src/main/java/org/keycloak/picketlink/ldap/LDAPPartitionManagerProvider.java 26(+0 -26)

picketlink/keycloak-picketlink-ldap/src/main/java/org/keycloak/picketlink/ldap/LDAPPartitionManagerProviderFactory.java 43(+0 -43)

picketlink/keycloak-picketlink-ldap/src/main/java/org/keycloak/picketlink/ldap/PartitionManagerRegistry.java 163(+0 -163)

picketlink/keycloak-picketlink-ldap/src/main/resources/META-INF/services/org.keycloak.picketlink.PartitionManagerProviderFactory 1(+0 -1)

picketlink/pom.xml 24(+0 -24)

pom.xml 1(+0 -1)

services/pom.xml 6(+0 -6)

services/src/main/java/org/keycloak/services/managers/OAuthClientManager.java 96(+0 -96)

services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java 206(+0 -206)

services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsByIdResource.java 26(+0 -26)

services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsResource.java 121(+0 -121)

testsuite/integration/src/test/java/org/keycloak/testsuite/admin/OAuthClientTest.java 54(+0 -54)

Details

diff --git a/broker/oidc/pom.xml b/broker/oidc/pom.xml
index 27fb085..8913efb 100755
--- a/broker/oidc/pom.xml
+++ b/broker/oidc/pom.xml
@@ -52,6 +52,11 @@
             <artifactId>jboss-logging</artifactId>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
 </project>
diff --git a/broker/oidc/src/main/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProvider.java b/broker/oidc/src/main/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProvider.java
index 0eab543..0581eb1 100755
--- a/broker/oidc/src/main/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProvider.java
+++ b/broker/oidc/src/main/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProvider.java
@@ -112,11 +112,22 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
     }
 
     protected String extractTokenFromResponse(String response, String tokenName) {
+    	  if(response == null)
+    	  	return null;
+    	  
         if (response.startsWith("{")) {
             try {
-                return mapper.readTree(response).get(tokenName).getTextValue();
+            		JsonNode node = mapper.readTree(response);
+            		if(node.has(tokenName)){
+            			String s = node.get(tokenName).getTextValue();
+            			if(s == null || s.trim().isEmpty())
+            				return null;
+                  return s;
+            		} else {
+            			return null;
+            		}
             } catch (IOException e) {
-                throw new IdentityBrokerException("Could not extract token [" + tokenName + "] from response [" + response + "].", e);
+                throw new IdentityBrokerException("Could not extract token [" + tokenName + "] from response [" + response + "] due: " + e.getMessage(), e);
             }
         } else {
             Matcher matcher = Pattern.compile(tokenName + "=([^&]+)").matcher(response);
@@ -133,7 +144,7 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
         String accessToken = extractTokenFromResponse(response, OAUTH2_PARAMETER_ACCESS_TOKEN);
 
         if (accessToken == null) {
-            throw new IdentityBrokerException("No access token from server.");
+            throw new IdentityBrokerException("No access token available in OAuth server response: " + response);
         }
 
         return doGetFederatedIdentity(accessToken);
@@ -144,7 +155,6 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
         return null;
     }
 
-    ;
 
     protected UriBuilder createAuthorizationUrl(AuthenticationRequest request) {
         return UriBuilder.fromUri(getConfig().getAuthorizationUrl())
@@ -155,9 +165,20 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
                 .queryParam(OAUTH2_PARAMETER_REDIRECT_URI, request.getRedirectUri());
     }
 
+    /**
+     * Get JSON property as text. JSON numbers and booleans are converted to text. Empty string is converted to null. 
+     * 
+     * @param jsonNode to get property from
+     * @param name of property to get
+     * @return string value of the property or null.
+     */
     protected String getJsonProperty(JsonNode jsonNode, String name) {
-        if (jsonNode.has(name)) {
-            return jsonNode.get(name).asText();
+        if (jsonNode.has(name) && !jsonNode.get(name).isNull()) {
+        	  String s = jsonNode.get(name).asText();
+        	  if(s != null && !s.isEmpty())
+        	  		return s;
+        	  else
+      	  			return null;
         }
 
         return null;
diff --git a/broker/oidc/src/main/java/org/keycloak/broker/oidc/KeycloakOIDCIdentityProvider.java b/broker/oidc/src/main/java/org/keycloak/broker/oidc/KeycloakOIDCIdentityProvider.java
index 47847dc..ff89a89 100755
--- a/broker/oidc/src/main/java/org/keycloak/broker/oidc/KeycloakOIDCIdentityProvider.java
+++ b/broker/oidc/src/main/java/org/keycloak/broker/oidc/KeycloakOIDCIdentityProvider.java
@@ -4,14 +4,12 @@ import org.keycloak.broker.oidc.util.SimpleHttp;
 import org.keycloak.constants.AdapterConstants;
 import org.keycloak.events.EventBuilder;
 import org.keycloak.jose.jws.JWSInput;
-import org.keycloak.jose.jws.crypto.RSAProvider;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserSessionModel;
 import org.keycloak.representations.adapters.action.AdminAction;
 import org.keycloak.representations.adapters.action.LogoutAction;
 import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.util.JsonSerialization;
-import org.keycloak.util.PemUtils;
 
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
@@ -90,7 +88,7 @@ public class KeycloakOIDCIdentityProvider extends OIDCIdentityProvider {
         @Override
         public SimpleHttp generateTokenRequest(String authorizationCode) {
             return super.generateTokenRequest(authorizationCode)
-                    .param(AdapterConstants.APPLICATION_SESSION_STATE, "n/a");  // hack to get backchannel logout to work
+                    .param(AdapterConstants.CLIENT_SESSION_STATE, "n/a");  // hack to get backchannel logout to work
 
         }
 
diff --git a/broker/oidc/src/test/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProviderTest.java b/broker/oidc/src/test/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProviderTest.java
new file mode 100755
index 0000000..32e132d
--- /dev/null
+++ b/broker/oidc/src/test/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProviderTest.java
@@ -0,0 +1,134 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @authors tag. All rights reserved.
+ */
+package org.keycloak.broker.oidc;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.codehaus.jackson.JsonNode;
+import org.junit.Assert;
+import org.junit.Test;
+import org.keycloak.broker.provider.BrokeredIdentityContext;
+import org.keycloak.broker.provider.FederatedIdentity;
+import org.keycloak.broker.provider.IdentityBrokerException;
+import org.keycloak.models.IdentityProviderModel;
+
+/**
+ * Unit test for {@link AbstractOAuth2IdentityProvider}
+ * 
+ * @author Vlastimil Elias (velias at redhat dot com)
+ */
+public class AbstractOAuth2IdentityProviderTest {
+	
+	@Test
+	public void constructor_defaultScopeHandling(){
+		TestProvider tested = getTested();
+		
+		//default scope is set from the provider if not provided in the configuration
+		Assert.assertEquals( tested.getDefaultScopes(), tested.getConfig().getDefaultScope());
+		
+		//default scope is preserved if provided in the configuration
+		IdentityProviderModel model = new IdentityProviderModel();
+		OAuth2IdentityProviderConfig config = new OAuth2IdentityProviderConfig(model);
+		config.setDefaultScope("myscope");
+		tested = new TestProvider(config);
+
+		Assert.assertEquals("myscope", tested.getConfig().getDefaultScope());
+		
+	}
+
+	@Test
+	public void getJsonProperty_asJsonNode() throws IOException {
+		TestProvider tested = getTested();
+
+		JsonNode jsonNode = tested
+				.asJsonNode("{\"nullone\":null, \"emptyone\":\"\", \"blankone\": \" \", \"withvalue\" : \"my value\", \"withbooleanvalue\" : true, \"withnumbervalue\" : 10}");
+		Assert.assertNull(tested.getJsonProperty(jsonNode, "nonexisting"));
+		Assert.assertNull(tested.getJsonProperty(jsonNode, "nullone"));
+		Assert.assertNull(tested.getJsonProperty(jsonNode, "emptyone"));
+		Assert.assertEquals(" ", tested.getJsonProperty(jsonNode, "blankone"));
+		Assert.assertEquals("my value", tested.getJsonProperty(jsonNode, "withvalue"));
+		Assert.assertEquals("true", tested.getJsonProperty(jsonNode, "withbooleanvalue"));
+		Assert.assertEquals("10", tested.getJsonProperty(jsonNode, "withnumbervalue"));
+	}
+
+	@Test(expected = IdentityBrokerException.class)
+	public void getFederatedIdentity_responseUrlLine_tokenNotFound() {
+		TestProvider tested = getTested();
+		tested.getFederatedIdentity("cosi=sss");
+	}
+
+	@Test(expected = IdentityBrokerException.class)
+	public void getFederatedIdentity_responseJSON_tokenNotFound() {
+		TestProvider tested = getTested();
+		Map<String, String> notes = new HashMap<>();
+		tested.getFederatedIdentity("{\"cosi\":\"sss\"}");
+	}
+
+	@Test(expected = IdentityBrokerException.class)
+	public void getFederatedIdentity_responseJSON_invalidFormat() {
+		TestProvider tested = getTested();
+		Map<String, String> notes = new HashMap<>();
+		tested.getFederatedIdentity("{\"cosi\":\"sss\"");
+	}
+
+	@Test(expected = IdentityBrokerException.class)
+	public void getFederatedIdentity_responseJSON_emptyTokenField() {
+		TestProvider tested = getTested();
+		tested.getFederatedIdentity("{\""
+				+ AbstractOAuth2IdentityProvider.OAUTH2_PARAMETER_ACCESS_TOKEN + "\" : \"\"}");
+	}
+
+	@Test(expected = IdentityBrokerException.class)
+	public void getFederatedIdentity_responseJSON_nullTokenField() {
+		TestProvider tested = getTested();
+		tested.getFederatedIdentity("{\""
+				+ AbstractOAuth2IdentityProvider.OAUTH2_PARAMETER_ACCESS_TOKEN + "\" : null}");
+	}
+
+	@Test
+	public void getFederatedIdentity_responseJSON() {
+		TestProvider tested = getTested();
+		BrokeredIdentityContext fi = tested.getFederatedIdentity("{\""
+				+ AbstractOAuth2IdentityProvider.OAUTH2_PARAMETER_ACCESS_TOKEN + "\" : \"458rt\"}");
+		Assert.assertNotNull(fi);
+		Assert.assertEquals("458rt", fi.getId());
+	}
+
+	@Test
+	public void getFederatedIdentity_responseUrlLine() {
+		TestProvider tested = getTested();
+        BrokeredIdentityContext fi = tested.getFederatedIdentity("cosi=sss&"
+				+ AbstractOAuth2IdentityProvider.OAUTH2_PARAMETER_ACCESS_TOKEN + "=458rtf&kdesi=ss}");
+		Assert.assertNotNull(fi);
+		Assert.assertEquals("458rtf", fi.getId());
+	}
+
+	private TestProvider getTested() {
+		IdentityProviderModel model = new IdentityProviderModel();
+		OAuth2IdentityProviderConfig config = new OAuth2IdentityProviderConfig(model);
+		return new TestProvider(config);
+	}
+
+	private static class TestProvider extends AbstractOAuth2IdentityProvider<OAuth2IdentityProviderConfig> {
+
+		public TestProvider(OAuth2IdentityProviderConfig config) {
+			super(config);
+		}
+
+		@Override
+		protected String getDefaultScopes() {
+			return "default";
+		}
+
+		protected BrokeredIdentityContext doGetFederatedIdentity(String accessToken) {
+			return new BrokeredIdentityContext(accessToken);
+		};
+
+	};
+
+}
diff --git a/connections/jpa/src/main/resources/META-INF/persistence.xml b/connections/jpa/src/main/resources/META-INF/persistence.xml
index aca54ef..2a066d0 100755
--- a/connections/jpa/src/main/resources/META-INF/persistence.xml
+++ b/connections/jpa/src/main/resources/META-INF/persistence.xml
@@ -3,9 +3,8 @@
     xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
     version="1.0">
     <persistence-unit name="keycloak-default" transaction-type="RESOURCE_LOCAL">
-        <class>org.keycloak.models.jpa.entities.ApplicationEntity</class>
+        <class>org.keycloak.models.jpa.entities.ClientEntity</class>
         <class>org.keycloak.models.jpa.entities.CredentialEntity</class>
-        <class>org.keycloak.models.jpa.entities.OAuthClientEntity</class>
         <class>org.keycloak.models.jpa.entities.RealmEntity</class>
         <class>org.keycloak.models.jpa.entities.RealmAttributeEntity</class>
         <class>org.keycloak.models.jpa.entities.RequiredCredentialEntity</class>
diff --git a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.RC1.xml b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.RC1.xml
index 7c50600..6fc69db 100755
--- a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.RC1.xml
+++ b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.RC1.xml
@@ -36,5 +36,17 @@
         <addPrimaryKey columnNames="IDP_MAPPER_ID, NAME" constraintName="CONSTRAINT_IDPMConfig" tableName="IDP_MAPPER_CONFIG"/>
         <addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="IDENTITY_PROVIDER_MAPPER" constraintName="FK_IDPM_REALM" referencedColumnNames="ID" referencedTableName="REALM"/>
         <addForeignKeyConstraint baseColumnNames="IDP_MAPPER_ID" baseTableName="IDP_MAPPER_CONFIG" constraintName="FK_IDPMConfig" referencedColumnNames="ID" referencedTableName="IDENTITY_PROVIDER_MAPPER"/>
+
+        <addColumn tableName="CLIENT">
+            <column name="CONSENT_REQUIRED" type="BOOLEAN" defaultValueBoolean="false">
+                <constraints nullable="false"/>
+            </column>
+        </addColumn>
+        <update tableName="CLIENT">
+            <column name="CONSENT_REQUIRED" valueBoolean="true"/>
+            <where>DTYPE = 'OAuthClientEntity'</where>
+        </update>
+        <dropColumn tableName="CLIENT" columnName="DTYPE"/>
+        <renameColumn tableName="CLIENT" newColumnName="CLIENT_ID" oldColumnName="NAME"/>
     </changeSet>
 </databaseChangeLog>
diff --git a/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java b/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java
index f5ed855..138955b 100755
--- a/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java
+++ b/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java
@@ -33,8 +33,7 @@ public class DefaultMongoConnectionFactoryProvider implements MongoConnectionPro
             "org.keycloak.models.entities.RequiredCredentialEntity",
             "org.keycloak.models.entities.CredentialEntity",
             "org.keycloak.models.entities.FederatedIdentityEntity",
-            "org.keycloak.models.mongo.keycloak.entities.MongoApplicationEntity",
-            "org.keycloak.models.mongo.keycloak.entities.MongoOAuthClientEntity",
+            "org.keycloak.models.mongo.keycloak.entities.MongoClientEntity",
             "org.keycloak.models.sessions.mongo.entities.MongoUsernameLoginFailureEntity",
             "org.keycloak.models.sessions.mongo.entities.MongoUserSessionEntity",
             "org.keycloak.models.sessions.mongo.entities.MongoClientSessionEntity",
diff --git a/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/DefaultMongoUpdaterProvider.java b/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/DefaultMongoUpdaterProvider.java
index da1d2c0..10a1368 100644
--- a/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/DefaultMongoUpdaterProvider.java
+++ b/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/DefaultMongoUpdaterProvider.java
@@ -10,6 +10,7 @@ import org.keycloak.connections.mongo.updater.impl.updates.Update;
 import org.keycloak.connections.mongo.updater.impl.updates.Update1_0_0_Final;
 import org.keycloak.connections.mongo.updater.impl.updates.Update1_1_0_Beta1;
 import org.keycloak.connections.mongo.updater.impl.updates.Update1_2_0_Beta1;
+import org.keycloak.connections.mongo.updater.impl.updates.Update1_2_0_RC1;
 import org.keycloak.models.KeycloakSession;
 
 import java.util.Date;
@@ -28,7 +29,8 @@ public class DefaultMongoUpdaterProvider implements MongoUpdaterProvider {
     private Class<? extends Update>[] updates = new Class[]{
             Update1_0_0_Final.class,
             Update1_1_0_Beta1.class,
-            Update1_2_0_Beta1.class
+            Update1_2_0_Beta1.class,
+            Update1_2_0_RC1.class
     };
 
     @Override
diff --git a/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update.java b/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update.java
index 54e4b70..f05e79c 100644
--- a/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update.java
+++ b/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update.java
@@ -53,15 +53,8 @@ public abstract class Update {
         log.debugv("Deleted entries from {0}", collection);
     }
 
-    protected String insertApplicationRole(DBCollection roles, String roleName, String applicationId) {
-        BasicDBObject role = new BasicDBObject();
-        String roleId = KeycloakModelUtils.generateId();
-        role.append("_id", roleId);
-        role.append("name", roleName);
-        role.append("applicationId", applicationId);
-        role.append("nameIndex", applicationId + "//" + roleName);
-        roles.insert(role);
-        return roleId;
+    protected void renameCollection(String collection, String newName) {
+        db.getCollection(collection).rename(newName);
     }
 
     public void setLog(Logger log) {
diff --git a/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_Beta1.java b/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_Beta1.java
index 349520a..abaae4c 100644
--- a/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_Beta1.java
+++ b/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_Beta1.java
@@ -266,4 +266,15 @@ public class Update1_2_0_Beta1 extends Update {
         }
     }
 
+    private String insertApplicationRole(DBCollection roles, String roleName, String applicationId) {
+        BasicDBObject role = new BasicDBObject();
+        String roleId = KeycloakModelUtils.generateId();
+        role.append("_id", roleId);
+        role.append("name", roleName);
+        role.append("applicationId", applicationId);
+        role.append("nameIndex", applicationId + "//" + roleName);
+        roles.insert(role);
+        return roleId;
+    }
+
 }
diff --git a/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_RC1.java b/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_RC1.java
new file mode 100644
index 0000000..5954199
--- /dev/null
+++ b/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_RC1.java
@@ -0,0 +1,51 @@
+package org.keycloak.connections.mongo.updater.impl.updates;
+
+import com.mongodb.BasicDBObject;
+import com.mongodb.DBCollection;
+import com.mongodb.DBCursor;
+import org.keycloak.models.KeycloakSession;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class Update1_2_0_RC1 extends Update {
+
+    @Override
+    public String getId() {
+        return "1.2.0.RC1";
+    }
+
+    @Override
+    public void update(KeycloakSession session) {
+        convertApplicationsToClients();
+        convertOAuthClientsToClients();
+    }
+
+    private void convertApplicationsToClients() {
+        DBCollection applications = db.getCollection("applications");
+        applications.update(new BasicDBObject(), new BasicDBObject("$set", new BasicDBObject("consentRequired", false)), false, true);
+        applications.update(new BasicDBObject(), new BasicDBObject("$rename", new BasicDBObject("name", "clientId")), false, true);
+        renameCollection("applications", "clients");
+        log.debugv("Converted applications to clients");
+
+        DBCollection roles = db.getCollection("roles");
+        roles.update(new BasicDBObject(), new BasicDBObject("$rename", new BasicDBObject("applicationId", "clientId")), false, true);
+        log.debugv("Renamed roles.applicationId to roles.clientId");
+    }
+
+    private void convertOAuthClientsToClients() {
+        DBCollection clients = db.getCollection("clients");
+        DBCollection oauthClients = db.getCollection("oauthClients");
+        oauthClients.update(new BasicDBObject(), new BasicDBObject("$rename", new BasicDBObject("name", "clientId")), false, true);
+        oauthClients.update(new BasicDBObject(), new BasicDBObject("$set", new BasicDBObject("consentRequired", true)), false, true);
+
+        DBCursor curs = oauthClients.find();
+        while (curs.hasNext()) {
+            clients.insert(curs.next());
+        }
+
+        oauthClients.drop();
+        log.debugv("Converted oauthClients to clients");
+    }
+
+}
diff --git a/core/src/main/java/org/keycloak/constants/AdapterConstants.java b/core/src/main/java/org/keycloak/constants/AdapterConstants.java
index df302b2..aa22395 100755
--- a/core/src/main/java/org/keycloak/constants/AdapterConstants.java
+++ b/core/src/main/java/org/keycloak/constants/AdapterConstants.java
@@ -19,13 +19,13 @@ public interface AdapterConstants {
     String AUTH_DATA_PARAM_NAME = "org.keycloak.json.adapterConfig";
 
     // Attribute passed in codeToToken request from adapter to Keycloak and saved in ClientSession. Contains ID of HttpSession on adapter
-    public static final String APPLICATION_SESSION_STATE = "application_session_state";
+    public static final String CLIENT_SESSION_STATE = "client_session_state";
 
     // Attribute passed in codeToToken request from adapter to Keycloak and saved in ClientSession. Contains hostname of adapter where HttpSession is served
-    public static final String APPLICATION_SESSION_HOST = "application_session_host";
+    public static final String CLIENT_SESSION_HOST = "client_session_host";
 
     // Attribute passed in registerNode request for register new application cluster node once he joined cluster
-    public static final String APPLICATION_CLUSTER_HOST = "application_cluster_host";
+    public static final String CLIENT_CLUSTER_HOST = "client_cluster_host";
 
     // Cookie used on adapter side to store token info. Used only when tokenStore is 'COOKIE'
     public static final String KEYCLOAK_ADAPTER_STATE_COOKIE = "KEYCLOAK_ADAPTER_STATE";
diff --git a/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java
index e407049..cc9b657 100755
--- a/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java
@@ -1,44 +1,14 @@
 package org.keycloak.representations.idm;
 
-import java.util.List;
-import java.util.Map;
-
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public class ApplicationRepresentation {
-    protected String id;
+@Deprecated
+public class ApplicationRepresentation extends ClientRepresentation {
     protected String name;
-    protected String adminUrl;
-    protected String baseUrl;
-    protected Boolean surrogateAuthRequired;
-    protected Boolean enabled;
-    protected String secret;
-    protected String[] defaultRoles;
-    protected List<String> redirectUris;
-    protected List<String> webOrigins;
     @Deprecated
     protected ClaimRepresentation claims;
-    protected Integer notBefore;
-    protected Boolean bearerOnly;
-    protected Boolean publicClient;
-    protected Boolean frontchannelLogout;
-    protected String protocol;
-    protected Map<String, String> attributes;
-    protected Boolean fullScopeAllowed;
-    protected Integer nodeReRegistrationTimeout;
-    protected Map<String, Integer> registeredNodes;
-    protected List<ClientIdentityProviderMappingRepresentation> identityProviders;
-    protected List<ProtocolMapperRepresentation> protocolMappers;
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
 
     public String getName() {
         return name;
@@ -48,70 +18,6 @@ public class ApplicationRepresentation {
         this.name = name;
     }
 
-    public Boolean isEnabled() {
-        return enabled;
-    }
-
-    public void setEnabled(Boolean enabled) {
-        this.enabled = enabled;
-    }
-
-    public Boolean isSurrogateAuthRequired() {
-        return surrogateAuthRequired;
-    }
-
-    public void setSurrogateAuthRequired(Boolean surrogateAuthRequired) {
-        this.surrogateAuthRequired = surrogateAuthRequired;
-    }
-
-    public String getAdminUrl() {
-        return adminUrl;
-    }
-
-    public void setAdminUrl(String adminUrl) {
-        this.adminUrl = adminUrl;
-    }
-
-    public String getBaseUrl() {
-        return baseUrl;
-    }
-
-    public void setBaseUrl(String baseUrl) {
-        this.baseUrl = baseUrl;
-    }
-
-    public String getSecret() {
-        return secret;
-    }
-
-    public void setSecret(String secret) {
-        this.secret = secret;
-    }
-
-    public List<String> getRedirectUris() {
-        return redirectUris;
-    }
-
-    public void setRedirectUris(List<String> redirectUris) {
-        this.redirectUris = redirectUris;
-    }
-
-    public List<String> getWebOrigins() {
-        return webOrigins;
-    }
-
-    public void setWebOrigins(List<String> webOrigins) {
-        this.webOrigins = webOrigins;
-    }
-
-    public String[] getDefaultRoles() {
-        return defaultRoles;
-    }
-
-    public void setDefaultRoles(String[] defaultRoles) {
-        this.defaultRoles = defaultRoles;
-    }
-
     public ClaimRepresentation getClaims() {
         return claims;
     }
@@ -119,92 +25,4 @@ public class ApplicationRepresentation {
     public void setClaims(ClaimRepresentation claims) {
         this.claims = claims;
     }
-
-    public Integer getNotBefore() {
-        return notBefore;
-    }
-
-    public void setNotBefore(Integer notBefore) {
-        this.notBefore = notBefore;
-    }
-
-    public Boolean isBearerOnly() {
-        return bearerOnly;
-    }
-
-    public void setBearerOnly(Boolean bearerOnly) {
-        this.bearerOnly = bearerOnly;
-    }
-
-    public Boolean isPublicClient() {
-        return publicClient;
-    }
-
-    public void setPublicClient(Boolean publicClient) {
-        this.publicClient = publicClient;
-    }
-
-    public Boolean isFullScopeAllowed() {
-        return fullScopeAllowed;
-    }
-
-    public void setFullScopeAllowed(Boolean fullScopeAllowed) {
-        this.fullScopeAllowed = fullScopeAllowed;
-    }
-
-    public String getProtocol() {
-        return protocol;
-    }
-
-    public void setProtocol(String protocol) {
-        this.protocol = protocol;
-    }
-
-    public Map<String, String> getAttributes() {
-        return attributes;
-    }
-
-    public void setAttributes(Map<String, String> attributes) {
-        this.attributes = attributes;
-    }
-
-    public Integer getNodeReRegistrationTimeout() {
-        return nodeReRegistrationTimeout;
-    }
-
-    public void setNodeReRegistrationTimeout(Integer nodeReRegistrationTimeout) {
-        this.nodeReRegistrationTimeout = nodeReRegistrationTimeout;
-    }
-
-    public Map<String, Integer> getRegisteredNodes() {
-        return registeredNodes;
-    }
-
-    public void setRegisteredNodes(Map<String, Integer> registeredNodes) {
-        this.registeredNodes = registeredNodes;
-    }
-
-    public Boolean isFrontchannelLogout() {
-        return frontchannelLogout;
-    }
-
-    public void setFrontchannelLogout(Boolean frontchannelLogout) {
-        this.frontchannelLogout = frontchannelLogout;
-    }
-
-    public List<ClientIdentityProviderMappingRepresentation> getIdentityProviders() {
-        return this.identityProviders;
-    }
-
-    public void setIdentityProviders(List<ClientIdentityProviderMappingRepresentation> identityProviders) {
-        this.identityProviders = identityProviders;
-    }
-
-    public List<ProtocolMapperRepresentation> getProtocolMappers() {
-        return protocolMappers;
-    }
-
-    public void setProtocolMappers(List<ProtocolMapperRepresentation> protocolMappers) {
-        this.protocolMappers = protocolMappers;
-    }
 }
diff --git a/core/src/main/java/org/keycloak/representations/idm/ClientRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ClientRepresentation.java
new file mode 100755
index 0000000..de40f10
--- /dev/null
+++ b/core/src/main/java/org/keycloak/representations/idm/ClientRepresentation.java
@@ -0,0 +1,218 @@
+package org.keycloak.representations.idm;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ClientRepresentation {
+    protected String id;
+    protected String clientId;
+    protected String adminUrl;
+    protected String baseUrl;
+    protected Boolean surrogateAuthRequired;
+    protected Boolean enabled;
+    protected String secret;
+    protected String[] defaultRoles;
+    protected List<String> redirectUris;
+    protected List<String> webOrigins;
+    protected Integer notBefore;
+    protected Boolean bearerOnly;
+    protected Boolean consentRequired;
+    protected Boolean directGrantsOnly;
+    protected Boolean publicClient;
+    protected Boolean frontchannelLogout;
+    protected String protocol;
+    protected Map<String, String> attributes;
+    protected Boolean fullScopeAllowed;
+    protected Integer nodeReRegistrationTimeout;
+    protected Map<String, Integer> registeredNodes;
+    protected List<ClientIdentityProviderMappingRepresentation> identityProviders;
+    protected List<ProtocolMapperRepresentation> protocolMappers;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getClientId() {
+        return clientId;
+    }
+
+    public void setClientId(String clientId) {
+        this.clientId = clientId;
+    }
+
+    public Boolean isEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(Boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    public Boolean isSurrogateAuthRequired() {
+        return surrogateAuthRequired;
+    }
+
+    public void setSurrogateAuthRequired(Boolean surrogateAuthRequired) {
+        this.surrogateAuthRequired = surrogateAuthRequired;
+    }
+
+    public String getAdminUrl() {
+        return adminUrl;
+    }
+
+    public void setAdminUrl(String adminUrl) {
+        this.adminUrl = adminUrl;
+    }
+
+    public String getBaseUrl() {
+        return baseUrl;
+    }
+
+    public void setBaseUrl(String baseUrl) {
+        this.baseUrl = baseUrl;
+    }
+
+    public String getSecret() {
+        return secret;
+    }
+
+    public void setSecret(String secret) {
+        this.secret = secret;
+    }
+
+    public List<String> getRedirectUris() {
+        return redirectUris;
+    }
+
+    public void setRedirectUris(List<String> redirectUris) {
+        this.redirectUris = redirectUris;
+    }
+
+    public List<String> getWebOrigins() {
+        return webOrigins;
+    }
+
+    public void setWebOrigins(List<String> webOrigins) {
+        this.webOrigins = webOrigins;
+    }
+
+    public String[] getDefaultRoles() {
+        return defaultRoles;
+    }
+
+    public void setDefaultRoles(String[] defaultRoles) {
+        this.defaultRoles = defaultRoles;
+    }
+
+    public Integer getNotBefore() {
+        return notBefore;
+    }
+
+    public void setNotBefore(Integer notBefore) {
+        this.notBefore = notBefore;
+    }
+
+    public Boolean isBearerOnly() {
+        return bearerOnly;
+    }
+
+    public void setBearerOnly(Boolean bearerOnly) {
+        this.bearerOnly = bearerOnly;
+    }
+
+    public Boolean isConsentRequired() {
+        return consentRequired;
+    }
+
+    public void setConsentRequired(Boolean consentRequired) {
+        this.consentRequired = consentRequired;
+    }
+
+    public Boolean getDirectGrantsOnly() {
+        return directGrantsOnly;
+    }
+
+    public void setDirectGrantsOnly(Boolean directGrantsOnly) {
+        this.directGrantsOnly = directGrantsOnly;
+    }
+
+    public Boolean isPublicClient() {
+        return publicClient;
+    }
+
+    public void setPublicClient(Boolean publicClient) {
+        this.publicClient = publicClient;
+    }
+
+    public Boolean isFullScopeAllowed() {
+        return fullScopeAllowed;
+    }
+
+    public void setFullScopeAllowed(Boolean fullScopeAllowed) {
+        this.fullScopeAllowed = fullScopeAllowed;
+    }
+
+    public String getProtocol() {
+        return protocol;
+    }
+
+    public void setProtocol(String protocol) {
+        this.protocol = protocol;
+    }
+
+    public Map<String, String> getAttributes() {
+        return attributes;
+    }
+
+    public void setAttributes(Map<String, String> attributes) {
+        this.attributes = attributes;
+    }
+
+    public Integer getNodeReRegistrationTimeout() {
+        return nodeReRegistrationTimeout;
+    }
+
+    public void setNodeReRegistrationTimeout(Integer nodeReRegistrationTimeout) {
+        this.nodeReRegistrationTimeout = nodeReRegistrationTimeout;
+    }
+
+    public Map<String, Integer> getRegisteredNodes() {
+        return registeredNodes;
+    }
+
+    public void setRegisteredNodes(Map<String, Integer> registeredNodes) {
+        this.registeredNodes = registeredNodes;
+    }
+
+    public Boolean isFrontchannelLogout() {
+        return frontchannelLogout;
+    }
+
+    public void setFrontchannelLogout(Boolean frontchannelLogout) {
+        this.frontchannelLogout = frontchannelLogout;
+    }
+
+    public List<ClientIdentityProviderMappingRepresentation> getIdentityProviders() {
+        return this.identityProviders;
+    }
+
+    public void setIdentityProviders(List<ClientIdentityProviderMappingRepresentation> identityProviders) {
+        this.identityProviders = identityProviders;
+    }
+
+    public List<ProtocolMapperRepresentation> getProtocolMappers() {
+        return protocolMappers;
+    }
+
+    public void setProtocolMappers(List<ProtocolMapperRepresentation> protocolMappers) {
+        this.protocolMappers = protocolMappers;
+    }
+}
diff --git a/core/src/main/java/org/keycloak/representations/idm/MappingsRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/MappingsRepresentation.java
index 8172a2a..b7e90b8 100755
--- a/core/src/main/java/org/keycloak/representations/idm/MappingsRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/MappingsRepresentation.java
@@ -9,7 +9,7 @@ import java.util.Map;
  */
 public class MappingsRepresentation {
     protected List<RoleRepresentation> realmMappings;
-    protected Map<String, ApplicationMappingsRepresentation> applicationMappings;
+    protected Map<String, ClientMappingsRepresentation> clientMappings;
 
     public List<RoleRepresentation> getRealmMappings() {
         return realmMappings;
@@ -19,11 +19,11 @@ public class MappingsRepresentation {
         this.realmMappings = realmMappings;
     }
 
-    public Map<String, ApplicationMappingsRepresentation> getApplicationMappings() {
-        return applicationMappings;
+    public Map<String, ClientMappingsRepresentation> getClientMappings() {
+        return clientMappings;
     }
 
-    public void setApplicationMappings(Map<String, ApplicationMappingsRepresentation> applicationMappings) {
-        this.applicationMappings = applicationMappings;
+    public void setClientMappings(Map<String, ClientMappingsRepresentation> clientMappings) {
+        this.clientMappings = clientMappings;
     }
 }
diff --git a/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java
index 5f0ed4e..9eec3e9 100755
--- a/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java
@@ -1,157 +1,9 @@
 package org.keycloak.representations.idm;
 
-import java.util.List;
-import java.util.Map;
-
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public class OAuthClientRepresentation {
-    protected String id;
-    protected String name;
-    protected List<String> redirectUris;
-    protected List<String> webOrigins;
-    protected Boolean enabled;
-    protected String secret;
-    @Deprecated
-    protected ClaimRepresentation claims;
-    protected Integer notBefore;
-    protected Boolean publicClient;
-    protected String protocol;
-    protected Map<String, String> attributes;
-    protected Boolean directGrantsOnly;
-    protected Boolean fullScopeAllowed;
-    protected Boolean frontchannelLogout;
-    protected List<ProtocolMapperRepresentation> protocolMappers;
-    private List<ClientIdentityProviderMappingRepresentation> identityProviders;
-
-
-    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 Boolean isEnabled() {
-        return enabled;
-    }
-
-    public void setEnabled(Boolean enabled) {
-        this.enabled = enabled;
-    }
-
-    public List<String> getRedirectUris() {
-        return redirectUris;
-    }
-
-    public void setRedirectUris(List<String> redirectUris) {
-        this.redirectUris = redirectUris;
-    }
-
-    public List<String> getWebOrigins() {
-        return webOrigins;
-    }
-
-    public void setWebOrigins(List<String> webOrigins) {
-        this.webOrigins = webOrigins;
-    }
-
-    public String getSecret() {
-        return secret;
-    }
-
-    public void setSecret(String secret) {
-        this.secret = secret;
-    }
-
-    public ClaimRepresentation getClaims() {
-        return claims;
-    }
-
-    public void setClaims(ClaimRepresentation claims) {
-        this.claims = claims;
-    }
-
-    public Integer getNotBefore() {
-        return notBefore;
-    }
-
-    public void setNotBefore(Integer notBefore) {
-        this.notBefore = notBefore;
-    }
-
-    public Boolean isPublicClient() {
-        return publicClient;
-    }
-
-    public void setPublicClient(Boolean publicClient) {
-        this.publicClient = publicClient;
-    }
-
-    public Boolean isDirectGrantsOnly() {
-        return directGrantsOnly;
-    }
-
-    public void setDirectGrantsOnly(Boolean directGrantsOnly) {
-        this.directGrantsOnly = directGrantsOnly;
-    }
-
-    public Boolean isFullScopeAllowed() {
-        return fullScopeAllowed;
-    }
-
-    public void setFullScopeAllowed(Boolean fullScopeAllowed) {
-        this.fullScopeAllowed = fullScopeAllowed;
-    }
-
-    public String getProtocol() {
-        return protocol;
-    }
-
-    public void setProtocol(String protocol) {
-        this.protocol = protocol;
-    }
-
-    public Map<String, String> getAttributes() {
-        return attributes;
-    }
-
-    public void setAttributes(Map<String, String> attributes) {
-        this.attributes = attributes;
-    }
-
-    public Boolean isFrontchannelLogout() {
-        return frontchannelLogout;
-    }
-
-    public void setFrontchannelLogout(Boolean frontchannelLogout) {
-        this.frontchannelLogout = frontchannelLogout;
-    }
-
-    public List<ClientIdentityProviderMappingRepresentation> getIdentityProviders() {
-        return this.identityProviders;
-    }
-
-    public void setIdentityProviders(List<ClientIdentityProviderMappingRepresentation> identityProviders) {
-        this.identityProviders = identityProviders;
-    }
-
-    public List<ProtocolMapperRepresentation> getProtocolMappers() {
-        return protocolMappers;
-    }
-
-    public void setProtocolMappers(List<ProtocolMapperRepresentation> protocolMappers) {
-        this.protocolMappers = protocolMappers;
-    }
+@Deprecated
+public class OAuthClientRepresentation extends ApplicationRepresentation {
 }
diff --git a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
index b350e38..cbd5a77 100755
--- a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
@@ -25,13 +25,6 @@ public class RealmRepresentation {
     protected Boolean verifyEmail;
     protected Boolean resetPasswordAllowed;
 
-    @Deprecated
-    protected Boolean social;
-    @Deprecated
-    protected Boolean updateProfileOnInitialSocialLogin;
-    @Deprecated
-    protected Map<String, String> socialProviders;
-
     protected Boolean userCacheEnabled;
     protected Boolean realmCacheEnabled;
 
@@ -55,9 +48,8 @@ public class RealmRepresentation {
     protected String passwordPolicy;
     protected List<UserRepresentation> users;
     protected List<ScopeMappingRepresentation> scopeMappings;
-    protected Map<String, List<ScopeMappingRepresentation>> applicationScopeMappings;
-    protected List<ApplicationRepresentation> applications;
-    protected List<OAuthClientRepresentation> oauthClients;
+    protected Map<String, List<ScopeMappingRepresentation>> clientScopeMappings;
+    protected List<ClientRepresentation> clients;
     protected Map<String, String> browserSecurityHeaders;
     protected Map<String, String> smtpServer;
     protected List<UserFederationProviderRepresentation> userFederationProviders;
@@ -76,6 +68,18 @@ public class RealmRepresentation {
     protected Set<String> supportedLocales;
     protected String defaultLocale;
 
+    @Deprecated
+    protected Boolean social;
+    @Deprecated
+    protected Boolean updateProfileOnInitialSocialLogin;
+    @Deprecated
+    protected Map<String, String> socialProviders;
+    @Deprecated
+    protected Map<String, List<ScopeMappingRepresentation>> applicationScopeMappings;
+    @Deprecated
+    protected List<ApplicationRepresentation> applications;
+    @Deprecated
+    protected List<OAuthClientRepresentation> oauthClients;
 
     public String getId() {
         return id;
@@ -101,14 +105,6 @@ public class RealmRepresentation {
         return applications;
     }
 
-    public ApplicationRepresentation resource(String name) {
-        ApplicationRepresentation resource = new ApplicationRepresentation();
-        if (applications == null) applications = new ArrayList<ApplicationRepresentation>();
-        applications.add(resource);
-        resource.setName(name);
-        return resource;
-    }
-
     public void setUsers(List<UserRepresentation> users) {
         this.users = users;
     }
@@ -121,8 +117,12 @@ public class RealmRepresentation {
         return user;
     }
 
-    public void setApplications(List<ApplicationRepresentation> applications) {
-        this.applications = applications;
+    public List<ClientRepresentation> getClients() {
+        return clients;
+    }
+
+    public void setClients(List<ClientRepresentation> clients) {
+        this.clients = clients;
     }
 
     public Boolean isEnabled() {
@@ -321,22 +321,16 @@ public class RealmRepresentation {
         this.resetPasswordAllowed = resetPassword;
     }
 
+    @Deprecated
     public Boolean isSocial() {
         return social;
     }
 
-    public void setSocial(Boolean social) {
-        this.social = social;
-    }
-
+    @Deprecated
     public Boolean isUpdateProfileOnInitialSocialLogin() {
         return updateProfileOnInitialSocialLogin;
     }
 
-    public void setUpdateProfileOnInitialSocialLogin(Boolean updateProfileOnInitialSocialLogin) {
-        this.updateProfileOnInitialSocialLogin = updateProfileOnInitialSocialLogin;
-    }
-
     public Map<String, String> getBrowserSecurityHeaders() {
         return browserSecurityHeaders;
     }
@@ -345,14 +339,11 @@ public class RealmRepresentation {
         this.browserSecurityHeaders = browserSecurityHeaders;
     }
 
+    @Deprecated
     public Map<String, String> getSocialProviders() {
         return socialProviders;
     }
 
-    public void setSocialProviders(Map<String, String> socialProviders) {
-        this.socialProviders = socialProviders;
-    }
-
     public Map<String, String> getSmtpServer() {
         return smtpServer;
     }
@@ -361,20 +352,22 @@ public class RealmRepresentation {
         this.smtpServer = smtpServer;
     }
 
+    @Deprecated
     public List<OAuthClientRepresentation> getOauthClients() {
         return oauthClients;
     }
 
-    public void setOauthClients(List<OAuthClientRepresentation> oauthClients) {
-        this.oauthClients = oauthClients;
+    public Map<String, List<ScopeMappingRepresentation>> getClientScopeMappings() {
+        return clientScopeMappings;
     }
 
-    public Map<String, List<ScopeMappingRepresentation>> getApplicationScopeMappings() {
-        return applicationScopeMappings;
+    public void setClientScopeMappings(Map<String, List<ScopeMappingRepresentation>> clientScopeMappings) {
+        this.clientScopeMappings = clientScopeMappings;
     }
 
-    public void setApplicationScopeMappings(Map<String, List<ScopeMappingRepresentation>> applicationScopeMappings) {
-        this.applicationScopeMappings = applicationScopeMappings;
+    @Deprecated
+    public Map<String, List<ScopeMappingRepresentation>> getApplicationScopeMappings() {
+        return applicationScopeMappings;
     }
 
     public RolesRepresentation getRoles() {
diff --git a/core/src/main/java/org/keycloak/representations/idm/RoleRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/RoleRepresentation.java
index 34ea91f..9d0909d 100755
--- a/core/src/main/java/org/keycloak/representations/idm/RoleRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/RoleRepresentation.java
@@ -17,9 +17,10 @@ public class RoleRepresentation {
 
     public static class Composites {
         protected Set<String> realm;
+        protected Map<String, List<String>> client;
+        @Deprecated
         protected Map<String, List<String>> application;
 
-
         public Set<String> getRealm() {
             return realm;
         }
@@ -28,12 +29,17 @@ public class RoleRepresentation {
             this.realm = realm;
         }
 
-        public Map<String, List<String>> getApplication() {
-            return application;
+        public Map<String, List<String>> getClient() {
+            return client;
         }
 
-        public void setApplication(Map<String, List<String>> application) {
-            this.application = application;
+        public void setClient(Map<String, List<String>> client) {
+            this.client = client;
+        }
+
+        @Deprecated
+        public Map<String, List<String>> getApplication() {
+            return application;
         }
     }
 
diff --git a/core/src/main/java/org/keycloak/representations/idm/RolesRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/RolesRepresentation.java
index 496f738..afeb96a 100755
--- a/core/src/main/java/org/keycloak/representations/idm/RolesRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/RolesRepresentation.java
@@ -9,6 +9,8 @@ import java.util.Map;
  */
 public class RolesRepresentation {
     protected List<RoleRepresentation> realm;
+    protected Map<String, List<RoleRepresentation>> client;
+    @Deprecated
     protected Map<String, List<RoleRepresentation>> application;
 
     public List<RoleRepresentation> getRealm() {
@@ -19,11 +21,16 @@ public class RolesRepresentation {
         this.realm = realm;
     }
 
-    public Map<String, List<RoleRepresentation>> getApplication() {
-        return application;
+    public Map<String, List<RoleRepresentation>> getClient() {
+        return client;
+    }
+
+    public void setClient(Map<String, List<RoleRepresentation>> client) {
+        this.client = client;
     }
 
-    public void setApplication(Map<String, List<RoleRepresentation>> application) {
-        this.application = application;
+    @Deprecated
+    public Map<String, List<RoleRepresentation>> getApplication() {
+        return application;
     }
 }
diff --git a/core/src/main/java/org/keycloak/representations/idm/UserRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/UserRepresentation.java
index d2907d5..94a90d9 100755
--- a/core/src/main/java/org/keycloak/representations/idm/UserRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/UserRepresentation.java
@@ -25,10 +25,13 @@ public class UserRepresentation {
     protected List<CredentialRepresentation> credentials;
     protected List<String> requiredActions;
     protected List<FederatedIdentityRepresentation> federatedIdentities;
-    @Deprecated
-    protected List<SocialLinkRepresentation> socialLinks;
     protected List<String> realmRoles;
+    protected Map<String, List<String>> clientRoles;
+
+    @Deprecated
     protected Map<String, List<String>> applicationRoles;
+    @Deprecated
+    protected List<SocialLinkRepresentation> socialLinks;
 
     public String getSelf() {
         return self;
@@ -165,12 +168,17 @@ public class UserRepresentation {
         this.realmRoles = realmRoles;
     }
 
-    public Map<String, List<String>> getApplicationRoles() {
-        return applicationRoles;
+    public Map<String, List<String>> getClientRoles() {
+        return clientRoles;
+    }
+
+    public void setClientRoles(Map<String, List<String>> clientRoles) {
+        this.clientRoles = clientRoles;
     }
 
-    public void setApplicationRoles(Map<String, List<String>> applicationRoles) {
-        this.applicationRoles = applicationRoles;
+    @Deprecated
+    public Map<String, List<String>> getApplicationRoles() {
+        return applicationRoles;
     }
 
     public String getFederationLink() {
diff --git a/core/src/main/java/org/keycloak/representations/idm/UserSessionRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/UserSessionRepresentation.java
index 3035d2d..6701f6a 100755
--- a/core/src/main/java/org/keycloak/representations/idm/UserSessionRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/UserSessionRepresentation.java
@@ -15,7 +15,6 @@ public class UserSessionRepresentation {
     private String ipAddress;
     private long start;
     private long lastAccess;
-    private Map<String, String> applications = new HashMap<String, String>();
     private Map<String, String> clients = new HashMap<String, String>();
 
     public String getId() {
@@ -58,14 +57,6 @@ public class UserSessionRepresentation {
         this.lastAccess = lastAccess;
     }
 
-    public Map<String, String> getApplications() {
-        return applications;
-    }
-
-    public void setApplications(Map<String, String> applications) {
-        this.applications = applications;
-    }
-
     public Map<String, String> getClients() {
         return clients;
     }
diff --git a/core/src/main/java/org/keycloak/util/Time.java b/core/src/main/java/org/keycloak/util/Time.java
index 7da54f1..a5334dd 100644
--- a/core/src/main/java/org/keycloak/util/Time.java
+++ b/core/src/main/java/org/keycloak/util/Time.java
@@ -17,6 +17,10 @@ public class Time {
         return new Date(((long) time ) * 1000);
     }
 
+    public static long toMillis(int time) {
+        return ((long) time) * 1000;
+    }
+
     public static void setOffset(int offset) {
         Time.offset = offset;
     }
diff --git a/dependencies/server-all/pom.xml b/dependencies/server-all/pom.xml
index 9d8921f..d124ea5 100755
--- a/dependencies/server-all/pom.xml
+++ b/dependencies/server-all/pom.xml
@@ -144,34 +144,6 @@
             <artifactId>keycloak-kerberos-federation</artifactId>
             <version>${project.version}</version>
         </dependency>
-        <dependency>
-            <groupId>org.picketlink</groupId>
-            <artifactId>picketlink-common</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.picketlink</groupId>
-            <artifactId>picketlink-idm-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.picketlink</groupId>
-            <artifactId>picketlink-idm-impl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.picketlink</groupId>
-            <artifactId>picketlink-idm-simple-schema</artifactId>
-        </dependency>
-
-        <!-- picketlink -->
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-picketlink-api</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-picketlink-ldap</artifactId>
-            <version>${project.version}</version>
-        </dependency>
 
         <!-- saml -->
         <dependency>
diff --git a/distribution/modules/build.xml b/distribution/modules/build.xml
index 9f65cb9..df4bef5 100755
--- a/distribution/modules/build.xml
+++ b/distribution/modules/build.xml
@@ -259,14 +259,6 @@
             <maven-resource group="org.keycloak" artifact="keycloak-ldap-federation"/>
         </module-def>
 
-        <module-def name="org.keycloak.keycloak-picketlink-api">
-            <maven-resource group="org.keycloak" artifact="keycloak-picketlink-api"/>
-        </module-def>
-
-        <module-def name="org.keycloak.keycloak-picketlink-ldap">
-            <maven-resource group="org.keycloak" artifact="keycloak-picketlink-ldap"/>
-        </module-def>
-
         <module-def name="org.keycloak.keycloak-saml-core">
             <maven-resource group="org.keycloak" artifact="keycloak-saml-core"/>
         </module-def>
diff --git a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-ldap-federation/main/module.xml b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-ldap-federation/main/module.xml
index 29dfd9c..5f88f37 100755
--- a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-ldap-federation/main/module.xml
+++ b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-ldap-federation/main/module.xml
@@ -10,14 +10,9 @@
         <module name="org.keycloak.keycloak-core"/>
         <module name="org.keycloak.keycloak-model-api"/>
         <module name="org.keycloak.keycloak-kerberos-federation"/>
-        <module name="org.keycloak.keycloak-picketlink-api"/>
         <module name="javax.ws.rs.api"/>
         <module name="org.jboss.resteasy.resteasy-jaxrs"/>
         <module name="org.jboss.logging"/>
-        <module name="org.picketlink.common"/>
-        <module name="org.picketlink.idm.api"/>
-        <module name="org.picketlink.idm"/>
-        <module name="org.picketlink.idm.schema"/>
         <module name="javax.api"/>
     </dependencies>
 
diff --git a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-server/main/module.xml b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-server/main/module.xml
index f553d24..ddf2475 100755
--- a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-server/main/module.xml
+++ b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-server/main/module.xml
@@ -48,8 +48,6 @@
         <module name="org.keycloak.keycloak-model-sessions-jpa" services="import"/>
         <module name="org.keycloak.keycloak-model-sessions-mem" services="import"/>
         <module name="org.keycloak.keycloak-model-sessions-mongo" services="import"/>
-        <module name="org.keycloak.keycloak-picketlink-api" services="import"/>
-        <module name="org.keycloak.keycloak-picketlink-ldap" services="import"/>
         <module name="org.keycloak.keycloak-saml-protocol" services="import"/>
         <module name="org.keycloak.keycloak-services" export="true" services="import"/>
         <module name="org.keycloak.keycloak-social-core" services="import"/>
diff --git a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-services/main/module.xml b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-services/main/module.xml
index 86e86f4..9864a07 100755
--- a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-services/main/module.xml
+++ b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-services/main/module.xml
@@ -49,10 +49,8 @@
         <module name="org.keycloak.keycloak-model-sessions-jpa" services="import"/>
         <module name="org.keycloak.keycloak-model-sessions-mem" services="import"/>
         <module name="org.keycloak.keycloak-model-sessions-mongo" services="import"/>
-        <module name="org.keycloak.keycloak-picketlink-api" services="import"/>
         <module name="org.keycloak.keycloak-wildfly-extensions" services="import"/>
 
-        <module name="org.keycloak.keycloak-picketlink-ldap" services="import"/>
         <module name="org.keycloak.keycloak-saml-protocol" services="import"/>
         <module name="org.keycloak.keycloak-services" export="true" services="import"/>
         <module name="org.keycloak.keycloak-social-core" services="import"/>
diff --git a/distribution/subsystem-war/src/main/webapp/WEB-INF/jboss-deployment-structure.xml b/distribution/subsystem-war/src/main/webapp/WEB-INF/jboss-deployment-structure.xml
index 6caa2c8..aae18bf 100755
--- a/distribution/subsystem-war/src/main/webapp/WEB-INF/jboss-deployment-structure.xml
+++ b/distribution/subsystem-war/src/main/webapp/WEB-INF/jboss-deployment-structure.xml
@@ -40,9 +40,6 @@
             <module name="org.keycloak.keycloak-model-sessions-jpa" services="import"/>
             <module name="org.keycloak.keycloak-model-sessions-mem" services="import"/>
             <module name="org.keycloak.keycloak-model-sessions-mongo" services="import"/>
-            <module name="org.keycloak.keycloak-picketlink-api" services="import"/>
-
-            <module name="org.keycloak.keycloak-picketlink-ldap" services="import"/>
             <module name="org.keycloak.keycloak-saml-protocol" services="import"/>
             <module name="org.keycloak.keycloak-services" export="true" services="import"/>
             <module name="org.keycloak.keycloak-social-core" services="import"/>
diff --git a/docbook/reference/en/en-US/modules/identity-broker.xml b/docbook/reference/en/en-US/modules/identity-broker.xml
index 397fd02..4c1a3c2 100755
--- a/docbook/reference/en/en-US/modules/identity-broker.xml
+++ b/docbook/reference/en/en-US/modules/identity-broker.xml
@@ -284,6 +284,15 @@
                             during the authentication process.
                         </entry>
                     </row>
+                    <row>
+                        <entry>
+                            <literal>GUI order</literal>
+                        </entry>
+                        <entry>
+                            Allows you to define order of the provider when shown on login page. 
+                            You can put number into this field, providers with lower numbers are shown first.
+                        </entry>
+                    </row>
                     <!--<row>-->
                         <!--<entry>-->
                             <!--<literal>Store Tokens</literal>-->
diff --git a/docbook/reference/en/en-US/modules/themes.xml b/docbook/reference/en/en-US/modules/themes.xml
index db3d659..cd59f38 100755
--- a/docbook/reference/en/en-US/modules/themes.xml
+++ b/docbook/reference/en/en-US/modules/themes.xml
@@ -80,7 +80,7 @@
 <programlisting>[<![CDATA[
 "theme": {
     "default": "keycloak",
-    "staticMaxAge": 01,
+    "staticMaxAge": -1,
     "cacheTemplates": false,
     "cacheThemes": false,
     "folder": {
@@ -205,7 +205,7 @@ import=common/keycloak
         </para>
         <para>
             To deploy a theme as a module you need to create an jar (it's basically just a zip with jar extension) with
-            the theme resources and a file <literal>META/keycloak-server.json</literal> that describes the themes contained
+            the theme resources and a file <literal>META/keycloak-themes.json</literal> that describes the themes contained
             in the archive. For example <literal>example-theme.jar</literal> with the contents:
             <itemizedlist>
                 <listitem>META-INF/keycloak-themes.json</listitem>
@@ -213,7 +213,7 @@ import=common/keycloak
                 <listitem>theme/example-theme/login/login.ftl</listitem>
                 <listitem>theme/example-theme/login/resources/css/styles.css</listitem>
             </itemizedlist>
-            The contents of META-INF/keycloak-server.json in this case would be:
+            The contents of META-INF/keycloak-themes.json in this case would be:
 <programlisting>[<![CDATA[
 {
     "themes": [{
diff --git a/examples/admin-client/example-realm.json b/examples/admin-client/example-realm.json
index 2615e56..3317f48 100755
--- a/examples/admin-client/example-realm.json
+++ b/examples/admin-client/example-realm.json
@@ -17,12 +17,12 @@
                     "value": "password"
                 }
             ],
-            "applicationRoles": {
+            "clientRoles": {
                 "realm-management": [ "realm-admin" ]
             }
         }
     ],
-    "applications": [
+    "clients": [
         {
             "name": "examples-admin-client",
             "enabled": true,
diff --git a/examples/admin-client/src/main/webapp/index.jsp b/examples/admin-client/src/main/webapp/index.jsp
index 13b6eee..980f196 100644
--- a/examples/admin-client/src/main/webapp/index.jsp
+++ b/examples/admin-client/src/main/webapp/index.jsp
@@ -1,5 +1,5 @@
 <%@ page import="org.keycloak.admin.client.Keycloak" %>
-<%@ page import="org.keycloak.admin.client.resource.ApplicationsResource" %>
+<%@ page import="org.keycloak.admin.client.resource.ClientsResource" %>
 <%@ page import="org.keycloak.representations.idm.ApplicationRepresentation" %>
 <%@ page import="org.keycloak.util.UriUtils" %>
 <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1" %>
@@ -13,7 +13,7 @@
     String authServer = UriUtils.getOrigin(request.getRequestURL().toString()) + "/auth";
 
     Keycloak keycloak = Keycloak.getInstance(authServer, "example", "examples-admin-client", "password", "examples-admin-client", "password");
-    ApplicationsResource applications = keycloak.realm("example").applications();
+    ClientsResource applications = keycloak.realm("example").applications();
 
     out.println("<h1>Applications</h1>");
     out.println("<ul>");
diff --git a/examples/basic-auth/basicauthrealm.json b/examples/basic-auth/basicauthrealm.json
index f6bac20..0ed1bf5 100644
--- a/examples/basic-auth/basicauthrealm.json
+++ b/examples/basic-auth/basicauthrealm.json
@@ -24,7 +24,7 @@
                     "value" : "password" }
             ],
             "realmRoles": [ "user","admin" ],
-            "applicationRoles": {
+            "clientRoles": {
                 "realm-management": [ "realm-admin" ]
             }
         }
@@ -41,7 +41,7 @@
             }
         ]
     },
-    "applications": [
+    "clients": [
         {
             "name": "basic-auth-service",
             "enabled": true,
diff --git a/examples/broker/facebook-authentication/facebook-identity-provider-realm.json b/examples/broker/facebook-authentication/facebook-identity-provider-realm.json
index 32a3704..cc8c636 100644
--- a/examples/broker/facebook-authentication/facebook-identity-provider-realm.json
+++ b/examples/broker/facebook-authentication/facebook-identity-provider-realm.json
@@ -17,7 +17,7 @@
                     "value" : "password" }
             ],
             "realmRoles": [ "user","admin" ],
-            "applicationRoles": {
+            "clientRoles": {
                 "realm-management": [ "realm-admin" ]
             }
         }
@@ -30,7 +30,7 @@
             }
         ]
     },
-    "applications": [
+    "clients": [
         {
             "name": "facebook-authentication",
             "enabled": true,
diff --git a/examples/broker/google-authentication/google-identity-provider-realm.json b/examples/broker/google-authentication/google-identity-provider-realm.json
index 8b4deef..a721e34 100644
--- a/examples/broker/google-authentication/google-identity-provider-realm.json
+++ b/examples/broker/google-authentication/google-identity-provider-realm.json
@@ -17,7 +17,7 @@
                     "value" : "password" }
             ],
             "realmRoles": [ "user","admin" ],
-            "applicationRoles": {
+            "clientRoles": {
                 "realm-management": [ "realm-admin" ]
             }
         }
@@ -30,7 +30,7 @@
             }
         ]
     },
-    "applications": [
+    "clients": [
         {
             "name": "google-authentication",
             "enabled": true,
diff --git a/examples/broker/saml-broker-authentication/saml-broker-authentication-realm.json b/examples/broker/saml-broker-authentication/saml-broker-authentication-realm.json
index f8fbc8a..ad757ab 100644
--- a/examples/broker/saml-broker-authentication/saml-broker-authentication-realm.json
+++ b/examples/broker/saml-broker-authentication/saml-broker-authentication-realm.json
@@ -17,7 +17,7 @@
                     "value" : "password" }
             ],
             "realmRoles": [ "user","admin" ],
-            "applicationRoles": {
+            "clientRoles": {
                 "realm-management": [ "realm-admin" ]
             }
         }
@@ -30,7 +30,7 @@
             }
         ]
     },
-    "applications": [
+    "clients": [
         {
             "name": "saml-broker-authentication",
             "enabled": true,
diff --git a/examples/broker/saml-broker-authentication/saml-broker-realm.json b/examples/broker/saml-broker-authentication/saml-broker-realm.json
index 7f1cde0..8d0bad4 100644
--- a/examples/broker/saml-broker-authentication/saml-broker-realm.json
+++ b/examples/broker/saml-broker-authentication/saml-broker-realm.json
@@ -26,7 +26,7 @@
             }
         ]
     },
-    "applications": [
+    "clients": [
         {
             "name": "http://localhost:8080/auth/realms/saml-broker-authentication-realm",
             "protocol": "saml",
diff --git a/examples/broker/twitter-authentication/twitter-identity-provider-realm.json b/examples/broker/twitter-authentication/twitter-identity-provider-realm.json
index 4b70904..f9add02 100644
--- a/examples/broker/twitter-authentication/twitter-identity-provider-realm.json
+++ b/examples/broker/twitter-authentication/twitter-identity-provider-realm.json
@@ -18,7 +18,7 @@
                     "value" : "password" }
             ],
             "realmRoles": [ "user","admin" ],
-            "applicationRoles": {
+            "clientRoles": {
                 "realm-management": [ "realm-admin" ]
             }
         }
@@ -31,7 +31,7 @@
             }
         ]
     },
-    "applications": [
+    "clients": [
         {
             "name": "twitter-authentication",
             "enabled": true,
diff --git a/examples/cordova/example-realm.json b/examples/cordova/example-realm.json
index f0d6ad2..d07a5d3 100755
--- a/examples/cordova/example-realm.json
+++ b/examples/cordova/example-realm.json
@@ -18,7 +18,7 @@
                   "value" : "password" }
             ],
             "realmRoles": [ "user" ],
-            "applicationRoles": {
+            "clientRoles": {
                 "account": ["view-profile", "manage-account"]
             }
         }
@@ -41,7 +41,7 @@
             "roles": ["user"]
         }
     ],
-    "applications": [
+    "clients": [
         {
             "name": "cordova",
             "enabled": true,
@@ -50,7 +50,7 @@
             "webOrigins": ["localhost"]
         }
     ],
-    "applicationScopeMappings": {
+    "clientScopeMappings": {
         "account": [
             {
                 "client": "cordova",
diff --git a/examples/cors/cors-realm.json b/examples/cors/cors-realm.json
index ab08ee3..9e59580 100755
--- a/examples/cors/cors-realm.json
+++ b/examples/cors/cors-realm.json
@@ -23,7 +23,7 @@
                   "value" : "password" }
             ],
             "realmRoles": [ "user" ],
-            "applicationRoles": {
+            "clientRoles": {
                 "realm-management": [ "realm-admin" ]
             }
         }
@@ -42,7 +42,7 @@
             "roles": ["user"]
         }
     ],
-    "applications": [
+    "clients": [
         {
             "name": "angular-cors-product",
             "enabled": true,
@@ -56,7 +56,7 @@
             ]
         }
     ],
-    "applicationScopeMappings": {
+    "clientScopeMappings": {
         "realm-management": [
             {
                 "client": "angular-cors-product",
diff --git a/examples/demo-template/testrealm.json b/examples/demo-template/testrealm.json
index 031e20b..4b4d669 100755
--- a/examples/demo-template/testrealm.json
+++ b/examples/demo-template/testrealm.json
@@ -24,7 +24,7 @@
                     "value" : "password" }
             ],
             "realmRoles": [ "user" ],
-            "applicationRoles": {
+            "clientRoles": {
                 "account": [ "manage-account" ]
             }
         },
@@ -39,7 +39,7 @@
                     "value" : "password" }
             ],
             "realmRoles": [ "user" ],
-            "applicationRoles": {
+            "clientRoles": {
                 "account": [ "manage-account" ]
             }
         },
@@ -54,7 +54,7 @@
                     "value" : "password" }
             ],
             "realmRoles": [ "user" ],
-            "applicationRoles": {
+            "clientRoles": {
                 "account": [ "manage-account" ]
             }
         },
@@ -69,7 +69,7 @@
                     "value" : "password" }
             ],
             "realmRoles": [ "user","admin" ],
-            "applicationRoles": {
+            "clientRoles": {
                 "realm-management": [ "realm-admin" ]
             }
         }
@@ -92,7 +92,7 @@
             "roles": ["user"]
         }
     ],
-    "applications": [
+    "clients": [
         {
             "name": "customer-portal",
             "enabled": true,
@@ -146,12 +146,11 @@
             "adminUrl": "/database",
             "baseUrl": "/database",
             "bearerOnly": true
-        }
-    ],
-    "oauthClients": [
+        },
         {
             "name": "third-party",
             "enabled": true,
+            "consentRequired": true,
             "redirectUris": [
                 "/oauth-client/*",
                 "/oauth-client-cdi/*"
@@ -162,11 +161,11 @@
             "name": "admin-client",
             "enabled": true,
             "publicClient": true,
-            "directGrantsOnly": true
-
+            "directGrantsOnly": true,
+            "consentRequired": true
         }
     ],
-    "applicationScopeMappings": {
+    "clientScopeMappings": {
         "realm-management": [
             {
                 "client": "admin-client",
diff --git a/examples/fuse/testrealm.json b/examples/fuse/testrealm.json
index 9ec73f9..d474e66 100644
--- a/examples/fuse/testrealm.json
+++ b/examples/fuse/testrealm.json
@@ -24,7 +24,7 @@
                     "value" : "password" }
             ],
             "realmRoles": [ "user" ],
-            "applicationRoles": {
+            "clientRoles": {
                 "account": [ "manage-account" ]
             }
         },
@@ -39,7 +39,7 @@
                     "value" : "password" }
             ],
             "realmRoles": [ "user" ],
-            "applicationRoles": {
+            "clientRoles": {
                 "account": [ "manage-account" ]
             }
         },
@@ -54,7 +54,7 @@
                     "value" : "password" }
             ],
             "realmRoles": [ "user" ],
-            "applicationRoles": {
+            "clientRoles": {
                 "account": [ "manage-account" ]
             }
         },
@@ -69,7 +69,7 @@
                     "value" : "password" }
             ],
             "realmRoles": [ "user","admin" ],
-            "applicationRoles": {
+            "clientRoles": {
                 "realm-management": [ "realm-admin" ]
             }
         },
@@ -84,7 +84,7 @@
                   "value" : "password" }
             ],
             "realmRoles": [ "user", "jmxAdmin" ],
-            "applicationRoles": {
+            "clientRoles": {
                 "account": [ "manage-account" ],
                 "realm-management": [ "realm-admin" ]
             }
@@ -134,7 +134,7 @@
             }
         ]
     },
-    "applications": [
+    "clients": [
         {
             "name": "customer-portal",
             "enabled": true,
@@ -178,14 +178,13 @@
             "adminUrl": "http://localhost:8383/admin-camel-endpoint",
             "baseUrl": "http://localhost:8383/admin-camel-endpoint",
             "bearerOnly": true
-        }
-    ],
-    "oauthClients": [
+        },
         {
             "name": "ssh-jmx-admin-client",
             "enabled": true,
             "publicClient": false,
             "directGrantsOnly": true,
+            "consentRequired": true,
             "secret": "password"
         }
     ],
diff --git a/examples/js-console/example-realm.json b/examples/js-console/example-realm.json
index ddbb6ea..81c92aa 100755
--- a/examples/js-console/example-realm.json
+++ b/examples/js-console/example-realm.json
@@ -18,7 +18,7 @@
                   "value" : "password" }
             ],
             "realmRoles": [ "user" ],
-            "applicationRoles": {
+            "clientRoles": {
                 "account": ["view-profile", "manage-account"]
             }
         }
@@ -41,7 +41,7 @@
             "roles": ["user"]
         }
     ],
-    "applications": [
+    "clients": [
         {
             "name": "js-console",
             "enabled": true,
@@ -53,7 +53,7 @@
             "webOrigins": []
         }
     ],
-    "applicationScopeMappings": {
+    "clientScopeMappings": {
         "account": [
             {
                 "client": "js-console",
diff --git a/examples/kerberos/kerberosrealm.json b/examples/kerberos/kerberosrealm.json
index 4339e36..006961c 100644
--- a/examples/kerberos/kerberosrealm.json
+++ b/examples/kerberos/kerberosrealm.json
@@ -13,7 +13,7 @@
             "roles": [ "user" ]
         }
     ],
-    "applications": [
+    "clients": [
         {
             "name": "kerberos-app",
             "enabled": true,
diff --git a/examples/multi-tenant/tenant1-realm.json b/examples/multi-tenant/tenant1-realm.json
index e7a9cc9..e759b12 100644
--- a/examples/multi-tenant/tenant1-realm.json
+++ b/examples/multi-tenant/tenant1-realm.json
@@ -20,7 +20,7 @@
                     "value" : "user-tenant1" }
             ],
             "realmRoles": [ "user" ],
-            "applicationRoles": {
+            "clientRoles": {
                 "multi-tenant": [ "user" ]
             }
         }
@@ -40,7 +40,7 @@
         }
 
     ],
-    "applications": [
+    "clients": [
         {
             "name": "multi-tenant",
             "enabled": true,
diff --git a/examples/multi-tenant/tenant2-realm.json b/examples/multi-tenant/tenant2-realm.json
index d628b73..2cd0e61 100644
--- a/examples/multi-tenant/tenant2-realm.json
+++ b/examples/multi-tenant/tenant2-realm.json
@@ -21,7 +21,7 @@
                     "value" : "user-tenant2" }
             ],
             "realmRoles": [ "user" ],
-            "applicationRoles": {
+            "clientRoles": {
                 "multi-tenant": [ "user" ]
             }
         }
@@ -41,9 +41,9 @@
         }
 
     ],
-    "applications": [
+    "clients": [
         {
-            "name": "multi-tenant",
+            "clientId": "multi-tenant",
             "enabled": true,
             "adminUrl": "/multitenant/tenant2",
             "baseUrl": "/multitenant/tenant2",
diff --git a/examples/saml/testsaml.json b/examples/saml/testsaml.json
index b7f66af..7cf4a8e 100755
--- a/examples/saml/testsaml.json
+++ b/examples/saml/testsaml.json
@@ -25,9 +25,9 @@
             "realmRoles": ["manager"]
         }
     ],
-    "applications": [
+    "clients": [
         {
-            "name": "http://localhost:8080/sales-post/",
+            "clientId": "http://localhost:8080/sales-post/",
             "enabled": true,
             "fullScopeAllowed": true,
             "protocol": "saml",
@@ -41,7 +41,7 @@
             }
         },
         {
-            "name": "http://localhost:8080/sales-post-sig/",
+            "clientId": "http://localhost:8080/sales-post-sig/",
             "enabled": true,
             "protocol": "saml",
             "fullScopeAllowed": true,
@@ -60,7 +60,7 @@
             }
         },
         {
-            "name": "http://localhost:8080/sales-post-enc/",
+            "clientId": "http://localhost:8080/sales-post-enc/",
             "enabled": true,
             "protocol": "saml",
             "fullScopeAllowed": true,
@@ -82,7 +82,7 @@
             }
         },
         {
-            "name": "http://localhost:8080/employee/",
+            "clientId": "http://localhost:8080/employee/",
             "enabled": true,
             "fullScopeAllowed": true,
             "protocol": "saml",
@@ -96,7 +96,7 @@
             }
         },
         {
-            "name": "http://localhost:8080/employee-sig/",
+            "clientId": "http://localhost:8080/employee-sig/",
             "enabled": true,
             "protocol": "saml",
             "fullScopeAllowed": true,
diff --git a/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ExportUtils.java b/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ExportUtils.java
index 9e68367..c404c3d 100755
--- a/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ExportUtils.java
+++ b/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ExportUtils.java
@@ -6,10 +6,8 @@ import org.codehaus.jackson.JsonFactory;
 import org.codehaus.jackson.JsonGenerator;
 import org.codehaus.jackson.map.ObjectMapper;
 import org.codehaus.jackson.map.SerializationConfig;
-import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleContainerModel;
 import org.keycloak.models.RoleModel;
@@ -18,9 +16,8 @@ import org.keycloak.models.UserCredentialValueModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.utils.ModelToRepresentation;
 import org.keycloak.representations.idm.ApplicationRepresentation;
-import org.keycloak.representations.idm.ClaimRepresentation;
+import org.keycloak.representations.idm.ClientRepresentation;
 import org.keycloak.representations.idm.CredentialRepresentation;
-import org.keycloak.representations.idm.OAuthClientRepresentation;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.representations.idm.RoleRepresentation;
 import org.keycloak.representations.idm.RolesRepresentation;
@@ -57,52 +54,41 @@ public class ExportUtils {
             rep.setEventsListeners(new LinkedList<String>(realm.getEventsListeners()));
         }
 
-        // Applications
-        List<ApplicationModel> applications = realm.getApplications();
-        List<ApplicationRepresentation> appReps = new ArrayList<ApplicationRepresentation>();
-        for (ApplicationModel app : applications) {
-            ApplicationRepresentation appRep = exportApplication(app);
-            appReps.add(appRep);
+        // Clients
+        List<ClientModel> clients = realm.getClients();
+        List<ClientRepresentation> clientReps = new ArrayList<>();
+        for (ClientModel app : clients) {
+            ClientRepresentation clientRep = exportClient(app);
+            clientReps.add(clientRep);
         }
-        rep.setApplications(appReps);
-
-        // OAuth clients
-        List<OAuthClientModel> oauthClients = realm.getOAuthClients();
-        List<OAuthClientRepresentation> oauthClientReps = new ArrayList<OAuthClientRepresentation>();
-        for (OAuthClientModel oauthClient : oauthClients) {
-            OAuthClientRepresentation clientRep = ModelToRepresentation.toRepresentation(oauthClient);
-            clientRep.setSecret(oauthClient.getSecret());
-            oauthClientReps.add(clientRep);
-        }
-        rep.setOauthClients(oauthClientReps);
+        rep.setClients(clientReps);
 
         // Roles
         List<RoleRepresentation> realmRoleReps = null;
-        Map<String, List<RoleRepresentation>> appRolesReps = new HashMap<String, List<RoleRepresentation>>();
+        Map<String, List<RoleRepresentation>> clientRolesReps = new HashMap<>();
 
         Set<RoleModel> realmRoles = realm.getRoles();
         if (realmRoles != null && realmRoles.size() > 0) {
             realmRoleReps = exportRoles(realmRoles);
         }
-        for (ApplicationModel app : applications) {
-            Set<RoleModel> currentAppRoles = app.getRoles();
+        for (ClientModel client : clients) {
+            Set<RoleModel> currentAppRoles = client.getRoles();
             List<RoleRepresentation> currentAppRoleReps = exportRoles(currentAppRoles);
-            appRolesReps.put(app.getName(), currentAppRoleReps);
+            clientRolesReps.put(client.getClientId(), currentAppRoleReps);
         }
 
         RolesRepresentation rolesRep = new RolesRepresentation();
         if (realmRoleReps != null) {
             rolesRep.setRealm(realmRoleReps);
         }
-        if (appRolesReps.size() > 0) {
-            rolesRep.setApplication(appRolesReps);
+        if (clientRolesReps.size() > 0) {
+            rolesRep.setClient(clientRolesReps);
         }
         rep.setRoles(rolesRep);
 
         // Scopes
-        List<ClientModel> allClients = new ArrayList<ClientModel>(applications);
-        allClients.addAll(realm.getOAuthClients());
-        Map<String, List<ScopeMappingRepresentation>> appScopeReps = new HashMap<String, List<ScopeMappingRepresentation>>();
+        List<ClientModel> allClients = new ArrayList<>(clients);
+        Map<String, List<ScopeMappingRepresentation>> clientScopeReps = new HashMap<>();
 
         for (ClientModel client : allClients) {
             Set<RoleModel> clientScopes = client.getScopeMappings();
@@ -114,12 +100,12 @@ public class ExportUtils {
                     }
                     scopeMappingRep.role(scope.getName());
                 } else {
-                    ApplicationModel app = (ApplicationModel)scope.getContainer();
-                    String appName = app.getName();
-                    List<ScopeMappingRepresentation> currentAppScopes = appScopeReps.get(appName);
+                    ClientModel app = (ClientModel)scope.getContainer();
+                    String appName = app.getClientId();
+                    List<ScopeMappingRepresentation> currentAppScopes = clientScopeReps.get(appName);
                     if (currentAppScopes == null) {
-                        currentAppScopes = new ArrayList<ScopeMappingRepresentation>();
-                        appScopeReps.put(appName, currentAppScopes);
+                        currentAppScopes = new ArrayList<>();
+                        clientScopeReps.put(appName, currentAppScopes);
                     }
 
                     ScopeMappingRepresentation currentClientScope = null;
@@ -139,8 +125,8 @@ public class ExportUtils {
             }
         }
 
-        if (appScopeReps.size() > 0) {
-            rep.setApplicationScopeMappings(appScopeReps);
+        if (clientScopeReps.size() > 0) {
+            rep.setClientScopeMappings(clientScopeReps);
         }
 
         // Finally users if needed
@@ -162,14 +148,13 @@ public class ExportUtils {
 
     /**
      * Full export of application including claims and secret
-     * @param app
+     * @param client
      * @return full ApplicationRepresentation
      */
-    public static ApplicationRepresentation exportApplication(ApplicationModel app) {
-        ApplicationRepresentation appRep = ModelToRepresentation.toRepresentation(app);
-
-        appRep.setSecret(app.getSecret());
-        return appRep;
+    public static ClientRepresentation exportClient(ClientModel client) {
+        ClientRepresentation clientRep = ModelToRepresentation.toRepresentation(client);
+        clientRep.setSecret(client.getSecret());
+        return clientRep;
     }
 
     public static List<RoleRepresentation> exportRoles(Collection<RoleModel> roles) {
@@ -201,27 +186,27 @@ public class ExportUtils {
         Set<RoleModel> composites = role.getComposites();
         if (composites != null && composites.size() > 0) {
             Set<String> compositeRealmRoles = null;
-            Map<String, List<String>> compositeAppRoles = null;
+            Map<String, List<String>> compositeClientRoles = null;
 
             for (RoleModel composite : composites) {
                 RoleContainerModel crContainer = composite.getContainer();
                 if (crContainer instanceof RealmModel) {
 
                     if (compositeRealmRoles == null) {
-                        compositeRealmRoles = new HashSet<String>();
+                        compositeRealmRoles = new HashSet<>();
                     }
                     compositeRealmRoles.add(composite.getName());
                 } else {
-                    if (compositeAppRoles == null) {
-                        compositeAppRoles = new HashMap<String, List<String>>();
+                    if (compositeClientRoles == null) {
+                        compositeClientRoles = new HashMap<>();
                     }
 
-                    ApplicationModel app = (ApplicationModel)crContainer;
-                    String appName = app.getName();
-                    List<String> currentAppComposites = compositeAppRoles.get(appName);
+                    ClientModel app = (ClientModel)crContainer;
+                    String appName = app.getClientId();
+                    List<String> currentAppComposites = compositeClientRoles.get(appName);
                     if (currentAppComposites == null) {
-                        currentAppComposites = new ArrayList<String>();
-                        compositeAppRoles.put(appName, currentAppComposites);
+                        currentAppComposites = new ArrayList<>();
+                        compositeClientRoles.put(appName, currentAppComposites);
                     }
                     currentAppComposites.add(composite.getName());
                 }
@@ -231,8 +216,8 @@ public class ExportUtils {
             if (compositeRealmRoles != null) {
                 compRep.setRealm(compositeRealmRoles);
             }
-            if (compositeAppRoles != null) {
-                compRep.setApplication(compositeAppRoles);
+            if (compositeClientRoles != null) {
+                compRep.setClient(compositeClientRoles);
             }
 
             roleRep.setComposites(compRep);
@@ -263,29 +248,29 @@ public class ExportUtils {
 
         // Role mappings
         Set<RoleModel> roles = user.getRoleMappings();
-        List<String> realmRoleNames = new ArrayList<String>();
-        Map<String, List<String>> appRoleNames = new HashMap<String, List<String>>();
+        List<String> realmRoleNames = new ArrayList<>();
+        Map<String, List<String>> clientRoleNames = new HashMap<>();
         for (RoleModel role : roles) {
             if (role.getContainer() instanceof RealmModel) {
                 realmRoleNames.add(role.getName());
             } else {
-                ApplicationModel app = (ApplicationModel)role.getContainer();
-                String appName = app.getName();
-                List<String> currentAppRoles = appRoleNames.get(appName);
-                if (currentAppRoles == null) {
-                    currentAppRoles = new ArrayList<String>();
-                    appRoleNames.put(appName, currentAppRoles);
+                ClientModel client = (ClientModel)role.getContainer();
+                String clientId = client.getClientId();
+                List<String> currentClientRoles = clientRoleNames.get(clientId);
+                if (currentClientRoles == null) {
+                    currentClientRoles = new ArrayList<>();
+                    clientRoleNames.put(clientId, currentClientRoles);
                 }
 
-                currentAppRoles.add(role.getName());
+                currentClientRoles.add(role.getName());
             }
         }
 
         if (realmRoleNames.size() > 0) {
             userRep.setRealmRoles(realmRoleNames);
         }
-        if (appRoleNames.size() > 0) {
-            userRep.setApplicationRoles(appRoleNames);
+        if (clientRoleNames.size() > 0) {
+            userRep.setClientRoles(clientRoleNames);
         }
 
         // Credentials
diff --git a/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ImportUtils.java b/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ImportUtils.java
index 5c0a60c..66b106c 100755
--- a/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ImportUtils.java
+++ b/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ImportUtils.java
@@ -8,7 +8,7 @@ import org.jboss.logging.Logger;
 import org.keycloak.Config;
 import org.keycloak.exportimport.Strategy;
 import org.keycloak.models.AdminRoles;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RealmProvider;
@@ -54,7 +54,7 @@ public class ImportUtils {
                 if (Config.getAdminRealm().equals(realm.getId())) {
                     // Delete all masterAdmin apps due to foreign key constraints
                     for (RealmModel currRealm : model.getRealms()) {
-                        currRealm.setMasterAdminApp(null);
+                        currRealm.setMasterAdminClient(null);
                     }
                 }
                 // TODO: For migration between versions, it should be possible to delete just realm but keep it's users
@@ -81,9 +81,9 @@ public class ImportUtils {
             // We just imported master realm. All 'masterAdminApps' need to be refreshed
             RealmModel adminRealm = realm;
             for (RealmModel currentRealm : model.getRealms()) {
-                ApplicationModel masterApp = adminRealm.getApplicationByName(KeycloakModelUtils.getMasterRealmAdminApplicationName(currentRealm));
+                ClientModel masterApp = adminRealm.getClientByClientId(KeycloakModelUtils.getMasterRealmAdminApplicationClientId(currentRealm));
                 if (masterApp != null) {
-                    currentRealm.setMasterAdminApp(masterApp);
+                    currentRealm.setMasterAdminClient(masterApp);
                 }  else {
                     setupMasterAdminManagement(model, currentRealm);
                 }
@@ -91,9 +91,9 @@ public class ImportUtils {
         } else {
             // Need to refresh masterApp for current realm
             RealmModel adminRealm = model.getRealm(adminRealmId);
-            ApplicationModel masterApp = adminRealm.getApplicationByName(KeycloakModelUtils.getMasterRealmAdminApplicationName(realm));
+            ClientModel masterApp = adminRealm.getClientByClientId(KeycloakModelUtils.getMasterRealmAdminApplicationClientId(realm));
             if (masterApp != null) {
-                realm.setMasterAdminApp(masterApp);
+                realm.setMasterAdminClient(masterApp);
             }  else {
                 setupMasterAdminManagement(model, realm);
             }
@@ -119,9 +119,9 @@ public class ImportUtils {
         }
         adminRole.setDescription("${role_"+AdminRoles.ADMIN+"}");
 
-        ApplicationModel realmAdminApp = KeycloakModelUtils.createApplication(adminRealm, KeycloakModelUtils.getMasterRealmAdminApplicationName(realm));
+        ClientModel realmAdminApp = KeycloakModelUtils.createClient(adminRealm, KeycloakModelUtils.getMasterRealmAdminApplicationClientId(realm));
         realmAdminApp.setBearerOnly(true);
-        realm.setMasterAdminApp(realmAdminApp);
+        realm.setMasterAdminClient(realmAdminApp);
 
         for (String r : AdminRoles.ALL_REALM_ROLES) {
             RoleModel role = realmAdminApp.addRole(r);
@@ -220,7 +220,7 @@ public class ImportUtils {
 
     private static void importUsers(KeycloakSession session, RealmProvider model, String realmName, List<UserRepresentation> userReps) {
         RealmModel realm = model.getRealmByName(realmName);
-        Map<String, ApplicationModel> apps = realm.getApplicationNameMap();
+        Map<String, ClientModel> apps = realm.getClientNameMap();
         for (UserRepresentation user : userReps) {
             RepresentationToModel.createUser(session, realm, user, apps);
         }
diff --git a/federation/ldap/pom.xml b/federation/ldap/pom.xml
index a48b36d..72803ab 100755
--- a/federation/ldap/pom.xml
+++ b/federation/ldap/pom.xml
@@ -32,12 +32,6 @@
             <scope>provided</scope>
         </dependency>
         <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-picketlink-api</artifactId>
-            <version>${project.version}</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
             <groupId>org.jboss.resteasy</groupId>
             <artifactId>resteasy-jaxrs</artifactId>
             <scope>provided</scope>
@@ -61,27 +55,6 @@
             <artifactId>jboss-logging</artifactId>
             <scope>provided</scope>
         </dependency>
-
-        <dependency>
-            <groupId>org.picketlink</groupId>
-            <artifactId>picketlink-common</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.picketlink</groupId>
-            <artifactId>picketlink-idm-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.picketlink</groupId>
-            <artifactId>picketlink-idm-impl</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.picketlink</groupId>
-            <artifactId>picketlink-idm-simple-schema</artifactId>
-            <scope>provided</scope>
-        </dependency>
     </dependencies>
 
     <build>
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/AbstractAttributedType.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/AbstractAttributedType.java
new file mode 100644
index 0000000..7e6d80b
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/AbstractAttributedType.java
@@ -0,0 +1,85 @@
+package org.keycloak.federation.ldap.idm.model;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import static java.util.Collections.unmodifiableCollection;
+import static java.util.Collections.unmodifiableMap;
+
+/**
+ * Abstract base class for all AttributedType implementations
+ *
+ * @author Shane Bryzak
+ *
+ */
+public abstract class AbstractAttributedType implements AttributedType {
+    private static final long serialVersionUID = -6118293036241099199L;
+
+    private String id;
+    private String entryDN;
+
+    private Map<String, Attribute<? extends Serializable>> attributes =
+            new HashMap<String, Attribute<? extends Serializable>>();
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getEntryDN() {
+        return entryDN;
+    }
+
+    public void setEntryDN(String entryDN) {
+        this.entryDN = entryDN;
+    }
+
+    public void setAttribute(Attribute<? extends Serializable> attribute) {
+        attributes.put(attribute.getName(), attribute);
+    }
+
+    public void removeAttribute(String name) {
+        attributes.remove(name);
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T extends Serializable> Attribute<T> getAttribute(String name) {
+        return (Attribute<T>) attributes.get(name);
+    }
+
+    public Collection<Attribute<? extends Serializable>> getAttributes() {
+        return unmodifiableCollection(attributes.values());
+    }
+
+    public Map<String,Attribute<? extends Serializable>> getAttributesMap() {
+        return unmodifiableMap(attributes);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        }
+
+        if (!getClass().isInstance(obj)) {
+            return false;
+        }
+
+        AttributedType other = (AttributedType) obj;
+
+        return getId() != null && other.getId() != null && getId().equals(other.getId());
+    }
+
+    @Override
+    public int hashCode() {
+        int result = getId() != null ? getId().hashCode() : 0;
+        result = 31 * result + (getId() != null ? getId().hashCode() : 0);
+        return result;
+    }
+
+}
\ No newline at end of file
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/AbstractIdentityType.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/AbstractIdentityType.java
new file mode 100644
index 0000000..8ee8bd6
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/AbstractIdentityType.java
@@ -0,0 +1,70 @@
+package org.keycloak.federation.ldap.idm.model;
+
+import java.util.Date;
+
+/**
+ * Abstract base class for IdentityType implementations
+ *
+ * @author Shane Bryzak
+ */
+public abstract class AbstractIdentityType extends AbstractAttributedType implements IdentityType {
+
+    private static final long serialVersionUID = 2843998332737143820L;
+
+    private boolean enabled = true;
+    private Date createdDate = new Date();
+    private Date expirationDate = null;
+
+    public boolean isEnabled() {
+        return this.enabled;
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    @Override
+    @AttributeProperty
+    public Date getExpirationDate() {
+        return this.expirationDate;
+    }
+
+    @Override
+    public void setExpirationDate(Date expirationDate) {
+        this.expirationDate = expirationDate;
+    }
+
+    @Override
+    @AttributeProperty
+    public Date getCreatedDate() {
+        return this.createdDate;
+    }
+
+    @Override
+    public void setCreatedDate(Date createdDate) {
+        this.createdDate = createdDate;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        }
+
+        if (!getClass().isInstance(obj)) {
+            return false;
+        }
+
+        IdentityType other = (IdentityType) obj;
+
+        return (getId() != null && other.getId() != null)
+                && (getId().equals(other.getId()));
+    }
+
+    @Override
+    public int hashCode() {
+        return super.hashCode();
+    }
+}
+
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/Attribute.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/Attribute.java
new file mode 100644
index 0000000..82dac06
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/Attribute.java
@@ -0,0 +1,80 @@
+package org.keycloak.federation.ldap.idm.model;
+
+import java.io.Serializable;
+
+/**
+ * Represents an attribute value, a type of metadata that can be associated with an IdentityType
+ *
+ * @author Shane Bryzak
+ *
+ * @param <T>
+ */
+public class Attribute<T extends Serializable> implements Serializable {
+
+    private static final long serialVersionUID = 237211288303510728L;
+
+    /**
+     * The name of the attribute
+     */
+    private String name;
+
+    /**
+     * The attribute value.
+     */
+    private T value;
+
+    /**
+     * Indicates whether this Attribute has a read-only value
+     */
+    private boolean readOnly = false;
+
+    /**
+     * Indicates whether the Attribute value has been loaded
+     */
+    private boolean loaded = false;
+
+    public Attribute(String name, T value) {
+        this.name = name;
+        this.value = value;
+    }
+
+    public Attribute(String name, T value, boolean readOnly) {
+        this(name, value);
+        this.readOnly = readOnly;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public T getValue() {
+        return value;
+    }
+
+    public boolean isReadOnly() {
+        return readOnly;
+    }
+
+    public boolean isLoaded() {
+        return loaded;
+    }
+
+    public void setLoaded(boolean value) {
+        this.loaded = value;
+    }
+
+    /**
+     * Sets the value for this attribute.  If the Attribute value is readOnly, a RuntimeException is thrown.
+     *
+     * @param value
+     */
+    public void setValue(T value) {
+        if (readOnly) {
+            throw new RuntimeException("Error setting Attribute value [" + name + " ] - value is read only.");
+        }
+        this.value = value;
+    }
+}
+
+
+
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/AttributedType.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/AttributedType.java
new file mode 100644
index 0000000..5c37427
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/AttributedType.java
@@ -0,0 +1,75 @@
+package org.keycloak.federation.ldap.idm.model;
+
+import java.io.Serializable;
+import java.util.Collection;
+
+import org.keycloak.federation.ldap.idm.query.AttributeParameter;
+import org.keycloak.federation.ldap.idm.query.QueryParameter;
+
+/**
+ *
+ * @author Shane Bryzak
+ *
+ */
+public interface AttributedType extends Serializable {
+
+    /**
+     * A query parameter used to set the id value.
+     */
+    QueryParameter ID = new AttributeParameter("id");
+
+    /**
+     * Returns the unique identifier for this instance
+     * @return
+     */
+    String getId();
+
+    /**
+     * Sets the unique identifier for this instance
+     * @return
+     */
+    void setId(String id);
+
+    /**
+     * Set the specified attribute. This operation will overwrite any previous value.
+     *
+     * @param attribute to be set
+     */
+    void setAttribute(Attribute<? extends Serializable> attribute);
+
+    /**
+     * Remove the attribute with given name
+     *
+     * @param name of attribute
+     */
+    void removeAttribute(String name);
+
+
+    // LDAP specific stuff
+    void setEntryDN(String entryDN);
+    String getEntryDN();
+
+
+    /**
+     * Return the attribute value with the specified name
+     *
+     * @param name of attribute
+     * @return attribute value or null if attribute with given name doesn't exist. If given attribute has many values method
+     *         will return first one
+     */
+    <T extends Serializable> Attribute<T> getAttribute(String name);
+
+    /**
+     * Returns a Map containing all attribute values for this IdentityType instance.
+     *
+     * @return map of attribute names and their values
+     */
+    Collection<Attribute<? extends Serializable>> getAttributes();
+
+    public final class QUERY_ATTRIBUTE {
+        public static AttributeParameter byName(String name) {
+            return new AttributeParameter(name);
+        }
+    }
+}
+
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/AttributeProperty.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/AttributeProperty.java
new file mode 100644
index 0000000..33b8706
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/AttributeProperty.java
@@ -0,0 +1,31 @@
+package org.keycloak.federation.ldap.idm.model;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Marks a property of an IdentityType, Partition or Relationship as being an attribute of that
+ * IdentityType, Partition or Relationship.
+ *
+ * @author Shane Bryzak
+ */
+@Target({METHOD, FIELD})
+@Documented
+@Retention(RUNTIME)
+@Inherited
+public @interface AttributeProperty {
+
+    /**
+     * <p>Managed properties are stored as ad-hoc attributes and mapped from and to a specific property of a type.</p>
+     *
+     * @return
+     */
+    boolean managed() default false;
+
+}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/IdentityType.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/IdentityType.java
new file mode 100644
index 0000000..f8ae8a1
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/IdentityType.java
@@ -0,0 +1,100 @@
+package org.keycloak.federation.ldap.idm.model;
+
+import java.util.Date;
+
+import org.keycloak.federation.ldap.idm.query.AttributeParameter;
+import org.keycloak.federation.ldap.idm.query.QueryParameter;
+
+/**
+ * This interface is the base for all identity model objects.  It declares a number of
+ * properties that must be supported by all identity types, in addition to defining the API
+ * for identity attribute management.
+ *
+ * @author Shane Bryzak
+ */
+public interface IdentityType extends AttributedType {
+
+    /**
+     * A query parameter used to set the enabled value.
+     */
+    QueryParameter ENABLED = new AttributeParameter("enabled");
+
+    /**
+     * A query parameter used to set the createdDate value
+     */
+    QueryParameter CREATED_DATE = new AttributeParameter("createdDate");
+
+    /**
+     * A query parameter used to set the created after date
+     */
+    QueryParameter CREATED_AFTER = new AttributeParameter("createdDate");
+
+    /**
+     * A query parameter used to set the modified after date
+     */
+    QueryParameter MODIFIED_AFTER = new AttributeParameter("modifyDate");
+
+    /**
+     * A query parameter used to set the created before date
+     */
+    QueryParameter CREATED_BEFORE = new AttributeParameter("createdDate");
+
+    /**
+     * A query parameter used to set the expiryDate value
+     */
+    QueryParameter EXPIRY_DATE = new AttributeParameter("expirationDate");
+
+    /**
+     * A query parameter used to set the expiration after date
+     */
+    QueryParameter EXPIRY_AFTER = new AttributeParameter("expirationDate");
+
+    /**
+     * A query parameter used to set the expiration before date
+     */
+    QueryParameter EXPIRY_BEFORE = new AttributeParameter("expirationDate");
+
+    /**
+     * Indicates the current enabled status of this IdentityType.
+     *
+     * @return A boolean value indicating whether this IdentityType is enabled.
+     */
+    boolean isEnabled();
+
+    /**
+     * <p>Sets the current enabled status of this {@link IdentityType}.</p>
+     *
+     * @param enabled
+     */
+    void setEnabled(boolean enabled);
+
+    /**
+     * Returns the date that this IdentityType instance was created.
+     *
+     * @return Date value representing the creation date
+     */
+    Date getCreatedDate();
+
+    /**
+     * <p>Sets the date that this {@link IdentityType} was created.</p>
+     *
+     * @param createdDate
+     */
+    void setCreatedDate(Date createdDate);
+
+    /**
+     * Returns the date that this IdentityType expires, or null if there is no expiry date.
+     *
+     * @return
+     */
+    Date getExpirationDate();
+
+    /**
+     * <p>Sets the date that this {@link IdentityType} expires.</p>
+     *
+     * @param expirationDate
+     */
+    void setExpirationDate(Date expirationDate);
+
+}
+
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/LDAPUser.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/LDAPUser.java
new file mode 100644
index 0000000..4ce7ef9
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/LDAPUser.java
@@ -0,0 +1,85 @@
+package org.keycloak.federation.ldap.idm.model;
+
+
+import org.keycloak.federation.ldap.idm.query.QueryParameter;
+
+/**
+ * This class represents a User; a human agent that may authenticate with the application
+ *
+ * @author Shane Bryzak
+ */
+public class LDAPUser extends AbstractIdentityType {
+
+    private static final long serialVersionUID = 4117586097100398485L;
+
+    public static final QueryParameter LOGIN_NAME = AttributedType.QUERY_ATTRIBUTE.byName("loginName");
+
+    /**
+     * A query parameter used to set the firstName value.
+     */
+    public static final QueryParameter FIRST_NAME = QUERY_ATTRIBUTE.byName("firstName");
+
+    /**
+     * A query parameter used to set the lastName value.
+     */
+    public static final QueryParameter LAST_NAME = QUERY_ATTRIBUTE.byName("lastName");
+
+    /**
+     * A query parameter used to set the email value.
+     */
+    public static final QueryParameter EMAIL = QUERY_ATTRIBUTE.byName("email");
+
+    @AttributeProperty
+    private String loginName;
+
+    @AttributeProperty
+    private String firstName;
+
+    @AttributeProperty
+    private String lastName;
+
+    @AttributeProperty
+    private String email;
+
+    public LDAPUser() {
+
+    }
+
+    public LDAPUser(String loginName) {
+        this.loginName = loginName;
+    }
+
+    public String getLoginName() {
+        return loginName;
+    }
+
+    public void setLoginName(String loginName) {
+        this.loginName = loginName;
+    }
+
+    public String getFirstName() {
+        return firstName;
+    }
+
+    public void setFirstName(String firstName) {
+        this.firstName = firstName;
+    }
+
+    public String getLastName() {
+        return lastName;
+    }
+
+    public void setLastName(String lastName) {
+        this.lastName = lastName;
+    }
+
+    public String getEmail() {
+        return this.email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+}
+
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/AttributeParameter.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/AttributeParameter.java
new file mode 100644
index 0000000..c5feea9
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/AttributeParameter.java
@@ -0,0 +1,21 @@
+package org.keycloak.federation.ldap.idm.query;
+
+/**
+ * <p>This class can be used to define a query parameter for properties annotated with
+ * {@link org.keycloak.federation.ldap.idm.model.AttributeProperty}.
+ * </p>
+ *
+ * @author pedroigor
+ */
+public class AttributeParameter implements QueryParameter {
+
+    private final String name;
+
+    public AttributeParameter(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/Condition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/Condition.java
new file mode 100644
index 0000000..85d81d8
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/Condition.java
@@ -0,0 +1,18 @@
+package org.keycloak.federation.ldap.idm.query;
+
+/**
+ * <p>A {@link Condition} is used to specify how a specific {@link QueryParameter}
+ * is defined in order to filter query results.</p>
+ *
+ * @author Pedro Igor
+ */
+public interface Condition {
+
+    /**
+     * <p>The {@link QueryParameter} restricted by this condition.</p>
+     *
+     * @return
+     */
+    QueryParameter getParameter();
+
+}
\ No newline at end of file
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/IdentityQuery.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/IdentityQuery.java
new file mode 100644
index 0000000..1a77727
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/IdentityQuery.java
@@ -0,0 +1,225 @@
+package org.keycloak.federation.ldap.idm.query;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.keycloak.federation.ldap.idm.model.IdentityType;
+
+/**
+ * <p>An {@link IdentityQuery} is responsible for querying the underlying identity stores for instances of
+ * a given {@link IdentityType}.</p>
+ *
+ * <p>Instances of this class are obtained using the {@link IdentityQueryBuilder#createIdentityQuery(Class)}
+ * method.</p>
+ *
+ * <pre>
+ *      IdentityManager identityManager = getIdentityManager();
+ *
+ *      // here we get the query builder
+ *      IdentityQueryBuilder builder = identityManager.getQueryBuilder();
+ *
+ *      // create a condition
+ *      Condition condition = builder.equal(User.LOGIN_NAME, "john");
+ *
+ *      // create a query for a specific identity type using the previously created condition
+ *      IdentityQuery query = builder.createIdentityQuery(User.class).where(condition);
+ *
+ *      // execute the query
+ *      List<User> result = query.getResultList();
+ * </pre>
+ *
+ * <p>When preparing a query you may want to create conditions to filter its results and configure how they must be retrieved.
+ * For that, you can use the {@link IdentityQueryBuilder}, which provides useful methods for creating
+ * different expressions and conditions.</p>
+ *
+ * @author Shane Bryzak
+ * @author Pedro Igor
+ */
+public interface IdentityQuery<T extends IdentityType> {
+
+    /**
+     * @see #setPaginationContext(Object object)
+     */
+    Object getPaginationContext();
+
+    /**
+     * Used for pagination models like LDAP when search will return some object (like cookie) for searching on next page
+     *
+     * @param object to be used for search next page
+     *
+     * @return this query
+     */
+    IdentityQuery<T> setPaginationContext(Object object);
+
+    /**
+     * @deprecated Will be removed soon.
+     *
+     * @see #setSortParameters(QueryParameter...)
+     */
+    @Deprecated
+    QueryParameter[] getSortParameters();
+
+    /**
+     * Parameters used to sort the results. First parameter has biggest priority. For example: setSortParameter(User.LAST_NAME,
+     * User.FIRST_NAME) means that results will be sorted primarily by lastName and firstName will be used to sort only records with
+     * same lastName
+     *
+     * @param sortParameters parameters to specify sort criteria
+     *
+     * @deprecated Use {@link IdentityQuery#sortBy(Sort...)} instead. Where you can create sort conditions
+     * from the {@link IdentityQueryBuilder}.
+     *
+     * @return this query
+     */
+    @Deprecated
+    IdentityQuery<T> setSortParameters(QueryParameter... sortParameters);
+
+    /**
+     * @deprecated Use {@link IdentityQuery#getSorting()} for a list of sorting conditions. Will be removed soon.
+     *
+     * @return true if sorting will be ascending
+     *
+     * @see #setSortAscending(boolean)
+     */
+    @Deprecated
+    boolean isSortAscending();
+
+    /**
+     * Specify if sorting will be ascending (true) or descending (false)
+     *
+     * @param sortAscending to specify if sorting will be ascending or descending
+     *
+     * @deprecated Use {@link IdentityQuery#sortBy(Sort...)} instead. Where you can create sort conditions
+     * from the {@link IdentityQueryBuilder}.
+     *
+     * @return this query
+     */
+    @Deprecated
+    IdentityQuery<T> setSortAscending(boolean sortAscending);
+
+    /**
+     * <p>Set a query parameter to this query in order to filter the results.</p>
+     *
+     * <p>This method always create an equality condition. For more conditions options  take a look at {@link
+     * IdentityQueryBuilder} and use the {@link IdentityQuery#where(Condition...)}
+     * instead.</p>
+     *
+     * @param param The query parameter.
+     * @param value The value to match for equality.
+     *
+     * @return
+     *
+     * @deprecated Use {@link IdentityQuery#where(Condition...)} to specify query conditions.
+     */
+    @Deprecated
+    IdentityQuery<T> setParameter(QueryParameter param, Object... value);
+
+    /**
+     * <p>Add to this query the conditions that will be used to filter results.</p>
+     *
+     * <p>Any condition previously added to this query will be preserved and the new conditions added. If you want to clear the
+     * conditions you must create a new query instance.</p>
+     *
+     * @param condition One or more conditions created from {@link IdentityQueryBuilder}.
+     *
+     * @return
+     */
+    IdentityQuery<T> where(Condition... condition);
+
+    /**
+     * <p>Add to this query the sorting conditions to be applied to the results.</p>
+     *
+     * @param sorts The ordering conditions.
+     *
+     * @return
+     */
+    IdentityQuery<T> sortBy(Sort... sorts);
+
+    /**
+     * <p>The type used to create this query.</p>
+     *
+     * @return
+     */
+    Class<T> getIdentityType();
+
+    /**
+     * <p>Returns a map with all the parameter set for this query.</p>
+     *
+     * @return
+     *
+     * @deprecated Use {@link IdentityQuery#getConditions()} instead. Will be removed.
+     */
+    @Deprecated
+    Map<QueryParameter, Object[]> getParameters();
+
+    /**
+     * <p>Returns a set containing all conditions used by this query to filter its results.</p>
+     *
+     * @return
+     */
+    Set<Condition> getConditions();
+
+    /**
+     * <p>Returns a set containing all sorting conditions used to filter the results.</p>
+     *
+     * @return
+     */
+    Set<Sort> getSorting();
+
+    /**
+     * <p>Returns the value used to restrict the given query parameter.</p>
+     *
+     * @param queryParameter
+     *
+     * @return
+     */
+    @Deprecated
+    Object[] getParameter(QueryParameter queryParameter);
+
+    @Deprecated
+    Map<QueryParameter, Object[]> getParameters(Class<?> type);
+
+    int getOffset();
+
+    /**
+     * <p>Set the position of the first result to retrieve.</p>
+     *
+     * @param offset
+     *
+     * @return
+     */
+    IdentityQuery<T> setOffset(int offset);
+
+    /**
+     * <p>Returns the number of instances to retrieve.</p>
+     *
+     * @return
+     */
+    int getLimit();
+
+    /**
+     * <p>Set the maximum number of results to retrieve.</p>
+     *
+     * @param limit the number of instances to retrieve.
+     *
+     * @return
+     */
+    IdentityQuery<T> setLimit(int limit);
+
+    /**
+     * <p>Execute the query against the underlying identity stores and returns a list containing all instances of
+     * the type (defined when creating this query instance) that match the conditions previously specified.</p>
+     *
+     * @return
+     */
+    List<T> getResultList();
+
+    /**
+     * Count of all query results. It takes into account query parameters, but it doesn't take into account pagination parameter
+     * like offset and limit
+     *
+     * @return count of all query results
+     */
+    int getResultCount();
+}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/IdentityQueryBuilder.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/IdentityQueryBuilder.java
new file mode 100644
index 0000000..0220635
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/IdentityQueryBuilder.java
@@ -0,0 +1,124 @@
+package org.keycloak.federation.ldap.idm.query;
+
+import org.keycloak.federation.ldap.idm.model.IdentityType;
+
+/**
+ * <p>The {@link IdentityQueryBuilder} is responsible for creating {@link IdentityQuery} instances and also
+ * provide methods to create conditions, orderings, sorting, etc.</p>
+ *
+ * @author Pedro Igor
+ */
+public interface IdentityQueryBuilder {
+
+    /**
+     * <p>Create a condition for testing the whether the query parameter satisfies the given pattern..</p>
+     *
+     * @param parameter The query parameter.
+     * @param pattern The pattern to match.
+     *
+     * @return
+     */
+    Condition like(QueryParameter parameter, String pattern);
+
+    /**
+     * <p>Create a condition for testing the arguments for equality.</p>
+     *
+     * @param parameter The query parameter.
+     * @param value The value to compare.
+     *
+     * @return
+     */
+    Condition equal(QueryParameter parameter, Object value);
+
+    /**
+     * <p>Create a condition for testing whether the query parameter is grater than the given value..</p>
+     *
+     * @param parameter The query parameter.
+     * @param x The value to compare.
+     *
+     * @return
+     */
+    Condition greaterThan(QueryParameter parameter, Object x);
+
+    /**
+     * <p>Create a condition for testing whether the query parameter is grater than or equal to the given value..</p>
+     *
+     * @param parameter The query parameter.
+     * @param x The value to compare.
+     *
+     * @return
+     */
+    Condition greaterThanOrEqualTo(QueryParameter parameter, Object x);
+
+    /**
+     * <p>Create a condition for testing whether the query parameter is less than the given value..</p>
+     *
+     * @param parameter The query parameter.
+     * @param x The value to compare.
+     *
+     * @return
+     */
+    Condition lessThan(QueryParameter parameter, Object x);
+
+    /**
+     * <p>Create a condition for testing whether the query parameter is less than or equal to the given value..</p>
+     *
+     * @param parameter The query parameter.
+     * @param x The value to compare.
+     *
+     * @return
+     */
+    Condition lessThanOrEqualTo(QueryParameter parameter, Object x);
+
+    /**
+     * <p>Create a condition for testing whether the query parameter is between the given values.</p>
+     *
+     * @param parameter The query parameter.
+     * @param x The first value.
+     * @param x The second value.
+     *
+     * @return
+     */
+    Condition between(QueryParameter parameter, Object x, Object y);
+
+    /**
+     * <p>Create a condition for testing whether the query parameter is contained in a list of values.</p>
+     *
+     * @param parameter The query parameter.
+     * @param values A list of values.
+     *
+     * @return
+     */
+    Condition in(QueryParameter parameter, Object... values);
+
+    /**
+     * <p>Create an ascending order for the given <code>parameter</code>. Once created, you can use it to sort the results of a
+     * query.</p>
+     *
+     * @param parameter The query parameter to sort.
+     *
+     * @return
+     */
+    Sort asc(QueryParameter parameter);
+
+    /**
+     * <p>Create an descending order for the given <code>parameter</code>. Once created, you can use it to sort the results of a
+     * query.</p>
+     *
+     * @param parameter The query parameter to sort.
+     *
+     * @return
+     */
+    Sort desc(QueryParameter parameter);
+
+    /**
+     * <p> Create an {@link IdentityQuery} that can be used to query for {@link
+     * IdentityType} instances of a the given <code>identityType</code>. </p>
+     *
+     * @param identityType The type to search. If you provide the {@link IdentityType}
+     * base interface any of its sub-types will be returned.
+     *
+     * @return
+     */
+    <T extends IdentityType> IdentityQuery<T> createIdentityQuery(Class<T> identityType);
+}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/BetweenCondition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/BetweenCondition.java
new file mode 100644
index 0000000..672fdaa
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/BetweenCondition.java
@@ -0,0 +1,33 @@
+package org.keycloak.federation.ldap.idm.query.internal;
+
+import org.keycloak.federation.ldap.idm.query.Condition;
+import org.keycloak.federation.ldap.idm.query.QueryParameter;
+
+/**
+ * @author Pedro Igor
+ */
+public class BetweenCondition implements Condition {
+
+    private final Comparable x;
+    private final Comparable y;
+    private final QueryParameter parameter;
+
+    public BetweenCondition(QueryParameter parameter, Comparable x, Comparable y) {
+        this.parameter = parameter;
+        this.x = x;
+        this.y = y;
+    }
+
+    @Override
+    public QueryParameter getParameter() {
+        return this.parameter;
+    }
+
+    public Comparable getX() {
+        return this.x;
+    }
+
+    public Comparable getY() {
+        return this.y;
+    }
+}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/DefaultIdentityQuery.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/DefaultIdentityQuery.java
new file mode 100644
index 0000000..21b0253
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/DefaultIdentityQuery.java
@@ -0,0 +1,207 @@
+package org.keycloak.federation.ldap.idm.query.internal;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.keycloak.federation.ldap.idm.model.IdentityType;
+import org.keycloak.federation.ldap.idm.query.Condition;
+import org.keycloak.federation.ldap.idm.query.IdentityQuery;
+import org.keycloak.federation.ldap.idm.query.IdentityQueryBuilder;
+import org.keycloak.federation.ldap.idm.query.QueryParameter;
+import org.keycloak.federation.ldap.idm.query.Sort;
+import org.keycloak.federation.ldap.idm.store.IdentityStore;
+import org.keycloak.models.ModelException;
+
+import static java.util.Collections.unmodifiableSet;
+
+/**
+ * Default IdentityQuery implementation.
+ *
+ * @param <T>
+ *
+ * @author Shane Bryzak
+ */
+public class DefaultIdentityQuery<T extends IdentityType> implements IdentityQuery<T> {
+
+    private final Map<QueryParameter, Object[]> parameters = new LinkedHashMap<QueryParameter, Object[]>();
+    private final Class<T> identityType;
+    private final IdentityStore identityStore;
+    private final IdentityQueryBuilder queryBuilder;
+    private int offset;
+    private int limit;
+    private Object paginationContext;
+    private QueryParameter[] sortParameters;
+    private boolean sortAscending = true;
+    private final Set<Condition> conditions = new LinkedHashSet<Condition>();
+    private final Set<Sort> ordering = new LinkedHashSet<Sort>();
+
+    public DefaultIdentityQuery(IdentityQueryBuilder queryBuilder, Class<T> identityType, IdentityStore identityStore) {
+        this.queryBuilder = queryBuilder;
+        this.identityStore = identityStore;
+        this.identityType = identityType;
+    }
+
+    @Override
+    public IdentityQuery<T> setParameter(QueryParameter queryParameter, Object... value) {
+        if (value == null || value.length == 0) {
+            throw new ModelException("Query Parameter values null or empty");
+        }
+
+        parameters.put(queryParameter, value);
+
+        if (IdentityType.CREATED_AFTER.equals(queryParameter) || IdentityType.EXPIRY_AFTER.equals(queryParameter)) {
+            this.conditions.add(queryBuilder.greaterThanOrEqualTo(queryParameter, value[0]));
+        } else if (IdentityType.CREATED_BEFORE.equals(queryParameter) || IdentityType.EXPIRY_BEFORE.equals(queryParameter)) {
+            this.conditions.add(queryBuilder.lessThanOrEqualTo(queryParameter, value[0]));
+        } else {
+            this.conditions.add(queryBuilder.equal(queryParameter, value[0]));
+        }
+
+        return this;
+    }
+
+    @Override
+    public IdentityQuery<T> where(Condition... condition) {
+        this.conditions.addAll(Arrays.asList(condition));
+        return this;
+    }
+
+    @Override
+    public IdentityQuery<T> sortBy(Sort... sorts) {
+        this.ordering.addAll(Arrays.asList(sorts));
+        return this;
+    }
+
+    @Override
+    public Set<Sort> getSorting() {
+        return unmodifiableSet(this.ordering);
+    }
+
+    @Override
+    public Class<T> getIdentityType() {
+        return identityType;
+    }
+
+    @Override
+    public Map<QueryParameter, Object[]> getParameters() {
+        return parameters;
+    }
+
+    @Override
+    public Object[] getParameter(QueryParameter queryParameter) {
+        return this.parameters.get(queryParameter);
+    }
+
+    @Override
+    public Map<QueryParameter, Object[]> getParameters(Class<?> type) {
+        Map<QueryParameter, Object[]> typedParameters = new HashMap<QueryParameter, Object[]>();
+
+        Set<Map.Entry<QueryParameter, Object[]>> entrySet = this.parameters.entrySet();
+
+        for (Map.Entry<QueryParameter, Object[]> entry : entrySet) {
+            if (type.isInstance(entry.getKey())) {
+                typedParameters.put(entry.getKey(), entry.getValue());
+            }
+        }
+
+        return typedParameters;
+    }
+
+    @Override
+    public int getLimit() {
+        return limit;
+    }
+
+    @Override
+    public int getOffset() {
+        return offset;
+    }
+
+    @Override
+    public Object getPaginationContext() {
+        return paginationContext;
+    }
+
+    @Override
+    public QueryParameter[] getSortParameters() {
+        return sortParameters;
+    }
+
+    @Override
+    public boolean isSortAscending() {
+        return sortAscending;
+    }
+
+    @Override
+    public List<T> getResultList() {
+
+        // remove this statement once deprecated methods on IdentityQuery are removed
+        if (this.sortParameters != null) {
+            for (QueryParameter parameter : this.sortParameters) {
+                if (isSortAscending()) {
+                    sortBy(this.queryBuilder.asc(parameter));
+                } else {
+                    sortBy(this.queryBuilder.desc(parameter));
+                }
+            }
+        }
+
+        List<T> result = new ArrayList<T>();
+
+        try {
+            for (T identityType : identityStore.fetchQueryResults(this)) {
+                result.add(identityType);
+            }
+        } catch (Exception e) {
+            throw new ModelException("LDAP Query failed", e);
+        }
+
+        return result;
+    }
+
+    @Override
+    public int getResultCount() {
+        return identityStore.countQueryResults(this);
+    }
+
+    @Override
+    public IdentityQuery<T> setOffset(int offset) {
+        this.offset = offset;
+        return this;
+    }
+
+    @Override
+    public IdentityQuery<T> setLimit(int limit) {
+        this.limit = limit;
+        return this;
+    }
+
+    @Override
+    public IdentityQuery<T> setSortParameters(QueryParameter... sortParameters) {
+        this.sortParameters = sortParameters;
+        return this;
+    }
+
+    @Override
+    public IdentityQuery<T> setSortAscending(boolean sortAscending) {
+        this.sortAscending = sortAscending;
+        return this;
+    }
+
+    @Override
+    public IdentityQuery<T> setPaginationContext(Object object) {
+        this.paginationContext = object;
+        return this;
+    }
+
+    @Override
+    public Set<Condition> getConditions() {
+        return unmodifiableSet(this.conditions);
+    }
+}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/DefaultQueryBuilder.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/DefaultQueryBuilder.java
new file mode 100644
index 0000000..5d3b72e
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/DefaultQueryBuilder.java
@@ -0,0 +1,89 @@
+package org.keycloak.federation.ldap.idm.query.internal;
+
+import org.keycloak.federation.ldap.idm.model.IdentityType;
+import org.keycloak.federation.ldap.idm.query.Condition;
+import org.keycloak.federation.ldap.idm.query.IdentityQuery;
+import org.keycloak.federation.ldap.idm.query.IdentityQueryBuilder;
+import org.keycloak.federation.ldap.idm.query.QueryParameter;
+import org.keycloak.federation.ldap.idm.query.Sort;
+import org.keycloak.federation.ldap.idm.store.IdentityStore;
+import org.keycloak.models.ModelException;
+
+/**
+ * @author Pedro Igor
+ */
+public class DefaultQueryBuilder implements IdentityQueryBuilder {
+
+    private final IdentityStore identityStore;
+
+    public DefaultQueryBuilder(IdentityStore identityStore) {
+        this.identityStore = identityStore;
+    }
+
+    @Override
+    public Condition like(QueryParameter parameter, String pattern) {
+        return new LikeCondition(parameter, pattern);
+    }
+
+    @Override
+    public Condition equal(QueryParameter parameter, Object value) {
+        return new EqualCondition(parameter, value);
+    }
+
+    @Override
+    public Condition greaterThan(QueryParameter parameter, Object x) {
+        throwExceptionIfNotComparable(x);
+        return new GreaterThanCondition(parameter, (Comparable) x, false);
+    }
+
+    @Override
+    public Condition greaterThanOrEqualTo(QueryParameter parameter, Object x) {
+        throwExceptionIfNotComparable(x);
+        return new GreaterThanCondition(parameter, (Comparable) x, true);
+    }
+
+    @Override
+    public Condition lessThan(QueryParameter parameter, Object x) {
+        throwExceptionIfNotComparable(x);
+        return new LessThanCondition(parameter, (Comparable) x, false);
+    }
+
+    @Override
+    public Condition lessThanOrEqualTo(QueryParameter parameter, Object x) {
+        throwExceptionIfNotComparable(x);
+        return new LessThanCondition(parameter, (Comparable) x, true);
+    }
+
+    @Override
+    public Condition between(QueryParameter parameter, Object x, Object y) {
+        throwExceptionIfNotComparable(x);
+        throwExceptionIfNotComparable(y);
+        return new BetweenCondition(parameter, (Comparable) x, (Comparable) y);
+    }
+
+    @Override
+    public Condition in(QueryParameter parameter, Object... x) {
+        return new InCondition(parameter, x);
+    }
+
+    @Override
+    public Sort asc(QueryParameter parameter) {
+        return new Sort(parameter, true);
+    }
+
+    @Override
+    public Sort desc(QueryParameter parameter) {
+        return new Sort(parameter, false);
+    }
+
+    @Override
+    public <T extends IdentityType> IdentityQuery createIdentityQuery(Class<T> identityType) {
+        return new DefaultIdentityQuery(this, identityType, this.identityStore);
+    }
+
+    private void throwExceptionIfNotComparable(Object x) {
+        if (!Comparable.class.isInstance(x)) {
+            throw new ModelException("Query parameter value [" + x + "] must be " + Comparable.class + ".");
+        }
+    }
+}
\ No newline at end of file
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/EqualCondition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/EqualCondition.java
new file mode 100644
index 0000000..a3fee26
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/EqualCondition.java
@@ -0,0 +1,36 @@
+package org.keycloak.federation.ldap.idm.query.internal;
+
+import org.keycloak.federation.ldap.idm.query.AttributeParameter;
+import org.keycloak.federation.ldap.idm.query.Condition;
+import org.keycloak.federation.ldap.idm.query.QueryParameter;
+
+/**
+ * @author Pedro Igor
+ */
+public class EqualCondition implements Condition {
+
+    private final QueryParameter parameter;
+    private final Object value;
+
+    public EqualCondition(QueryParameter parameter, Object value) {
+        this.parameter = parameter;
+        this.value = value;
+    }
+
+    @Override
+    public QueryParameter getParameter() {
+        return this.parameter;
+    }
+
+    public Object getValue() {
+        return this.value;
+    }
+
+    @Override
+    public String toString() {
+        return "EqualCondition{" +
+                "parameter=" + ((AttributeParameter) parameter).getName() +
+                ", value=" + value +
+                '}';
+    }
+}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/GreaterThanCondition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/GreaterThanCondition.java
new file mode 100644
index 0000000..cbdf540
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/GreaterThanCondition.java
@@ -0,0 +1,34 @@
+package org.keycloak.federation.ldap.idm.query.internal;
+
+import org.keycloak.federation.ldap.idm.query.Condition;
+import org.keycloak.federation.ldap.idm.query.QueryParameter;
+
+/**
+ * @author Pedro Igor
+ */
+public class GreaterThanCondition implements Condition {
+
+    private final boolean orEqual;
+
+    private final QueryParameter parameter;
+    private final Comparable value;
+
+    public GreaterThanCondition(QueryParameter parameter, Comparable value, boolean orEqual) {
+        this.parameter = parameter;
+        this.value = value;
+        this.orEqual = orEqual;
+    }
+
+    @Override
+    public QueryParameter getParameter() {
+        return this.parameter;
+    }
+
+    public Comparable getValue() {
+        return this.value;
+    }
+
+    public boolean isOrEqual() {
+        return this.orEqual;
+    }
+}
\ No newline at end of file
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/InCondition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/InCondition.java
new file mode 100644
index 0000000..54d2234
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/InCondition.java
@@ -0,0 +1,28 @@
+package org.keycloak.federation.ldap.idm.query.internal;
+
+import org.keycloak.federation.ldap.idm.query.Condition;
+import org.keycloak.federation.ldap.idm.query.QueryParameter;
+
+/**
+ * @author Pedro Igor
+ */
+public class InCondition implements Condition {
+
+    private final QueryParameter parameter;
+    private final Object[] value;
+
+    public InCondition(QueryParameter parameter, Object[] value) {
+        this.parameter = parameter;
+        this.value = value;
+    }
+
+    @Override
+    public QueryParameter getParameter() {
+        return this.parameter;
+    }
+
+    public Object[] getValue() {
+        return this.value;
+    }
+}
+
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LessThanCondition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LessThanCondition.java
new file mode 100644
index 0000000..5906a5c
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LessThanCondition.java
@@ -0,0 +1,34 @@
+package org.keycloak.federation.ldap.idm.query.internal;
+
+import org.keycloak.federation.ldap.idm.query.Condition;
+import org.keycloak.federation.ldap.idm.query.QueryParameter;
+
+/**
+ * @author Pedro Igor
+ */
+public class LessThanCondition implements Condition {
+
+    private final boolean orEqual;
+
+    private final QueryParameter parameter;
+    private final Comparable value;
+
+    public LessThanCondition(QueryParameter parameter, Comparable value, boolean orEqual) {
+        this.parameter = parameter;
+        this.value = value;
+        this.orEqual = orEqual;
+    }
+
+    @Override
+    public QueryParameter getParameter() {
+        return this.parameter;
+    }
+
+    public Comparable getValue() {
+        return this.value;
+    }
+
+    public boolean isOrEqual() {
+        return this.orEqual;
+    }
+}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LikeCondition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LikeCondition.java
new file mode 100644
index 0000000..6c68103
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LikeCondition.java
@@ -0,0 +1,28 @@
+package org.keycloak.federation.ldap.idm.query.internal;
+
+import org.keycloak.federation.ldap.idm.query.Condition;
+import org.keycloak.federation.ldap.idm.query.QueryParameter;
+
+/**
+ * @author Pedro Igor
+ */
+public class LikeCondition implements Condition {
+
+    private final QueryParameter parameter;
+    private final Object value;
+
+    public LikeCondition(QueryParameter parameter, Object value) {
+        this.parameter = parameter;
+        this.value = value;
+    }
+
+    @Override
+    public QueryParameter getParameter() {
+        return this.parameter;
+    }
+
+    public Object getValue() {
+        return this.value;
+    }
+
+}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/QueryParameter.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/QueryParameter.java
new file mode 100644
index 0000000..ae2bbdf
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/QueryParameter.java
@@ -0,0 +1,12 @@
+package org.keycloak.federation.ldap.idm.query;
+
+/**
+ * A marker interface indicating that the implementing class can be used as a
+ * parameter within an IdentityQuery or RelationshipQuery
+ *
+ * @author Shane Bryzak
+ *
+ */
+public interface QueryParameter {
+
+}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/Sort.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/Sort.java
new file mode 100644
index 0000000..dfd331e
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/Sort.java
@@ -0,0 +1,23 @@
+package org.keycloak.federation.ldap.idm.query;
+
+/**
+ * @author Pedro Igor
+ */
+public class Sort {
+
+    private final QueryParameter parameter;
+    private final boolean asc;
+
+    public Sort(QueryParameter parameter, boolean asc) {
+        this.parameter = parameter;
+        this.asc = asc;
+    }
+
+    public QueryParameter getParameter() {
+        return this.parameter;
+    }
+
+    public boolean isAscending() {
+        return asc;
+    }
+}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/IdentityStore.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/IdentityStore.java
new file mode 100644
index 0000000..7fef705
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/IdentityStore.java
@@ -0,0 +1,81 @@
+package org.keycloak.federation.ldap.idm.store;
+
+import java.util.List;
+
+import org.keycloak.federation.ldap.idm.model.AttributedType;
+import org.keycloak.federation.ldap.idm.model.IdentityType;
+import org.keycloak.federation.ldap.idm.model.LDAPUser;
+import org.keycloak.federation.ldap.idm.query.IdentityQuery;
+import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStoreConfiguration;
+
+/**
+ * IdentityStore representation providing minimal SPI
+ *
+ * TODO: Rather remove this abstraction
+ *
+ * @author Boleslaw Dawidowicz
+ * @author Shane Bryzak
+ */
+public interface IdentityStore {
+
+    /**
+     * Returns the configuration for this IdentityStore instance
+     *
+     * @return
+     */
+    LDAPIdentityStoreConfiguration getConfig();
+
+    // General
+
+    /**
+     * Persists the specified IdentityType
+     *
+     * @param value
+     */
+    void add(AttributedType value);
+
+    /**
+     * Updates the specified IdentityType
+     *
+     * @param value
+     */
+    void update(AttributedType value);
+
+    /**
+     * Removes the specified IdentityType
+     *
+     * @param value
+     */
+    void remove(AttributedType value);
+
+    // Identity query
+
+    <V extends IdentityType> List<V> fetchQueryResults(IdentityQuery<V> identityQuery);
+
+    <V extends IdentityType> int countQueryResults(IdentityQuery<V> identityQuery);
+
+//    // Relationship query
+//
+//    <V extends Relationship> List<V> fetchQueryResults(RelationshipQuery<V> query);
+//
+//    <V extends Relationship> int countQueryResults(RelationshipQuery<V> query);
+
+    // Credentials
+
+    /**
+     * Validates the specified credentials.
+     *
+     * @param user Keycloak user
+     * @param password Ldap password
+     */
+    boolean validatePassword(LDAPUser user, String password);
+
+    /**
+     * Updates the specified credential value.
+     *
+     * @param user Keycloak user
+     * @param password Ldap password
+     */
+    void updatePassword(LDAPUser user, String password);
+
+}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPIdentityStore.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPIdentityStore.java
new file mode 100644
index 0000000..8b91240
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPIdentityStore.java
@@ -0,0 +1,761 @@
+package org.keycloak.federation.ldap.idm.store.ldap;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.ModificationItem;
+import javax.naming.directory.SearchResult;
+
+import org.jboss.logging.Logger;
+import org.keycloak.federation.ldap.idm.model.AttributedType;
+import org.keycloak.federation.ldap.idm.model.IdentityType;
+import org.keycloak.federation.ldap.idm.model.LDAPUser;
+import org.keycloak.federation.ldap.idm.query.AttributeParameter;
+import org.keycloak.federation.ldap.idm.query.Condition;
+import org.keycloak.federation.ldap.idm.query.IdentityQuery;
+import org.keycloak.federation.ldap.idm.query.IdentityQueryBuilder;
+import org.keycloak.federation.ldap.idm.query.QueryParameter;
+import org.keycloak.federation.ldap.idm.query.internal.BetweenCondition;
+import org.keycloak.federation.ldap.idm.query.internal.DefaultQueryBuilder;
+import org.keycloak.federation.ldap.idm.query.internal.EqualCondition;
+import org.keycloak.federation.ldap.idm.query.internal.GreaterThanCondition;
+import org.keycloak.federation.ldap.idm.query.internal.InCondition;
+import org.keycloak.federation.ldap.idm.query.internal.LessThanCondition;
+import org.keycloak.federation.ldap.idm.query.internal.LikeCondition;
+import org.keycloak.federation.ldap.idm.store.IdentityStore;
+import org.keycloak.models.LDAPConstants;
+import org.keycloak.models.ModelDuplicateException;
+import org.keycloak.models.ModelException;
+import org.keycloak.models.utils.reflection.NamedPropertyCriteria;
+import org.keycloak.models.utils.reflection.Property;
+import org.keycloak.models.utils.reflection.PropertyQueries;
+import org.keycloak.models.utils.reflection.TypedPropertyCriteria;
+import org.keycloak.util.reflections.Reflections;
+
+/**
+ * An IdentityStore implementation backed by an LDAP directory
+ *
+ * @author Shane Bryzak
+ * @author Anil Saldhana
+ * @author <a href="mailto:psilva@redhat.com">Pedro Silva</a>
+ */
+public class LDAPIdentityStore implements IdentityStore {
+
+    private static final Logger logger = Logger.getLogger(LDAPIdentityStore.class);
+
+    public static final String EMPTY_ATTRIBUTE_VALUE = " ";
+
+    private final LDAPIdentityStoreConfiguration config;
+    private final LDAPOperationManager operationManager;
+
+    public LDAPIdentityStore(LDAPIdentityStoreConfiguration config) {
+        this.config = config;
+
+        try {
+            this.operationManager = new LDAPOperationManager(getConfig());
+        } catch (NamingException e) {
+            throw new ModelException("Couldn't init operation manager", e);
+        }
+    }
+
+    @Override
+    public LDAPIdentityStoreConfiguration getConfig() {
+        return this.config;
+    }
+
+    @Override
+    public void add(AttributedType attributedType) {
+        // id will be assigned by the ldap server
+        attributedType.setId(null);
+
+        String entryDN = getBindingDN(attributedType, true);
+        this.operationManager.createSubContext(entryDN, extractAttributes(attributedType, true));
+        addToParentAsMember(attributedType);
+        attributedType.setId(getEntryIdentifier(attributedType));
+
+        attributedType.setEntryDN(entryDN);
+
+        if (logger.isTraceEnabled()) {
+            logger.tracef("Type with identifier [%s] successfully added to identity store [%s].", attributedType.getId(), this);
+        }
+    }
+
+    @Override
+    public void update(AttributedType attributedType) {
+        BasicAttributes updatedAttributes = extractAttributes(attributedType, false);
+        NamingEnumeration<Attribute> attributes = updatedAttributes.getAll();
+
+        this.operationManager.modifyAttributes(getBindingDN(attributedType, true), attributes);
+
+        if (logger.isTraceEnabled()) {
+            logger.tracef("Type with identifier [%s] successfully updated to identity store [%s].", attributedType.getId(), this);
+        }
+    }
+
+    @Override
+    public void remove(AttributedType attributedType) {
+        LDAPMappingConfiguration mappingConfig = getMappingConfig(attributedType.getClass());
+
+        this.operationManager.removeEntryById(getBaseDN(attributedType), attributedType.getId(), mappingConfig);
+
+        if (logger.isTraceEnabled()) {
+            logger.tracef("Type with identifier [%s] successfully removed from identity store [%s].", attributedType.getId(), this);
+        }
+    }
+
+    @Override
+    public <V extends IdentityType> List<V> fetchQueryResults(IdentityQuery<V> identityQuery) {
+        List<V> results = new ArrayList<V>();
+
+        try {
+            if (identityQuery.getSorting() != null && !identityQuery.getSorting().isEmpty()) {
+                throw new ModelException("LDAP Identity Store does not support sorted queries.");
+            }
+
+            for (Condition condition : identityQuery.getConditions()) {
+
+                if (IdentityType.ID.equals(condition.getParameter())) {
+                    if (EqualCondition.class.isInstance(condition)) {
+                        EqualCondition equalCondition = (EqualCondition) condition;
+                        SearchResult search = this.operationManager
+                                .lookupById(getConfig().getBaseDN(), equalCondition.getValue().toString(), null);
+
+                        if (search != null) {
+                            results.add((V) populateAttributedType(search, null));
+                        }
+                    }
+
+                    return results;
+                }
+            }
+
+            if (!IdentityType.class.equals(identityQuery.getIdentityType())) {
+                // the ldap store does not support queries based on root types. Except if based on the identifier.
+                LDAPMappingConfiguration ldapEntryConfig = getMappingConfig(identityQuery.getIdentityType());
+                StringBuilder filter = createIdentityTypeSearchFilter(identityQuery, ldapEntryConfig);
+                String baseDN = getBaseDN(ldapEntryConfig);
+                List<SearchResult> search;
+
+                if (getConfig().isPagination() && identityQuery.getLimit() > 0) {
+                    search = this.operationManager.searchPaginated(baseDN, filter.toString(), ldapEntryConfig, identityQuery);
+                } else {
+                    search = this.operationManager.search(baseDN, filter.toString(), ldapEntryConfig);
+                }
+
+                for (SearchResult result : search) {
+                    if (!result.getNameInNamespace().equals(baseDN)) {
+                        results.add((V) populateAttributedType(result, null));
+                    }
+                }
+            }
+        } catch (Exception e) {
+            throw new ModelException("Querying of identity type failed " + identityQuery, e);
+        }
+
+        return results;
+    }
+
+    @Override
+    public <V extends IdentityType> int countQueryResults(IdentityQuery<V> identityQuery) {
+        int limit = identityQuery.getLimit();
+        int offset = identityQuery.getOffset();
+
+        identityQuery.setLimit(0);
+        identityQuery.setOffset(0);
+
+        int resultCount = identityQuery.getResultList().size();
+
+        identityQuery.setLimit(limit);
+        identityQuery.setOffset(offset);
+
+        return resultCount;
+    }
+
+    public IdentityQueryBuilder createQueryBuilder() {
+        return new DefaultQueryBuilder(this);
+    }
+
+    // *************** CREDENTIALS AND USER SPECIFIC STUFF
+
+    @Override
+    public boolean validatePassword(LDAPUser user, String password) {
+        String userDN = getEntryDNOfUser(user);
+
+        if (logger.isDebugEnabled()) {
+            logger.debugf("Using DN [%s] for authentication of user [%s]", userDN, user.getLoginName());
+        }
+
+        if (operationManager.authenticate(userDN, password)) {
+            return true;
+        }
+
+        return false;
+    }
+
+    @Override
+    public void updatePassword(LDAPUser user, String password) {
+        String userDN = getEntryDNOfUser(user);
+
+        if (logger.isDebugEnabled()) {
+            logger.debugf("Using DN [%s] for updating LDAP password of user [%s]", userDN, user.getLoginName());
+        }
+
+        if (getConfig().isActiveDirectory()) {
+            updateADPassword(userDN, password);
+        } else {
+            ModificationItem[] mods = new ModificationItem[1];
+
+            try {
+                BasicAttribute mod0 = new BasicAttribute(LDAPConstants.USER_PASSWORD_ATTRIBUTE, password);
+
+                mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, mod0);
+
+                operationManager.modifyAttribute(userDN, mod0);
+            } catch (Exception e) {
+                throw new ModelException("Error updating password.", e);
+            }
+        }
+    }
+
+
+    private void updateADPassword(String userDN, String password) {
+        try {
+            // Replace the "unicdodePwd" attribute with a new value
+            // Password must be both Unicode and a quoted string
+            String newQuotedPassword = "\"" + password + "\"";
+            byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE");
+
+            BasicAttribute unicodePwd = new BasicAttribute("unicodePwd", newUnicodePassword);
+
+            List<ModificationItem> modItems = new ArrayList<ModificationItem>();
+            modItems.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE, unicodePwd));
+
+            // Used in ActiveDirectory to put account into "enabled" state (aka userAccountControl=512, see http://support.microsoft.com/kb/305144/en ) after password update. If value is -1, it's ignored
+            if (getConfig().isUserAccountControlsAfterPasswordUpdate()) {
+                BasicAttribute userAccountControl = new BasicAttribute("userAccountControl", "512");
+                modItems.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE, userAccountControl));
+
+                logger.debugf("Attribute userAccountControls will be switched to 512 after password update of user [%s]", userDN);
+            }
+
+            operationManager.modifyAttributes(userDN, modItems.toArray(new ModificationItem[] {}));
+        } catch (Exception e) {
+            throw new ModelException(e);
+        }
+    }
+
+
+    private String getEntryDNOfUser(LDAPUser user) {
+        // First try if user already has entryDN on him
+        String entryDN = user.getEntryDN();
+        if (entryDN != null) {
+            return entryDN;
+        }
+
+        // Need to find user in LDAP
+        String username = user.getLoginName();
+        user = getUser(username);
+        if (user == null) {
+            throw new ModelException("No LDAP user found with username " + username);
+        }
+
+        return user.getEntryDN();
+    }
+
+
+    public LDAPUser getUser(String username) {
+
+        if (isNullOrEmpty(username)) {
+            return null;
+        }
+
+        IdentityQueryBuilder queryBuilder = createQueryBuilder();
+        List<LDAPUser> agents = queryBuilder.createIdentityQuery(LDAPUser.class)
+                .where(queryBuilder.equal(LDAPUser.LOGIN_NAME, username)).getResultList();
+
+        if (agents.isEmpty()) {
+            return null;
+        } else if (agents.size() == 1) {
+            return agents.get(0);
+        } else {
+            throw new ModelDuplicateException("Error - multiple Agent objects found with same login name");
+        }
+    }
+
+    // ************ END CREDENTIALS AND USER SPECIFIC STUFF
+
+
+    private String getBaseDN(final LDAPMappingConfiguration ldapEntryConfig) {
+        String baseDN = getConfig().getBaseDN();
+
+        if (ldapEntryConfig.getBaseDN() != null) {
+            baseDN = ldapEntryConfig.getBaseDN();
+        }
+
+        return baseDN;
+    }
+
+    protected <V extends IdentityType> StringBuilder createIdentityTypeSearchFilter(final IdentityQuery<V> identityQuery, final LDAPMappingConfiguration ldapEntryConfig) {
+        StringBuilder filter = new StringBuilder();
+
+        for (Condition condition : identityQuery.getConditions()) {
+            QueryParameter queryParameter = condition.getParameter();
+
+            if (!IdentityType.ID.equals(queryParameter)) {
+                if (AttributeParameter.class.isInstance(queryParameter)) {
+                    AttributeParameter attributeParameter = (AttributeParameter) queryParameter;
+                    String attributeName = ldapEntryConfig.getMappedProperties().get(attributeParameter.getName());
+
+                    if (attributeName != null) {
+                        if (EqualCondition.class.isInstance(condition)) {
+                            EqualCondition equalCondition = (EqualCondition) condition;
+                            Object parameterValue = equalCondition.getValue();
+
+                            if (Date.class.isInstance(parameterValue)) {
+                                parameterValue = LDAPUtil.formatDate((Date) parameterValue);
+                            }
+
+                            filter.append("(").append(attributeName).append(LDAPConstants.EQUAL).append(parameterValue).append(")");
+                        } else if (LikeCondition.class.isInstance(condition)) {
+                            LikeCondition likeCondition = (LikeCondition) condition;
+                            String parameterValue = (String) likeCondition.getValue();
+
+                        } else if (GreaterThanCondition.class.isInstance(condition)) {
+                            GreaterThanCondition greaterThanCondition = (GreaterThanCondition) condition;
+                            Comparable parameterValue = (Comparable) greaterThanCondition.getValue();
+
+                            if (Date.class.isInstance(parameterValue)) {
+                                parameterValue = LDAPUtil.formatDate((Date) parameterValue);
+                            }
+
+                            if (greaterThanCondition.isOrEqual()) {
+                                filter.append("(").append(attributeName).append(">=").append(parameterValue).append(")");
+                            } else {
+                                filter.append("(").append(attributeName).append(">").append(parameterValue).append(")");
+                            }
+                        } else if (LessThanCondition.class.isInstance(condition)) {
+                            LessThanCondition lessThanCondition = (LessThanCondition) condition;
+                            Comparable parameterValue = (Comparable) lessThanCondition.getValue();
+
+                            if (Date.class.isInstance(parameterValue)) {
+                                parameterValue = LDAPUtil.formatDate((Date) parameterValue);
+                            }
+
+                            if (lessThanCondition.isOrEqual()) {
+                                filter.append("(").append(attributeName).append("<=").append(parameterValue).append(")");
+                            } else {
+                                filter.append("(").append(attributeName).append("<").append(parameterValue).append(")");
+                            }
+                        } else if (BetweenCondition.class.isInstance(condition)) {
+                            BetweenCondition betweenCondition = (BetweenCondition) condition;
+                            Comparable x = betweenCondition.getX();
+                            Comparable y = betweenCondition.getY();
+
+                            if (Date.class.isInstance(x)) {
+                                x = LDAPUtil.formatDate((Date) x);
+                            }
+
+                            if (Date.class.isInstance(y)) {
+                                y = LDAPUtil.formatDate((Date) y);
+                            }
+
+                            filter.append("(").append(x).append("<=").append(attributeName).append("<=").append(y).append(")");
+                        } else if (InCondition.class.isInstance(condition)) {
+                            InCondition inCondition = (InCondition) condition;
+                            Object[] valuesToCompare = inCondition.getValue();
+
+                            filter.append("(&(");
+
+                            for (int i = 0; i< valuesToCompare.length; i++) {
+                                Object value = valuesToCompare[i];
+
+                                filter.append("(").append(attributeName).append(LDAPConstants.EQUAL).append(value).append(")");
+                            }
+
+                            filter.append("))");
+                        } else {
+                            throw new ModelException("Unsupported query condition [" + condition + "].");
+                        }
+                    }
+                }
+            }
+        }
+
+
+        filter.insert(0, "(&(");
+        filter.append(getObjectClassesFilter(ldapEntryConfig));
+        filter.append("))");
+
+        return filter;
+    }
+
+    private StringBuilder getObjectClassesFilter(final LDAPMappingConfiguration ldapEntryConfig) {
+        StringBuilder builder = new StringBuilder();
+
+        if (ldapEntryConfig != null && !ldapEntryConfig.getObjectClasses().isEmpty()) {
+            for (String objectClass : ldapEntryConfig.getObjectClasses()) {
+                builder.append("(").append(LDAPConstants.OBJECT_CLASS).append(LDAPConstants.EQUAL).append(objectClass).append(")");
+            }
+        } else {
+            builder.append("(").append(LDAPConstants.OBJECT_CLASS).append(LDAPConstants.EQUAL).append("*").append(")");
+        }
+
+        return builder;
+    }
+
+    private AttributedType populateAttributedType(SearchResult searchResult, AttributedType attributedType) {
+        return populateAttributedType(searchResult, attributedType, 0);
+    }
+
+    private AttributedType populateAttributedType(SearchResult searchResult, AttributedType attributedType, int hierarchyDepthCount) {
+        try {
+            String entryDN = searchResult.getNameInNamespace();
+            Attributes attributes = searchResult.getAttributes();
+
+            if (attributedType == null) {
+                attributedType = Reflections.newInstance(getConfig().getSupportedTypeByBaseDN(entryDN, getEntryObjectClasses(attributes)));
+            }
+
+            attributedType.setEntryDN(entryDN);
+
+            LDAPMappingConfiguration mappingConfig = getMappingConfig(attributedType.getClass());
+
+            if (hierarchyDepthCount > mappingConfig.getHierarchySearchDepth()) {
+                return null;
+            }
+
+            if (logger.isTraceEnabled()) {
+                logger.tracef("Populating attributed type [%s] from DN [%s]", attributedType, entryDN);
+            }
+
+            NamingEnumeration<? extends Attribute> ldapAttributes = attributes.getAll();
+
+            while (ldapAttributes.hasMore()) {
+                Attribute ldapAttribute = ldapAttributes.next();
+                Object attributeValue;
+
+                try {
+                    attributeValue = ldapAttribute.get();
+                } catch (NoSuchElementException nsee) {
+                    continue;
+                }
+
+                String ldapAttributeName = ldapAttribute.getID();
+
+                if (ldapAttributeName.toLowerCase().equals(getConfig().getUniqueIdentifierAttributeName().toLowerCase())) {
+                    attributedType.setId(this.operationManager.decodeEntryUUID(attributeValue));
+                } else {
+                    String attributeName = findAttributeName(mappingConfig.getMappedProperties(), ldapAttributeName);
+
+                    if (attributeName != null) {
+                        // Find if it's java property or attribute
+                        Property<Object> property = PropertyQueries
+                                .createQuery(attributedType.getClass())
+                                .addCriteria(new NamedPropertyCriteria(attributeName)).getFirstResult();
+
+                        if (property != null) {
+                            if (logger.isTraceEnabled()) {
+                                logger.tracef("Populating property [%s] from ldap attribute [%s] with value [%s] from DN [%s].", property.getName(), ldapAttributeName, attributeValue, entryDN);
+                            }
+
+                            if (property.getJavaClass().equals(Date.class)) {
+                                property.setValue(attributedType, LDAPUtil.parseDate(attributeValue.toString()));
+                            } else {
+                                property.setValue(attributedType, attributeValue);
+                            }
+                        } else {
+                            if (logger.isTraceEnabled()) {
+                                logger.tracef("Populating attribute [%s] from ldap attribute [%s] with value [%s] from DN [%s].", attributeName, ldapAttributeName, attributeValue, entryDN);
+                            }
+
+                            attributedType.setAttribute(new org.keycloak.federation.ldap.idm.model.Attribute(attributeName, (Serializable) attributeValue));
+                        }
+                    }
+                }
+            }
+
+            if (IdentityType.class.isInstance(attributedType)) {
+                IdentityType identityType = (IdentityType) attributedType;
+
+                String createdTimestamp = attributes.get(LDAPConstants.CREATE_TIMESTAMP).get().toString();
+
+                identityType.setCreatedDate(LDAPUtil.parseDate(createdTimestamp));
+            }
+
+            LDAPMappingConfiguration entryConfig = getMappingConfig(attributedType.getClass());
+
+            if (mappingConfig.getParentMembershipAttributeName() != null) {
+                StringBuilder filter = new StringBuilder("(&");
+                String entryBaseDN = entryDN.substring(entryDN.indexOf(LDAPConstants.COMMA) + 1);
+
+                filter
+                        .append("(")
+                        .append(getObjectClassesFilter(entryConfig))
+                        .append(")")
+                        .append("(")
+                        .append(mappingConfig.getParentMembershipAttributeName())
+                        .append(LDAPConstants.EQUAL).append("")
+                        .append(getBindingDN(attributedType, false))
+                        .append(LDAPConstants.COMMA)
+                        .append(entryBaseDN)
+                        .append(")");
+
+                filter.append(")");
+
+                if (logger.isTraceEnabled()) {
+                    logger.tracef("Searching parent entry for DN [%s] using filter [%s].", entryBaseDN, filter.toString());
+                }
+
+                List<SearchResult> search = this.operationManager.search(getConfig().getBaseDN(), filter.toString(), entryConfig);
+
+                if (!search.isEmpty()) {
+                    SearchResult next = search.get(0);
+
+                    Property<AttributedType> parentProperty = PropertyQueries
+                            .<AttributedType>createQuery(attributedType.getClass())
+                            .addCriteria(new TypedPropertyCriteria(attributedType.getClass())).getFirstResult();
+
+                    if (parentProperty != null) {
+                        String parentDN = next.getNameInNamespace();
+                        String parentBaseDN = parentDN.substring(parentDN.indexOf(",") + 1);
+                        Class<? extends AttributedType> baseDNType = getConfig().getSupportedTypeByBaseDN(parentBaseDN, getEntryObjectClasses(attributes));
+
+                        if (parentProperty.getJavaClass().isAssignableFrom(baseDNType)) {
+                            if (logger.isTraceEnabled()) {
+                                logger.tracef("Found parent [%s] for entry for DN [%s].", parentDN, entryDN);
+                            }
+
+                            int hierarchyDepthCount1 = ++hierarchyDepthCount;
+
+                            parentProperty.setValue(attributedType, populateAttributedType(next, null, hierarchyDepthCount1));
+                        }
+                    }
+                } else {
+                    if (logger.isTraceEnabled()) {
+                        logger.tracef("No parent entry found for DN [%s] using filter [%s].", entryDN, filter.toString());
+                    }
+                }
+            }
+        } catch (Exception e) {
+            throw new ModelException("Could not populate attribute type " + attributedType + ".", e);
+        }
+
+        return attributedType;
+    }
+
+    private String findAttributeName(Map<String, String> attrMapping, String ldapAttributeName) {
+        for (Map.Entry<String,String> currentAttr : attrMapping.entrySet()) {
+            if (currentAttr.getValue().equalsIgnoreCase(ldapAttributeName)) {
+                return currentAttr.getKey();
+            }
+        }
+
+        return null;
+    }
+
+    private List<String> getEntryObjectClasses(final Attributes attributes) throws NamingException {
+        Attribute objectClassesAttribute = attributes.get(LDAPConstants.OBJECT_CLASS);
+        List<String> objectClasses = new ArrayList<String>();
+
+        if (objectClassesAttribute == null) {
+            return objectClasses;
+        }
+
+        NamingEnumeration<?> all = objectClassesAttribute.getAll();
+
+        while (all.hasMore()) {
+            objectClasses.add(all.next().toString());
+        }
+
+        return objectClasses;
+    }
+
+    protected BasicAttributes extractAttributes(AttributedType attributedType, boolean isCreate) {
+        BasicAttributes entryAttributes = new BasicAttributes();
+        LDAPMappingConfiguration mappingConfig = getMappingConfig(attributedType.getClass());
+        Map<String, String> mappedProperties = mappingConfig.getMappedProperties();
+
+        for (String propertyName : mappedProperties.keySet()) {
+            if (!mappingConfig.getReadOnlyAttributes().contains(propertyName) && (isCreate || !mappingConfig.getBindingProperty().getName().equals(propertyName))) {
+                Property<Object> property = PropertyQueries
+                        .<Object>createQuery(attributedType.getClass())
+                        .addCriteria(new NamedPropertyCriteria(propertyName)).getFirstResult();
+
+                Object propertyValue = null;
+                if (property != null) {
+                    // Mapped Java property on the object
+                    propertyValue = property.getValue(attributedType);
+                } else {
+                    // Not mapped property. So fallback to attribute
+                    org.keycloak.federation.ldap.idm.model.Attribute<?> attribute = attributedType.getAttribute(propertyName);
+                    if (attribute != null) {
+                        propertyValue = attribute.getValue();
+                    }
+                }
+
+                if (AttributedType.class.isInstance(propertyValue)) {
+                    AttributedType referencedType = (AttributedType) propertyValue;
+                    propertyValue = getBindingDN(referencedType, true);
+                } else {
+                    if (propertyValue == null || isNullOrEmpty(propertyValue.toString())) {
+                        propertyValue = EMPTY_ATTRIBUTE_VALUE;
+                    }
+                }
+
+                entryAttributes.put(mappedProperties.get(propertyName), propertyValue);
+            }
+        }
+
+        // Don't extract object classes for update
+        if (isCreate) {
+            LDAPMappingConfiguration ldapEntryConfig = getMappingConfig(attributedType.getClass());
+
+            BasicAttribute objectClassAttribute = new BasicAttribute(LDAPConstants.OBJECT_CLASS);
+
+            for (String objectClassValue : ldapEntryConfig.getObjectClasses()) {
+                objectClassAttribute.add(objectClassValue);
+
+                if (objectClassValue.equals(LDAPConstants.GROUP_OF_NAMES)
+                        || objectClassValue.equals(LDAPConstants.GROUP_OF_ENTRIES)
+                        || objectClassValue.equals(LDAPConstants.GROUP_OF_UNIQUE_NAMES)) {
+                    entryAttributes.put(LDAPConstants.MEMBER, EMPTY_ATTRIBUTE_VALUE);
+                }
+            }
+
+            entryAttributes.put(objectClassAttribute);
+        }
+
+        return entryAttributes;
+    }
+
+    // TODO: Move class StringUtil from SAML module
+    public static boolean isNullOrEmpty(String str) {
+        return str == null || str.isEmpty();
+    }
+
+    private LDAPMappingConfiguration getMappingConfig(Class<? extends AttributedType> attributedType) {
+        LDAPMappingConfiguration mappingConfig = getConfig().getMappingConfig(attributedType);
+
+        if (mappingConfig == null) {
+            throw new ModelException("Not mapped type [" + attributedType + "].");
+        }
+
+        return mappingConfig;
+    }
+
+    public String getBindingDN(AttributedType attributedType, boolean appendBaseDN) {
+        LDAPMappingConfiguration mappingConfig = getMappingConfig(attributedType.getClass());
+        Property<String> idProperty = mappingConfig.getIdProperty();
+
+        String baseDN;
+
+        if (mappingConfig.getBaseDN() == null || !appendBaseDN) {
+            baseDN = "";
+        } else {
+            baseDN = LDAPConstants.COMMA + getBaseDN(attributedType);
+        }
+
+        Property<String> bindingProperty = mappingConfig.getBindingProperty();
+        String bindingAttribute;
+        String dn;
+
+        if (bindingProperty == null) {
+            bindingAttribute = mappingConfig.getMappedProperties().get(idProperty.getName());
+            dn = idProperty.getValue(attributedType);
+        } else {
+            bindingAttribute = mappingConfig.getMappedProperties().get(bindingProperty.getName());
+            dn = mappingConfig.getBindingProperty().getValue(attributedType);
+        }
+
+        return bindingAttribute + LDAPConstants.EQUAL + dn + baseDN;
+    }
+
+    private String getBaseDN(AttributedType attributedType) {
+        LDAPMappingConfiguration mappingConfig = getMappingConfig(attributedType.getClass());
+        String baseDN = mappingConfig.getBaseDN();
+        String parentDN = mappingConfig.getParentMapping().get(mappingConfig.getIdProperty().getValue(attributedType));
+
+        if (parentDN != null) {
+            baseDN = parentDN;
+        } else {
+            Property<AttributedType> parentProperty = PropertyQueries
+                    .<AttributedType>createQuery(attributedType.getClass())
+                    .addCriteria(new TypedPropertyCriteria(attributedType.getClass())).getFirstResult();
+
+            if (parentProperty != null) {
+                AttributedType parentType = parentProperty.getValue(attributedType);
+
+                if (parentType != null) {
+                    Property<String> parentIdProperty = getMappingConfig(parentType.getClass()).getIdProperty();
+
+                    String parentId = parentIdProperty.getValue(parentType);
+
+                    String parentBaseDN = mappingConfig.getParentMapping().get(parentId);
+
+                    if (parentBaseDN != null) {
+                        baseDN = parentBaseDN;
+                    } else {
+                        baseDN = getBaseDN(parentType);
+                    }
+                }
+            }
+        }
+
+        if (baseDN == null) {
+            baseDN = getConfig().getBaseDN();
+        }
+
+        return baseDN;
+    }
+
+    protected void addToParentAsMember(final AttributedType attributedType) {
+        LDAPMappingConfiguration entryConfig = getMappingConfig(attributedType.getClass());
+
+        if (entryConfig.getParentMembershipAttributeName() != null) {
+            Property<AttributedType> parentProperty = PropertyQueries
+                    .<AttributedType>createQuery(attributedType.getClass())
+                    .addCriteria(new TypedPropertyCriteria(attributedType.getClass()))
+                    .getFirstResult();
+
+            if (parentProperty != null) {
+                AttributedType parentType = parentProperty.getValue(attributedType);
+
+                if (parentType != null) {
+                    Attributes attributes = this.operationManager.getAttributes(parentType.getId(), getBaseDN(parentType), entryConfig);
+                    Attribute attribute = attributes.get(entryConfig.getParentMembershipAttributeName());
+
+                    attribute.add(getBindingDN(attributedType, true));
+
+                    this.operationManager.modifyAttribute(getBindingDN(parentType, true), attribute);
+                }
+            }
+        }
+    }
+
+    protected String getEntryIdentifier(final AttributedType attributedType) {
+        try {
+            // we need this to retrieve the entry's identifier from the ldap server
+            List<SearchResult> search = this.operationManager.search(getBaseDN(attributedType), "(" + getBindingDN(attributedType, false) + ")", getMappingConfig(attributedType.getClass()));
+            Attribute id = search.get(0).getAttributes().get(getConfig().getUniqueIdentifierAttributeName());
+
+            if (id == null) {
+                throw new ModelException("Could not retrieve identifier for entry [" + getBindingDN(attributedType, true) + "].");
+            }
+
+            return this.operationManager.decodeEntryUUID(id.get());
+        } catch (NamingException ne) {
+            throw new ModelException("Could not add type [" + attributedType + "].", ne);
+        }
+    }
+}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPIdentityStoreConfiguration.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPIdentityStoreConfiguration.java
new file mode 100644
index 0000000..0c0a2e1
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPIdentityStoreConfiguration.java
@@ -0,0 +1,188 @@
+package org.keycloak.federation.ldap.idm.store.ldap;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.keycloak.federation.ldap.idm.model.AttributedType;
+import org.keycloak.models.LDAPConstants;
+import org.keycloak.models.ModelException;
+
+/**
+ * A configuration for the LDAP store.
+ *
+ * @author anil saldhana
+ * @since Sep 6, 2012
+ */
+
+public class LDAPIdentityStoreConfiguration {
+
+    private String ldapURL;
+    private String factoryName = "com.sun.jndi.ldap.LdapCtxFactory";
+    private String authType = "simple";
+    private String protocol;
+    private String bindDN;
+    private String bindCredential;
+    private boolean activeDirectory;
+    private Properties connectionProperties;
+    private boolean pagination;
+    private String uniqueIdentifierAttributeName;
+    private boolean userAccountControlsAfterPasswordUpdate;
+
+    private String baseDN;
+    private Map<Class<? extends AttributedType>, LDAPMappingConfiguration> mappingConfig = new HashMap<Class<? extends AttributedType>, LDAPMappingConfiguration>();
+
+    public String getLdapURL() {
+        return this.ldapURL;
+    }
+
+    public String getFactoryName() {
+        return this.factoryName;
+    }
+
+    public String getAuthType() {
+        return this.authType;
+    }
+
+    public String getBaseDN() {
+        return this.baseDN;
+    }
+
+    public String getBindDN() {
+        return this.bindDN;
+    }
+
+    public String getBindCredential() {
+        return this.bindCredential;
+    }
+
+    public boolean isActiveDirectory() {
+        return this.activeDirectory;
+    }
+
+    public Properties getConnectionProperties() {
+        return this.connectionProperties;
+    }
+
+    public LDAPMappingConfiguration mappingConfig(Class<? extends AttributedType> clazz) {
+        LDAPMappingConfiguration mappingConfig = new LDAPMappingConfiguration(clazz);
+        this.mappingConfig.put(clazz, mappingConfig);
+        return mappingConfig;
+    }
+
+    public Class<? extends AttributedType> getSupportedTypeByBaseDN(String entryDN, List<String> objectClasses) {
+        String entryBaseDN = entryDN.substring(entryDN.indexOf(LDAPConstants.COMMA) + 1);
+
+        for (LDAPMappingConfiguration mappingConfig : this.mappingConfig.values()) {
+            if (mappingConfig.getBaseDN() != null) {
+
+                if (mappingConfig.getBaseDN().equalsIgnoreCase(entryDN)
+                        || mappingConfig.getParentMapping().values().contains(entryDN)) {
+                    return mappingConfig.getMappedClass();
+                }
+
+                if (mappingConfig.getBaseDN().equalsIgnoreCase(entryBaseDN)
+                        || mappingConfig.getParentMapping().values().contains(entryBaseDN)) {
+                    return mappingConfig.getMappedClass();
+                }
+            }
+        }
+
+        for (LDAPMappingConfiguration mappingConfig : this.mappingConfig.values()) {
+            for (String objectClass : objectClasses) {
+                if (mappingConfig.getObjectClasses().contains(objectClass)) {
+                    return mappingConfig.getMappedClass();
+                }
+            }
+        }
+
+        throw new ModelException("No type found with Base DN [" + entryDN + "] or objectClasses [" + objectClasses + ".");
+    }
+
+    public LDAPMappingConfiguration getMappingConfig(Class<? extends AttributedType> attributedType) {
+        for (LDAPMappingConfiguration mappingConfig : this.mappingConfig.values()) {
+            if (attributedType.equals(mappingConfig.getMappedClass())) {
+                return mappingConfig;
+            }
+        }
+
+        return null;
+    }
+
+    public String getProtocol() {
+        return protocol;
+    }
+
+    public String getUniqueIdentifierAttributeName() {
+        return uniqueIdentifierAttributeName;
+    }
+
+    public boolean isPagination() {
+        return pagination;
+    }
+
+    public boolean isUserAccountControlsAfterPasswordUpdate() {
+        return userAccountControlsAfterPasswordUpdate;
+    }
+
+    public LDAPIdentityStoreConfiguration setLdapURL(String ldapURL) {
+        this.ldapURL = ldapURL;
+        return this;
+    }
+
+    public LDAPIdentityStoreConfiguration setFactoryName(String factoryName) {
+        this.factoryName = factoryName;
+        return this;
+    }
+
+    public LDAPIdentityStoreConfiguration setAuthType(String authType) {
+        this.authType = authType;
+        return this;
+    }
+
+    public LDAPIdentityStoreConfiguration setProtocol(String protocol) {
+        this.protocol = protocol;
+        return this;
+    }
+
+    public LDAPIdentityStoreConfiguration setBindDN(String bindDN) {
+        this.bindDN = bindDN;
+        return this;
+    }
+
+    public LDAPIdentityStoreConfiguration setBindCredential(String bindCredential) {
+        this.bindCredential = bindCredential;
+        return this;
+    }
+
+    public LDAPIdentityStoreConfiguration setActiveDirectory(boolean activeDirectory) {
+        this.activeDirectory = activeDirectory;
+        return this;
+    }
+
+    public LDAPIdentityStoreConfiguration setPagination(boolean pagination) {
+        this.pagination = pagination;
+        return this;
+    }
+
+    public LDAPIdentityStoreConfiguration setConnectionProperties(Properties connectionProperties) {
+        this.connectionProperties = connectionProperties;
+        return this;
+    }
+
+    public LDAPIdentityStoreConfiguration setUniqueIdentifierAttributeName(String uniqueIdentifierAttributeName) {
+        this.uniqueIdentifierAttributeName = uniqueIdentifierAttributeName;
+        return this;
+    }
+
+    public LDAPIdentityStoreConfiguration setUserAccountControlsAfterPasswordUpdate(boolean userAccountControlsAfterPasswordUpdate) {
+        this.userAccountControlsAfterPasswordUpdate = userAccountControlsAfterPasswordUpdate;
+        return this;
+    }
+
+    public LDAPIdentityStoreConfiguration setBaseDN(String baseDN) {
+        this.baseDN = baseDN;
+        return this;
+    }
+}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPMappingConfiguration.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPMappingConfiguration.java
new file mode 100644
index 0000000..033d93b
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPMappingConfiguration.java
@@ -0,0 +1,231 @@
+package org.keycloak.federation.ldap.idm.store.ldap;
+
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Member;
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.keycloak.federation.ldap.idm.model.Attribute;
+import org.keycloak.federation.ldap.idm.model.AttributedType;
+import org.keycloak.federation.ldap.idm.model.IdentityType;
+import org.keycloak.models.ModelException;
+import org.keycloak.models.utils.reflection.NamedPropertyCriteria;
+import org.keycloak.models.utils.reflection.Property;
+import org.keycloak.models.utils.reflection.PropertyQueries;
+
+/**
+ * @author pedroigor
+ */
+public class LDAPMappingConfiguration {
+
+    private final Class<? extends AttributedType> mappedClass;
+    private Set<String> objectClasses;
+    private String baseDN;
+    private final Map<String, String> mappedProperties = new HashMap<String, String>();
+    private Property<String> idProperty;
+    private Class<? extends AttributedType> relatedAttributedType;
+    private String parentMembershipAttributeName;
+    private Map<String, String> parentMapping = new HashMap<String, String>();
+    private final Set<String> readOnlyAttributes = new HashSet<String>();
+    private int hierarchySearchDepth;
+    private Property<String> bindingProperty;
+
+    public LDAPMappingConfiguration(Class<? extends AttributedType> mappedClass) {
+        this.mappedClass = mappedClass;
+    }
+
+    public Class<? extends AttributedType> getMappedClass() {
+        return this.mappedClass;
+    }
+
+    public Set<String> getObjectClasses() {
+        return this.objectClasses;
+    }
+
+    public String getBaseDN() {
+        return this.baseDN;
+    }
+
+    public Map<String, String> getMappedProperties() {
+        return this.mappedProperties;
+    }
+
+    public Property<String> getIdProperty() {
+        return this.idProperty;
+    }
+
+    public Property<String> getBindingProperty() {
+        return this.bindingProperty;
+    }
+
+    public Class<? extends AttributedType> getRelatedAttributedType() {
+        return this.relatedAttributedType;
+    }
+
+    public String getParentMembershipAttributeName() {
+        return this.parentMembershipAttributeName;
+    }
+
+    public Map<String, String> getParentMapping() {
+        return this.parentMapping;
+    }
+
+    public Set<String> getReadOnlyAttributes() {
+        return this.readOnlyAttributes;
+    }
+
+    public int getHierarchySearchDepth() {
+        return this.hierarchySearchDepth;
+    }
+
+    private Property getBindingProperty(final String bindingPropertyName) {
+        Property bindingProperty = PropertyQueries
+                .<String>createQuery(getMappedClass())
+                .addCriteria(new NamedPropertyCriteria(bindingPropertyName)).getFirstResult();
+
+        // We don't have Java property, so actually delegate to setAttribute/getAttribute
+        if (bindingProperty == null) {
+            bindingProperty = new Property<String>() {
+
+                @Override
+                public String getName() {
+                    return bindingPropertyName;
+                }
+
+                @Override
+                public Type getBaseType() {
+                    return null;
+                }
+
+                @Override
+                public Class<String> getJavaClass() {
+                    return String.class;
+                }
+
+                @Override
+                public AnnotatedElement getAnnotatedElement() {
+                    return null;
+                }
+
+                @Override
+                public Member getMember() {
+                    return null;
+                }
+
+                @Override
+                public String getValue(Object instance) {
+                    if (!(instance instanceof AttributedType)) {
+                        throw new IllegalStateException("Instance [ " + instance + " ] not an instance of AttributedType");
+                    }
+
+                    AttributedType attributedType = (AttributedType) instance;
+                    Attribute<String> attr = attributedType.getAttribute(bindingPropertyName);
+                    return attr!=null ? attr.getValue() : null;
+                }
+
+                @Override
+                public void setValue(Object instance, String value) {
+                    if (!(instance instanceof AttributedType)) {
+                        throw new IllegalStateException("Instance [ " + instance + " ] not an instance of AttributedType");
+                    }
+
+                    AttributedType attributedType = (AttributedType) instance;
+                    attributedType.setAttribute(new Attribute(bindingPropertyName, value));
+                }
+
+                @Override
+                public Class<?> getDeclaringClass() {
+                    return null;
+                }
+
+                @Override
+                public boolean isReadOnly() {
+                    return false;
+                }
+
+                @Override
+                public void setAccessible() {
+
+                }
+
+                @Override
+                public boolean isAnnotationPresent(Class annotation) {
+                    return false;
+                }
+            };
+        }
+
+        return bindingProperty;
+    }
+
+    public LDAPMappingConfiguration setObjectClasses(Set<String> objectClasses) {
+        this.objectClasses = objectClasses;
+        return this;
+    }
+
+    public LDAPMappingConfiguration setBaseDN(String baseDN) {
+        this.baseDN = baseDN;
+        return this;
+    }
+
+    public LDAPMappingConfiguration addAttributeMapping(String userAttributeName, String ldapAttributeName) {
+        this.mappedProperties.put(userAttributeName, ldapAttributeName);
+        return this;
+    }
+
+    public LDAPMappingConfiguration addReadOnlyAttributeMapping(String userAttributeName, String ldapAttributeName) {
+        this.mappedProperties.put(userAttributeName, ldapAttributeName);
+        this.readOnlyAttributes.add(userAttributeName);
+        return this;
+    }
+
+    public LDAPMappingConfiguration setIdPropertyName(String idPropertyName) {
+
+        if (idPropertyName != null) {
+            this.idProperty = PropertyQueries
+                    .<String>createQuery(getMappedClass())
+                    .addCriteria(new NamedPropertyCriteria(idPropertyName)).getFirstResult();
+        } else {
+            this.idProperty = null;
+        }
+
+        if (IdentityType.class.isAssignableFrom(mappedClass) && idProperty == null) {
+            throw new ModelException("Id attribute not mapped to any property of [" + mappedClass + "].");
+        }
+
+        // Binding property is idProperty by default
+        if (this.bindingProperty == null) {
+            this.bindingProperty = this.idProperty;
+        }
+
+        return this;
+    }
+
+    public LDAPMappingConfiguration setRelatedAttributedType(Class<? extends AttributedType> relatedAttributedType) {
+        this.relatedAttributedType = relatedAttributedType;
+        return this;
+    }
+
+    public LDAPMappingConfiguration setParentMembershipAttributeName(String parentMembershipAttributeName) {
+        this.parentMembershipAttributeName = parentMembershipAttributeName;
+        return this;
+    }
+
+    public LDAPMappingConfiguration setParentMapping(Map<String, String> parentMapping) {
+        this.parentMapping = parentMapping;
+        return this;
+    }
+
+    public LDAPMappingConfiguration setHierarchySearchDepth(int hierarchySearchDepth) {
+        this.hierarchySearchDepth = hierarchySearchDepth;
+        return this;
+    }
+
+    public LDAPMappingConfiguration setBindingPropertyName(String bindingPropertyName) {
+        this.bindingProperty = getBindingProperty(bindingPropertyName);
+        return this;
+    }
+}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPOperationManager.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPOperationManager.java
new file mode 100644
index 0000000..507d61f
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPOperationManager.java
@@ -0,0 +1,606 @@
+package org.keycloak.federation.ldap.idm.store.ldap;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.naming.Binding;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.ModificationItem;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+import javax.naming.ldap.Control;
+import javax.naming.ldap.InitialLdapContext;
+import javax.naming.ldap.LdapContext;
+import javax.naming.ldap.PagedResultsControl;
+import javax.naming.ldap.PagedResultsResponseControl;
+
+import org.jboss.logging.Logger;
+import org.keycloak.federation.ldap.idm.model.IdentityType;
+import org.keycloak.federation.ldap.idm.query.IdentityQuery;
+import org.keycloak.models.LDAPConstants;
+import org.keycloak.models.ModelException;
+
+import static javax.naming.directory.SearchControls.SUBTREE_SCOPE;
+
+/**
+ * <p>This class provides a set of operations to manage LDAP trees.</p>
+ *
+ * @author Anil Saldhana
+ * @author <a href="mailto:psilva@redhat.com">Pedro Silva</a>
+ */
+public class LDAPOperationManager {
+
+    private static final Logger logger = Logger.getLogger(LDAPOperationManager.class);
+
+    private final LDAPIdentityStoreConfiguration config;
+    private final Map<String, Object> connectionProperties;
+
+    public LDAPOperationManager(LDAPIdentityStoreConfiguration config) throws NamingException {
+        this.config = config;
+        this.connectionProperties = Collections.unmodifiableMap(createConnectionProperties());
+    }
+
+    /**
+     * <p>
+     * Modifies the given {@link javax.naming.directory.Attribute} instance using the given DN. This method performs a REPLACE_ATTRIBUTE
+     * operation.
+     * </p>
+     *
+     * @param dn
+     * @param attribute
+     */
+    public void modifyAttribute(String dn, Attribute attribute) {
+        ModificationItem[] mods = new ModificationItem[]{new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attribute)};
+        modifyAttributes(dn, mods);
+    }
+
+    /**
+     * <p>
+     * Modifies the given {@link Attribute} instances using the given DN. This method performs a REPLACE_ATTRIBUTE
+     * operation.
+     * </p>
+     *
+     * @param dn
+     * @param attributes
+     */
+    public void modifyAttributes(String dn,  NamingEnumeration<Attribute> attributes) {
+        try {
+            List<ModificationItem> modItems = new ArrayList<ModificationItem>();
+            while (attributes.hasMore()) {
+                ModificationItem modItem = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attributes.next());
+                modItems.add(modItem);
+            }
+
+            modifyAttributes(dn, modItems.toArray(new ModificationItem[] {}));
+        } catch (NamingException ne) {
+            throw new ModelException("Could not modify attributes on entry from DN [" + dn + "]", ne);
+        }
+
+    }
+
+    /**
+     * <p>
+     * Removes the given {@link Attribute} instance using the given DN. This method performs a REMOVE_ATTRIBUTE
+     * operation.
+     * </p>
+     *
+     * @param dn
+     * @param attribute
+     */
+    public void removeAttribute(String dn, Attribute attribute) {
+        ModificationItem[] mods = new ModificationItem[]{new ModificationItem(DirContext.REMOVE_ATTRIBUTE, attribute)};
+        modifyAttributes(dn, mods);
+    }
+
+    /**
+     * <p>
+     * Adds the given {@link Attribute} instance using the given DN. This method performs a ADD_ATTRIBUTE operation.
+     * </p>
+     *
+     * @param dn
+     * @param attribute
+     */
+    public void addAttribute(String dn, Attribute attribute) {
+        ModificationItem[] mods = new ModificationItem[]{new ModificationItem(DirContext.ADD_ATTRIBUTE, attribute)};
+        modifyAttributes(dn, mods);
+    }
+
+    /**
+     * <p>
+     * Searches the LDAP tree.
+     * </p>
+     *
+     * @param baseDN
+     * @param id
+     *
+     * @return
+     */
+    public void removeEntryById(final String baseDN, final String id, final LDAPMappingConfiguration mappingConfiguration) {
+        final String filter = getFilterById(baseDN, id);
+
+        try {
+            final SearchControls cons = getSearchControls(mappingConfiguration);
+
+            execute(new LdapOperation<SearchResult>() {
+                @Override
+                public SearchResult execute(LdapContext context) throws NamingException {
+                    NamingEnumeration<SearchResult> result = context.search(baseDN, filter, cons);
+
+                    if (result.hasMore()) {
+                        SearchResult sr = result.next();
+                        if (logger.isDebugEnabled()) {
+                            logger.debugf("Removing entry [%s] with attributes: [", sr.getNameInNamespace());
+
+                            NamingEnumeration<? extends Attribute> all = sr.getAttributes().getAll();
+
+                            while (all.hasMore()) {
+                                Attribute attribute = all.next();
+
+                                logger.debugf("  %s = %s", attribute.getID(), attribute.get());
+                            }
+
+                            logger.debugf("]");
+                        }
+                        destroySubcontext(context, sr.getNameInNamespace());
+                    }
+
+                    result.close();
+
+                    return null;
+                }
+            });
+        } catch (NamingException e) {
+            throw new ModelException("Could not remove entry from DN [" + baseDN + "] and id [" + id + "]", e);
+        }
+    }
+
+    public List<SearchResult> search(final String baseDN, final String filter, LDAPMappingConfiguration mappingConfiguration) throws NamingException {
+        final List<SearchResult> result = new ArrayList<SearchResult>();
+        final SearchControls cons = getSearchControls(mappingConfiguration);
+
+        try {
+            return execute(new LdapOperation<List<SearchResult>>() {
+                @Override
+                public List<SearchResult> execute(LdapContext context) throws NamingException {
+                    NamingEnumeration<SearchResult> search = context.search(baseDN, filter, cons);
+
+                    while (search.hasMoreElements()) {
+                        result.add(search.nextElement());
+                    }
+
+                    search.close();
+
+                    return result;
+                }
+            });
+        } catch (NamingException e) {
+            logger.errorf(e, "Could not query server using DN [%s] and filter [%s]", baseDN, filter);
+            throw e;
+        }
+    }
+
+    public <V extends IdentityType> List<SearchResult> searchPaginated(final String baseDN, final String filter, LDAPMappingConfiguration mappingConfiguration, final IdentityQuery<V> identityQuery) throws NamingException {
+        final List<SearchResult> result = new ArrayList<SearchResult>();
+        final SearchControls cons = getSearchControls(mappingConfiguration);
+
+        try {
+            return execute(new LdapOperation<List<SearchResult>>() {
+                @Override
+                public List<SearchResult> execute(LdapContext context) throws NamingException {
+                    try {
+                        byte[] cookie = (byte[])identityQuery.getPaginationContext();
+                        PagedResultsControl pagedControls = new PagedResultsControl(identityQuery.getLimit(), cookie, Control.CRITICAL);
+                        context.setRequestControls(new Control[] { pagedControls });
+
+                        NamingEnumeration<SearchResult> search = context.search(baseDN, filter, cons);
+
+                        while (search.hasMoreElements()) {
+                            result.add(search.nextElement());
+                        }
+
+                        search.close();
+
+                        Control[] responseControls = context.getResponseControls();
+                        if (responseControls != null) {
+                            for (Control respControl : responseControls) {
+                                if (respControl instanceof PagedResultsResponseControl) {
+                                    PagedResultsResponseControl prrc = (PagedResultsResponseControl)respControl;
+                                    cookie = prrc.getCookie();
+                                    identityQuery.setPaginationContext(cookie);
+                                }
+                            }
+                        }
+
+                        return result;
+                    } catch (IOException ioe) {
+                        logger.errorf(ioe, "Could not query server with paginated query using DN [%s], filter [%s]", baseDN, filter);
+                        throw new NamingException(ioe.getMessage());
+                    }
+                }
+            });
+        } catch (NamingException e) {
+            logger.errorf(e, "Could not query server using DN [%s] and filter [%s]", baseDN, filter);
+            throw e;
+        }
+    }
+
+    private SearchControls getSearchControls(LDAPMappingConfiguration mappingConfiguration) {
+        final SearchControls cons = new SearchControls();
+
+        cons.setSearchScope(SUBTREE_SCOPE);
+        cons.setReturningObjFlag(false);
+
+        List<String> returningAttributes = getReturningAttributes(mappingConfiguration);
+
+        cons.setReturningAttributes(returningAttributes.toArray(new String[returningAttributes.size()]));
+        return cons;
+    }
+
+    public String getFilterById(String baseDN, String id) {
+        String filter = null;
+
+        if (this.config.isActiveDirectory()) {
+            final String strObjectGUID = "<GUID=" + id + ">";
+
+            try {
+                Attributes attributes = execute(new LdapOperation<Attributes>() {
+                    @Override
+                    public Attributes execute(LdapContext context) throws NamingException {
+                        return context.getAttributes(strObjectGUID);
+                    }
+                });
+
+                byte[] objectGUID = (byte[]) attributes.get(LDAPConstants.OBJECT_GUID).get();
+
+                filter = "(&(objectClass=*)(" + getUniqueIdentifierAttributeName() + LDAPConstants.EQUAL + LDAPUtil.convertObjectGUIToByteString(objectGUID) + "))";
+            } catch (NamingException ne) {
+                return filter;
+            }
+        }
+
+        if (filter == null) {
+            filter = "(&(objectClass=*)(" + getUniqueIdentifierAttributeName() + LDAPConstants.EQUAL + id + "))";
+        }
+
+        return filter;
+    }
+
+    public SearchResult lookupById(final String baseDN, final String id, final LDAPMappingConfiguration mappingConfiguration) {
+        final String filter = getFilterById(baseDN, id);
+
+        try {
+            final SearchControls cons = getSearchControls(mappingConfiguration);
+
+            return execute(new LdapOperation<SearchResult>() {
+                @Override
+                public SearchResult execute(LdapContext context) throws NamingException {
+                    NamingEnumeration<SearchResult> search = context.search(baseDN, filter, cons);
+
+                    try {
+                        if (search.hasMoreElements()) {
+                            return search.next();
+                        }
+                    } finally {
+                        if (search != null) {
+                            search.close();
+                        }
+                    }
+
+                    return null;
+                }
+            });
+        } catch (NamingException e) {
+            throw new ModelException("Could not query server using DN [" + baseDN + "] and filter [" + filter + "]", e);
+        }
+    }
+
+    /**
+     * <p>
+     * Destroys a subcontext with the given DN from the LDAP tree.
+     * </p>
+     *
+     * @param dn
+     */
+    private void destroySubcontext(LdapContext context, final String dn) {
+        try {
+            NamingEnumeration<Binding> enumeration = null;
+
+            try {
+                enumeration = context.listBindings(dn);
+
+                while (enumeration.hasMore()) {
+                    Binding binding = enumeration.next();
+                    String name = binding.getNameInNamespace();
+
+                    destroySubcontext(context, name);
+                }
+
+                context.unbind(dn);
+            } finally {
+                try {
+                    enumeration.close();
+                } catch (Exception e) {
+                }
+            }
+        } catch (Exception e) {
+            throw new ModelException("Could not unbind DN [" + dn + "]", e);
+        }
+    }
+
+    /**
+     * <p>
+     * Performs a simple authentication using the given DN and password to bind to the authentication context.
+     * </p>
+     *
+     * @param dn
+     * @param password
+     *
+     * @return
+     */
+    public boolean authenticate(String dn, String password) {
+        InitialContext authCtx = null;
+
+        try {
+            Hashtable<String, Object> env = new Hashtable<String, Object>(this.connectionProperties);
+
+            env.put(Context.SECURITY_PRINCIPAL, dn);
+            env.put(Context.SECURITY_CREDENTIALS, password);
+
+            // Never use connection pool to prevent password caching
+            env.put("com.sun.jndi.ldap.connect.pool", "false");
+
+            authCtx = new InitialLdapContext(env, null);
+
+            return true;
+        } catch (Exception e) {
+            if (logger.isDebugEnabled()) {
+                logger.debugf(e, "Authentication failed for DN [%s]", dn);
+            }
+
+            return false;
+        } finally {
+            if (authCtx != null) {
+                try {
+                    authCtx.close();
+                } catch (NamingException e) {
+
+                }
+            }
+        }
+    }
+
+    public void modifyAttributes(final String dn, final ModificationItem[] mods) {
+        try {
+            if (logger.isDebugEnabled()) {
+                logger.debugf("Modifying attributes for entry [%s]: [", dn);
+
+                for (ModificationItem item : mods) {
+                    Object values;
+
+                    if (item.getAttribute().size() > 0) {
+                        values = item.getAttribute().get();
+                    } else {
+                        values = "No values";
+                    }
+
+                    logger.debugf("  Op [%s]: %s = %s", item.getModificationOp(), item.getAttribute().getID(), values);
+                }
+
+                logger.debugf("]");
+            }
+
+            execute(new LdapOperation<Void>() {
+                @Override
+                public Void execute(LdapContext context) throws NamingException {
+                    context.modifyAttributes(dn, mods);
+                    return null;
+                }
+            });
+        } catch (NamingException e) {
+            throw new ModelException("Could not modify attribute for DN [" + dn + "]", e);
+        }
+    }
+
+    public void createSubContext(final String name, final Attributes attributes) {
+        try {
+            if (logger.isDebugEnabled()) {
+                logger.debugf("Creating entry [%s] with attributes: [", name);
+
+                NamingEnumeration<? extends Attribute> all = attributes.getAll();
+
+                while (all.hasMore()) {
+                    Attribute attribute = all.next();
+
+                    logger.debugf("  %s = %s", attribute.getID(), attribute.get());
+                }
+
+                logger.debugf("]");
+            }
+
+            execute(new LdapOperation<Void>() {
+                @Override
+                public Void execute(LdapContext context) throws NamingException {
+                    DirContext subcontext = context.createSubcontext(name, attributes);
+
+                    subcontext.close();
+
+                    return null;
+                }
+            });
+        } catch (NamingException e) {
+            throw new ModelException("Error creating subcontext [" + name + "]", e);
+        }
+    }
+
+    private String getUniqueIdentifierAttributeName() {
+        return this.config.getUniqueIdentifierAttributeName();
+    }
+
+    private NamingEnumeration<SearchResult> createEmptyEnumeration() {
+        return new NamingEnumeration<SearchResult>() {
+            @Override
+            public SearchResult next() throws NamingException {
+                return null;  //To change body of implemented methods use File | Settings | File Templates.
+            }
+
+            @Override
+            public boolean hasMore() throws NamingException {
+                return false;  //To change body of implemented methods use File | Settings | File Templates.
+            }
+
+            @Override
+            public void close() throws NamingException {
+                //To change body of implemented methods use File | Settings | File Templates.
+            }
+
+            @Override
+            public boolean hasMoreElements() {
+                return false;  //To change body of implemented methods use File | Settings | File Templates.
+            }
+
+            @Override
+            public SearchResult nextElement() {
+                return null;  //To change body of implemented methods use File | Settings | File Templates.
+            }
+        };
+    }
+
+    public Attributes getAttributes(final String entryUUID, final String baseDN, LDAPMappingConfiguration mappingConfiguration) {
+        SearchResult search = lookupById(baseDN, entryUUID, mappingConfiguration);
+
+        if (search == null) {
+            throw new ModelException("Couldn't find item with entryUUID [" + entryUUID + "] and baseDN [" + baseDN + "]");
+        }
+
+        return search.getAttributes();
+    }
+
+    public String decodeEntryUUID(final Object entryUUID) {
+        String id;
+
+        if (this.config.isActiveDirectory()) {
+            id = LDAPUtil.decodeObjectGUID((byte[]) entryUUID);
+        } else {
+            id = entryUUID.toString();
+        }
+
+        return id;
+    }
+
+    private LdapContext createLdapContext() throws NamingException {
+        return new InitialLdapContext(new Hashtable<Object, Object>(this.connectionProperties), null);
+    }
+
+    private Map<String, Object> createConnectionProperties() {
+        HashMap<String, Object> env = new HashMap<String, Object>();
+
+        env.put(Context.INITIAL_CONTEXT_FACTORY, this.config.getFactoryName());
+        env.put(Context.SECURITY_AUTHENTICATION, this.config.getAuthType());
+
+        String protocol = this.config.getProtocol();
+
+        if (protocol != null) {
+            env.put(Context.SECURITY_PROTOCOL, protocol);
+        }
+
+        String bindDN = this.config.getBindDN();
+
+        char[] bindCredential = null;
+
+        if (this.config.getBindCredential() != null) {
+            bindCredential = this.config.getBindCredential().toCharArray();
+        }
+
+        if (bindDN != null) {
+            env.put(Context.SECURITY_PRINCIPAL, bindDN);
+            env.put(Context.SECURITY_CREDENTIALS, bindCredential);
+        }
+
+        String url = this.config.getLdapURL();
+
+        if (url == null) {
+            throw new RuntimeException("url");
+        }
+
+        env.put(Context.PROVIDER_URL, url);
+
+        // Just dump the additional properties
+        Properties additionalProperties = this.config.getConnectionProperties();
+
+        if (additionalProperties != null) {
+            for (Object key : additionalProperties.keySet()) {
+                env.put(key.toString(), additionalProperties.getProperty(key.toString()));
+            }
+        }
+
+        if (config.isActiveDirectory()) {
+            env.put("java.naming.ldap.attributes.binary", LDAPConstants.OBJECT_GUID);
+        }
+
+        if (logger.isDebugEnabled()) {
+            logger.debugf("Creating LdapContext using properties: [%s]", env);
+        }
+
+        return env;
+    }
+
+    private <R> R execute(LdapOperation<R> operation) throws NamingException {
+        LdapContext context = null;
+
+        try {
+            context = createLdapContext();
+            return operation.execute(context);
+        } catch (NamingException ne) {
+            logger.error("Could not create Ldap context or operation execution error.", ne);
+            throw ne;
+        } finally {
+            if (context != null) {
+                try {
+                    context.close();
+                } catch (NamingException ne) {
+                    logger.error("Could not close Ldap context.", ne);
+                }
+            }
+        }
+    }
+
+    private interface LdapOperation<R> {
+        R execute(LdapContext context) throws NamingException;
+    }
+
+    private List<String> getReturningAttributes(final LDAPMappingConfiguration mappingConfiguration) {
+        List<String> returningAttributes = new ArrayList<String>();
+
+        if (mappingConfiguration != null) {
+            returningAttributes.addAll(mappingConfiguration.getMappedProperties().values());
+
+            returningAttributes.add(mappingConfiguration.getParentMembershipAttributeName());
+
+//            for (LDAPMappingConfiguration relationshipConfig : this.config.getRelationshipConfigs()) {
+//                if (relationshipConfig.getRelatedAttributedType().equals(mappingConfiguration.getMappedClass())) {
+//                    returningAttributes.addAll(relationshipConfig.getMappedProperties().values());
+//                }
+//            }
+        } else {
+            returningAttributes.add("*");
+        }
+
+        returningAttributes.add(getUniqueIdentifierAttributeName());
+        returningAttributes.add(LDAPConstants.CREATE_TIMESTAMP);
+        returningAttributes.add(LDAPConstants.OBJECT_CLASS);
+
+        return returningAttributes;
+    }
+}
\ No newline at end of file
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPUtil.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPUtil.java
new file mode 100644
index 0000000..f08ff85
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPUtil.java
@@ -0,0 +1,158 @@
+package org.keycloak.federation.ldap.idm.store.ldap;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.TimeZone;
+
+import org.keycloak.models.ModelException;
+
+/**
+ * <p>Utility class for working with LDAP.</p>
+ *
+ * @author Pedro Igor
+ */
+public class LDAPUtil {
+
+    /**
+     * <p>Formats the given date.</p>
+     *
+     * @param date The Date to format.
+     *
+     * @return A String representing the formatted date.
+     */
+    public static final String formatDate(Date date) {
+        if (date == null) {
+            throw new IllegalArgumentException("You must provide a date.");
+        }
+
+        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss'.0Z'");
+
+        dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+
+        return dateFormat.format(date);
+    }
+
+    /**
+     * <p>
+     * Parses dates/time stamps stored in LDAP. Some possible values:
+     * </p>
+     * <ul>
+     *     <li>20020228150820</li>
+     *     <li>20030228150820Z</li>
+     *     <li>20050228150820.12</li>
+     *     <li>20060711011740.0Z</li>
+     * </ul>
+     *
+     * @param date The date string to parse from.
+     *
+     * @return the Date.
+     */
+    public static final Date parseDate(String date) {
+        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
+
+        try {
+            if (date.endsWith("Z")) {
+                dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+            } else {
+                dateFormat.setTimeZone(TimeZone.getDefault());
+            }
+
+            return dateFormat.parse(date);
+        } catch (Exception e) {
+            throw new ModelException("Error converting ldap date.", e);
+        }
+    }
+
+
+
+    /**
+     * <p>Creates a byte-based {@link String} representation of a raw byte array representing the value of the
+     * <code>objectGUID</code> attribute retrieved from Active Directory.</p>
+     *
+     * <p>The returned string is useful to perform queries on AD based on the <code>objectGUID</code> value. Eg.:</p>
+     *
+     * <p>
+     * String filter = "(&(objectClass=*)(objectGUID" + EQUAL + convertObjectGUIToByteString(objectGUID) + "))";
+     * </p>
+     *
+     * @param objectGUID A raw byte array representing the value of the <code>objectGUID</code> attribute retrieved from
+     * Active Directory.
+     *
+     * @return A byte-based String representation in the form of \[0]\[1]\[2]\[3]\[4]\[5]\[6]\[7]\[8]\[9]\[10]\[11]\[12]\[13]\[14]\[15]
+     */
+    public static String convertObjectGUIToByteString(byte[] objectGUID) {
+        StringBuilder result = new StringBuilder();
+
+        for (int i = 0; i < objectGUID.length; i++) {
+            String transformed = prefixZeros((int) objectGUID[i] & 0xFF);
+            result.append("\\");
+            result.append(transformed);
+        }
+
+        return result.toString();
+    }
+
+    /**
+     * <p>Decode a raw byte array representing the value of the <code>objectGUID</code> attribute retrieved from Active
+     * Directory.</p>
+     *
+     * <p>The returned string is useful to directly bind an entry. Eg.:</p>
+     *
+     * <p>
+     * String bindingString = decodeObjectGUID(objectGUID);
+     * <br/>
+     * Attributes attributes = ctx.getAttributes(bindingString);
+     * </p>
+     *
+     * @param objectGUID A raw byte array representing the value of the <code>objectGUID</code> attribute retrieved from
+     * Active Directory.
+     *
+     * @return A string representing the decoded value in the form of [3][2][1][0]-[5][4]-[7][6]-[8][9]-[10][11][12][13][14][15].
+     */
+    public static String decodeObjectGUID(byte[] objectGUID) {
+        StringBuilder displayStr = new StringBuilder();
+
+        displayStr.append(convertToDashedString(objectGUID));
+
+        return displayStr.toString();
+    }
+
+    private static String convertToDashedString(byte[] objectGUID) {
+        StringBuilder displayStr = new StringBuilder();
+
+        displayStr.append(prefixZeros((int) objectGUID[3] & 0xFF));
+        displayStr.append(prefixZeros((int) objectGUID[2] & 0xFF));
+        displayStr.append(prefixZeros((int) objectGUID[1] & 0xFF));
+        displayStr.append(prefixZeros((int) objectGUID[0] & 0xFF));
+        displayStr.append("-");
+        displayStr.append(prefixZeros((int) objectGUID[5] & 0xFF));
+        displayStr.append(prefixZeros((int) objectGUID[4] & 0xFF));
+        displayStr.append("-");
+        displayStr.append(prefixZeros((int) objectGUID[7] & 0xFF));
+        displayStr.append(prefixZeros((int) objectGUID[6] & 0xFF));
+        displayStr.append("-");
+        displayStr.append(prefixZeros((int) objectGUID[8] & 0xFF));
+        displayStr.append(prefixZeros((int) objectGUID[9] & 0xFF));
+        displayStr.append("-");
+        displayStr.append(prefixZeros((int) objectGUID[10] & 0xFF));
+        displayStr.append(prefixZeros((int) objectGUID[11] & 0xFF));
+        displayStr.append(prefixZeros((int) objectGUID[12] & 0xFF));
+        displayStr.append(prefixZeros((int) objectGUID[13] & 0xFF));
+        displayStr.append(prefixZeros((int) objectGUID[14] & 0xFF));
+        displayStr.append(prefixZeros((int) objectGUID[15] & 0xFF));
+
+        return displayStr.toString();
+    }
+
+    private static String prefixZeros(int value) {
+        if (value <= 0xF) {
+            StringBuilder sb = new StringBuilder("0");
+            sb.append(Integer.toHexString(value));
+            return sb.toString();
+        } else {
+            return Integer.toHexString(value);
+        }
+    }
+
+
+}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProvider.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProvider.java
index f48880c..370e0f0 100755
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProvider.java
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProvider.java
@@ -3,6 +3,10 @@ package org.keycloak.federation.ldap;
 import org.jboss.logging.Logger;
 import org.keycloak.federation.kerberos.impl.KerberosUsernamePasswordAuthenticator;
 import org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator;
+import org.keycloak.federation.ldap.idm.model.LDAPUser;
+import org.keycloak.federation.ldap.idm.query.IdentityQuery;
+import org.keycloak.federation.ldap.idm.query.IdentityQueryBuilder;
+import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore;
 import org.keycloak.federation.ldap.kerberos.LDAPProviderKerberosConfig;
 import org.keycloak.models.CredentialValidationOutput;
 import org.keycloak.models.KeycloakSession;
@@ -16,12 +20,6 @@ import org.keycloak.models.UserFederationProvider;
 import org.keycloak.models.UserFederationProviderModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.constants.KerberosConstants;
-import org.picketlink.idm.IdentityManagementException;
-import org.picketlink.idm.IdentityManager;
-import org.picketlink.idm.PartitionManager;
-import org.picketlink.idm.model.basic.BasicModel;
-import org.picketlink.idm.model.basic.User;
-import org.picketlink.idm.query.IdentityQuery;
 
 import java.util.Arrays;
 import java.util.HashMap;
@@ -38,23 +36,21 @@ import java.util.Set;
  */
 public class LDAPFederationProvider implements UserFederationProvider {
     private static final Logger logger = Logger.getLogger(LDAPFederationProvider.class);
-    public static final String LDAP_ID = "LDAP_ID";
-    public static final String SYNC_REGISTRATIONS = "syncRegistrations";
 
     protected LDAPFederationProviderFactory factory;
     protected KeycloakSession session;
     protected UserFederationProviderModel model;
-    protected PartitionManager partitionManager;
+    protected LDAPIdentityStore ldapIdentityStore;
     protected EditMode editMode;
     protected LDAPProviderKerberosConfig kerberosConfig;
 
     protected final Set<String> supportedCredentialTypes = new HashSet<String>();
 
-    public LDAPFederationProvider(LDAPFederationProviderFactory factory, KeycloakSession session, UserFederationProviderModel model, PartitionManager partitionManager) {
+    public LDAPFederationProvider(LDAPFederationProviderFactory factory, KeycloakSession session, UserFederationProviderModel model, LDAPIdentityStore ldapIdentityStore) {
         this.factory = factory;
         this.session = session;
         this.model = model;
-        this.partitionManager = partitionManager;
+        this.ldapIdentityStore = ldapIdentityStore;
         this.kerberosConfig = new LDAPProviderKerberosConfig(model);
         String editModeString = model.getConfig().get(LDAPConstants.EDIT_MODE);
         if (editModeString == null) {
@@ -69,16 +65,6 @@ public class LDAPFederationProvider implements UserFederationProvider {
         }
     }
 
-    private ModelException convertIDMException(IdentityManagementException ie) {
-        Throwable realCause = ie;
-        while (realCause.getCause() != null) {
-            realCause = realCause.getCause();
-        }
-
-        // Use the message from the realCause
-        return new ModelException(realCause.getMessage(), ie);
-    }
-
     public KeycloakSession getSession() {
         return session;
     }
@@ -87,8 +73,8 @@ public class LDAPFederationProvider implements UserFederationProvider {
         return model;
     }
 
-    public PartitionManager getPartitionManager() {
-        return partitionManager;
+    public LDAPIdentityStore getLdapIdentityStore() {
+        return this.ldapIdentityStore;
     }
 
     @Override
@@ -125,22 +111,18 @@ public class LDAPFederationProvider implements UserFederationProvider {
 
     @Override
     public boolean synchronizeRegistrations() {
-        return "true".equalsIgnoreCase(model.getConfig().get(SYNC_REGISTRATIONS)) && editMode == EditMode.WRITABLE;
+        return "true".equalsIgnoreCase(model.getConfig().get(LDAPConstants.SYNC_REGISTRATIONS)) && editMode == EditMode.WRITABLE;
     }
 
     @Override
     public UserModel register(RealmModel realm, UserModel user) {
-        if (editMode == EditMode.READ_ONLY || editMode == EditMode.UNSYNCED) throw new IllegalStateException("Registration is not supported by this ldap server");;
+        if (editMode == EditMode.READ_ONLY || editMode == EditMode.UNSYNCED) throw new IllegalStateException("Registration is not supported by this ldap server");
         if (!synchronizeRegistrations()) throw new IllegalStateException("Registration is not supported by this ldap server");
 
-        try {
-            User picketlinkUser = LDAPUtils.addUser(this.partitionManager, user.getUsername(), user.getFirstName(), user.getLastName(), user.getEmail());
-            user.setAttribute(LDAP_ID, picketlinkUser.getId());
-            return proxy(user);
-        } catch (IdentityManagementException ie) {
-            throw convertIDMException(ie);
-        }
-
+        LDAPUser ldapUser = LDAPUtils.addUser(this.ldapIdentityStore, user.getUsername(), user.getFirstName(), user.getLastName(), user.getEmail());
+        user.setAttribute(LDAPConstants.LDAP_ID, ldapUser.getId());
+        user.setAttribute(LDAPConstants.LDAP_ENTRY_DN, ldapUser.getEntryDN());
+        return proxy(user);
     }
 
     @Override
@@ -150,58 +132,53 @@ public class LDAPFederationProvider implements UserFederationProvider {
             return false;
         }
 
-        try {
-            return LDAPUtils.removeUser(partitionManager, user.getUsername());
-        } catch (IdentityManagementException ie) {
-            throw convertIDMException(ie);
-        }
+        return LDAPUtils.removeUser(this.ldapIdentityStore, user.getUsername());
     }
 
     @Override
     public List<UserModel> searchByAttributes(Map<String, String> attributes, RealmModel realm, int maxResults) {
         List<UserModel> searchResults =new LinkedList<UserModel>();
-        try {
-            Map<String, User> plUsers = searchPicketlink(attributes, maxResults);
-            for (User user : plUsers.values()) {
-                if (session.userStorage().getUserByUsername(user.getLoginName(), realm) == null) {
-                    UserModel imported = importUserFromPicketlink(realm, user);
-                    searchResults.add(imported);
-                }
+
+        Map<String, LDAPUser> ldapUsers = searchLDAP(attributes, maxResults);
+        for (LDAPUser ldapUser : ldapUsers.values()) {
+            if (session.userStorage().getUserByUsername(ldapUser.getLoginName(), realm) == null) {
+                UserModel imported = importUserFromLDAP(realm, ldapUser);
+                searchResults.add(imported);
             }
-        } catch (IdentityManagementException ie) {
-            throw convertIDMException(ie);
         }
+
         return searchResults;
     }
 
-    protected Map<String, User> searchPicketlink(Map<String, String> attributes, int maxResults) {
-        IdentityManager identityManager = getIdentityManager();
-        Map<String, User> results = new HashMap<String, User>();
+    protected Map<String, LDAPUser> searchLDAP(Map<String, String> attributes, int maxResults) {
+
+        Map<String, LDAPUser> results = new HashMap<String, LDAPUser>();
         if (attributes.containsKey(USERNAME)) {
-            User user = BasicModel.getUser(identityManager, attributes.get(USERNAME));
+            LDAPUser user = LDAPUtils.getUser(this.ldapIdentityStore, attributes.get(USERNAME));
             if (user != null) {
                 results.put(user.getLoginName(), user);
             }
         }
 
         if (attributes.containsKey(EMAIL)) {
-            User user = queryByEmail(identityManager, attributes.get(EMAIL));
+            LDAPUser user = queryByEmail(attributes.get(EMAIL));
             if (user != null) {
                 results.put(user.getLoginName(), user);
             }
         }
 
         if (attributes.containsKey(FIRST_NAME) || attributes.containsKey(LAST_NAME)) {
-            IdentityQuery<User> query = identityManager.createIdentityQuery(User.class);
+            IdentityQueryBuilder queryBuilder = this.ldapIdentityStore.createQueryBuilder();
+            IdentityQuery<LDAPUser> query = queryBuilder.createIdentityQuery(LDAPUser.class);
             if (attributes.containsKey(FIRST_NAME)) {
-                query.setParameter(User.FIRST_NAME, attributes.get(FIRST_NAME));
+                query.where(queryBuilder.equal(LDAPUser.FIRST_NAME, attributes.get(FIRST_NAME)));
             }
             if (attributes.containsKey(LAST_NAME)) {
-                query.setParameter(User.LAST_NAME, attributes.get(LAST_NAME));
+                query.where(queryBuilder.equal(LDAPUser.LAST_NAME, attributes.get(LAST_NAME)));
             }
             query.setLimit(maxResults);
-            List<User> agents = query.getResultList();
-            for (User user : agents) {
+            List<LDAPUser> users = query.getResultList();
+            for (LDAPUser user : users) {
                 results.put(user.getLoginName(), user);
             }
         }
@@ -211,85 +188,69 @@ public class LDAPFederationProvider implements UserFederationProvider {
 
     @Override
     public boolean isValid(UserModel local) {
-        try {
-            User picketlinkUser = LDAPUtils.getUser(partitionManager, local.getUsername());
-            if (picketlinkUser == null) {
-                return false;
-            }
-            return picketlinkUser.getId().equals(local.getAttribute(LDAP_ID));
-        } catch (IdentityManagementException ie) {
-            throw convertIDMException(ie);
+        LDAPUser ldapUser = LDAPUtils.getUser(this.ldapIdentityStore, local.getUsername());
+        if (ldapUser == null) {
+            return false;
         }
+        return ldapUser.getId().equals(local.getAttribute(LDAPConstants.LDAP_ID));
     }
 
     @Override
     public UserModel getUserByUsername(RealmModel realm, String username) {
-        try {
-            User picketlinkUser = LDAPUtils.getUser(partitionManager, username);
-            if (picketlinkUser == null) {
-                return null;
-            }
-
-            // KEYCLOAK-808: Should we allow case-sensitivity to be configurable?
-            if (!username.equals(picketlinkUser.getLoginName())) {
-                logger.warnf("User found in LDAP but with different username. LDAP username: %s, Searched username: %s", username, picketlinkUser.getLoginName());
-                return null;
-            }
+        LDAPUser ldapUser = LDAPUtils.getUser(this.ldapIdentityStore, username);
+        if (ldapUser == null) {
+            return null;
+        }
 
-            return importUserFromPicketlink(realm, picketlinkUser);
-        } catch (IdentityManagementException ie) {
-            throw convertIDMException(ie);
+        // KEYCLOAK-808: Should we allow case-sensitivity to be configurable?
+        if (!username.equals(ldapUser.getLoginName())) {
+            logger.warnf("User found in LDAP but with different username. LDAP username: %s, Searched username: %s", username, ldapUser.getLoginName());
+            return null;
         }
-    }
 
-    public IdentityManager getIdentityManager() {
-        return partitionManager.createIdentityManager();
+        return importUserFromLDAP(realm, ldapUser);
     }
 
-    protected UserModel importUserFromPicketlink(RealmModel realm, User picketlinkUser) {
-        String email = (picketlinkUser.getEmail() != null && picketlinkUser.getEmail().trim().length() > 0) ? picketlinkUser.getEmail() : null;
+    protected UserModel importUserFromLDAP(RealmModel realm, LDAPUser ldapUser) {
+        String email = (ldapUser.getEmail() != null && ldapUser.getEmail().trim().length() > 0) ? ldapUser.getEmail() : null;
 
-        if (picketlinkUser.getLoginName() == null) {
-            throw new ModelException("User returned from LDAP has null username! Check configuration of your LDAP mappings. ID of user from LDAP: " + picketlinkUser.getId());
+        if (ldapUser.getLoginName() == null) {
+            throw new ModelException("User returned from LDAP has null username! Check configuration of your LDAP mappings. ID of user from LDAP: " + ldapUser.getId());
         }
 
-        UserModel imported = session.userStorage().addUser(realm, picketlinkUser.getLoginName());
+        UserModel imported = session.userStorage().addUser(realm, ldapUser.getLoginName());
         imported.setEnabled(true);
         imported.setEmail(email);
-        imported.setFirstName(picketlinkUser.getFirstName());
-        imported.setLastName(picketlinkUser.getLastName());
+        imported.setFirstName(ldapUser.getFirstName());
+        imported.setLastName(ldapUser.getLastName());
         imported.setFederationLink(model.getId());
-        imported.setAttribute(LDAP_ID, picketlinkUser.getId());
+        imported.setAttribute(LDAPConstants.LDAP_ID, ldapUser.getId());
+        imported.setAttribute(LDAPConstants.LDAP_ENTRY_DN, ldapUser.getEntryDN());
 
-        logger.debugf("Added new user from LDAP. Username: " + imported.getUsername() + ", Email: ", imported.getEmail() + ", LDAP_ID: " + picketlinkUser.getId());
+        logger.debugf("Imported new user from LDAP to Keycloak DB. Username: [%s], Email: [%s], LDAP_ID: [%s], LDAP Entry DN: [%s]", imported.getUsername(), imported.getEmail(),
+                ldapUser.getId(), ldapUser.getEntryDN());
         return proxy(imported);
     }
 
-    protected User queryByEmail(IdentityManager identityManager, String email) throws IdentityManagementException {
-        return LDAPUtils.getUserByEmail(identityManager, email);
+    protected LDAPUser queryByEmail(String email) {
+        return LDAPUtils.getUserByEmail(this.ldapIdentityStore, email);
     }
 
 
     @Override
     public UserModel getUserByEmail(RealmModel realm, String email) {
-        IdentityManager identityManager = getIdentityManager();
-
-        try {
-            User picketlinkUser = queryByEmail(identityManager, email);
-            if (picketlinkUser == null) {
-                return null;
-            }
-
-            // KEYCLOAK-808: Should we allow case-sensitivity to be configurable?
-            if (!email.equals(picketlinkUser.getEmail())) {
-                logger.warnf("User found in LDAP but with different email. LDAP email: %s, Searched email: %s", email, picketlinkUser.getEmail());
-                return null;
-            }
+        LDAPUser ldapUser = queryByEmail(email);
+        if (ldapUser == null) {
+            return null;
+        }
 
-            return importUserFromPicketlink(realm, picketlinkUser);
-        } catch (IdentityManagementException ie) {
-            throw convertIDMException(ie);
+        // KEYCLOAK-808: Should we allow case-sensitivity to be configurable?
+        if (!email.equals(ldapUser.getEmail())) {
+            logger.warnf("User found in LDAP but with different email. LDAP email: %s, Searched email: %s", email, ldapUser.getEmail());
+            return null;
         }
+
+        return importUserFromLDAP(realm, ldapUser);
     }
 
     @Override
@@ -302,18 +263,14 @@ public class LDAPFederationProvider implements UserFederationProvider {
         // complete I don't think we have to do anything here
     }
 
-    public boolean validPassword(String username, String password) {
+    public boolean validPassword(UserModel user, String password) {
         if (kerberosConfig.isAllowKerberosAuthentication() && kerberosConfig.isUseKerberosForPasswordAuthentication()) {
             // Use Kerberos JAAS (Krb5LoginModule)
             KerberosUsernamePasswordAuthenticator authenticator = factory.createKerberosUsernamePasswordAuthenticator(kerberosConfig);
-            return authenticator.validUser(username, password);
+            return authenticator.validUser(user.getUsername(), password);
         } else {
             // Use Naming LDAP API
-            try {
-                return LDAPUtils.validatePassword(partitionManager, username, password);
-            } catch (IdentityManagementException ie) {
-                throw convertIDMException(ie);
-            }
+            return LDAPUtils.validatePassword(this.ldapIdentityStore, user, password);
         }
     }
 
@@ -322,7 +279,7 @@ public class LDAPFederationProvider implements UserFederationProvider {
     public boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input) {
         for (UserCredentialModel cred : input) {
             if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
-                return validPassword(user.getUsername(), cred.getValue());
+                return validPassword(user, cred.getValue());
             } else {
                 return false; // invalid cred type
             }
@@ -353,7 +310,7 @@ public class LDAPFederationProvider implements UserFederationProvider {
                     UserModel user = findOrCreateAuthenticatedUser(realm, username);
 
                     if (user == null) {
-                        logger.warn("Kerberos/SPNEGO authentication succeeded with username [" + username + "], but couldn't find or create user with federation provider [" + model.getDisplayName() + "]");
+                        logger.warnf("Kerberos/SPNEGO authentication succeeded with username [%s], but couldn't find or create user with federation provider [%s]", username, model.getDisplayName());
                         return CredentialValidationOutput.failed();
                     } else {
                         String delegationCredential = spnegoAuthenticator.getSerializedDelegationCredential();
@@ -375,24 +332,23 @@ public class LDAPFederationProvider implements UserFederationProvider {
 
     @Override
     public void close() {
-        //To change body of implemented methods use File | Settings | File Templates.
     }
 
-    protected void importPicketlinkUsers(RealmModel realm, List<User> users, UserFederationProviderModel fedModel) {
-        for (User picketlinkUser : users) {
-            String username = picketlinkUser.getLoginName();
+    protected void importLDAPUsers(RealmModel realm, List<LDAPUser> ldapUsers, UserFederationProviderModel fedModel) {
+        for (LDAPUser ldapUser : ldapUsers) {
+            String username = ldapUser.getLoginName();
             UserModel currentUser = session.userStorage().getUserByUsername(username, realm);
 
             if (currentUser == null) {
                 // Add new user to Keycloak
-                importUserFromPicketlink(realm, picketlinkUser);
+                importUserFromLDAP(realm, ldapUser);
             } else {
-                if ((fedModel.getId().equals(currentUser.getFederationLink())) && (picketlinkUser.getId().equals(currentUser.getAttribute(LDAPFederationProvider.LDAP_ID)))) {
+                if ((fedModel.getId().equals(currentUser.getFederationLink())) && (ldapUser.getId().equals(currentUser.getAttribute(LDAPConstants.LDAP_ID)))) {
                     // Update keycloak user
-                    String email = (picketlinkUser.getEmail() != null && picketlinkUser.getEmail().trim().length() > 0) ? picketlinkUser.getEmail() : null;
+                    String email = (ldapUser.getEmail() != null && ldapUser.getEmail().trim().length() > 0) ? ldapUser.getEmail() : null;
                     currentUser.setEmail(email);
-                    currentUser.setFirstName(picketlinkUser.getFirstName());
-                    currentUser.setLastName(picketlinkUser.getLastName());
+                    currentUser.setFirstName(ldapUser.getFirstName());
+                    currentUser.setLastName(ldapUser.getLastName());
                     logger.debugf("Updated user from LDAP: %s", currentUser.getUsername());
                 } else {
                     logger.warnf("User '%s' is not updated during sync as he is not linked to federation provider '%s'", username, fedModel.getDisplayName());
@@ -404,29 +360,29 @@ public class LDAPFederationProvider implements UserFederationProvider {
     /**
      * Called after successful kerberos authentication
      *
-     * @param realm
+     * @param realm realm
      * @param username username without realm prefix
-     * @return
+     * @return finded or newly created user
      */
     protected UserModel findOrCreateAuthenticatedUser(RealmModel realm, String username) {
         UserModel user = session.userStorage().getUserByUsername(username, realm);
         if (user != null) {
-            logger.debug("Kerberos authenticated user " + username + " found in Keycloak storage");
+            logger.debugf("Kerberos authenticated user [%s] found in Keycloak storage", username);
             if (!model.getId().equals(user.getFederationLink())) {
-                logger.warn("User with username " + username + " already exists, but is not linked to provider [" + model.getDisplayName() + "]");
+                logger.warnf("User with username [%s] already exists, but is not linked to provider [%s]", username, model.getDisplayName());
                 return null;
             } else if (isValid(user)) {
                 return proxy(user);
             } else {
-                logger.warn("User with username " + username + " already exists and is linked to provider [" + model.getDisplayName() +
-                        "] but is not valid. Stale LDAP_ID on local user is: " + user.getAttribute(LDAP_ID));
+                logger.warnf("User with username [%s] aready exists and is linked to provider [%s] but is not valid. Stale LDAP_ID on local user is: %s",
+                        username,  model.getDisplayName(), user.getAttribute(LDAPConstants.LDAP_ID));
                 logger.warn("Will re-create user");
                 session.userStorage().removeUser(realm, user);
             }
         }
 
         // Creating user to local storage
-        logger.debug("Kerberos authenticated user " + username + " not in Keycloak storage. Creating him");
+        logger.debugf("Kerberos authenticated user [%s] not in Keycloak storage. Creating him", username);
         return getUserByUsername(realm, username);
     }
 }
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProviderFactory.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProviderFactory.java
index c197052..a498a93 100755
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProviderFactory.java
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProviderFactory.java
@@ -3,10 +3,15 @@ package org.keycloak.federation.ldap;
 import org.jboss.logging.Logger;
 import org.keycloak.Config;
 import org.keycloak.federation.kerberos.CommonKerberosConfig;
-import org.keycloak.federation.kerberos.KerberosConfig;
 import org.keycloak.federation.kerberos.impl.KerberosServerSubjectAuthenticator;
 import org.keycloak.federation.kerberos.impl.KerberosUsernamePasswordAuthenticator;
 import org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator;
+import org.keycloak.federation.ldap.idm.model.IdentityType;
+import org.keycloak.federation.ldap.idm.model.LDAPUser;
+import org.keycloak.federation.ldap.idm.query.Condition;
+import org.keycloak.federation.ldap.idm.query.IdentityQuery;
+import org.keycloak.federation.ldap.idm.query.IdentityQueryBuilder;
+import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
 import org.keycloak.models.KeycloakSessionTask;
@@ -16,16 +21,6 @@ import org.keycloak.models.UserFederationProvider;
 import org.keycloak.models.UserFederationProviderFactory;
 import org.keycloak.models.UserFederationProviderModel;
 import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.picketlink.PartitionManagerProvider;
-import org.picketlink.idm.IdentityManager;
-import org.picketlink.idm.PartitionManager;
-import org.picketlink.idm.model.IdentityType;
-import org.picketlink.idm.model.basic.User;
-import org.picketlink.idm.query.AttributeParameter;
-import org.picketlink.idm.query.Condition;
-import org.picketlink.idm.query.IdentityQuery;
-import org.picketlink.idm.query.IdentityQueryBuilder;
-import org.picketlink.idm.query.QueryParameter;
 
 import java.util.Collections;
 import java.util.Date;
@@ -41,6 +36,8 @@ public class LDAPFederationProviderFactory implements UserFederationProviderFact
     private static final Logger logger = Logger.getLogger(LDAPFederationProviderFactory.class);
     public static final String PROVIDER_NAME = "ldap";
 
+    private LDAPIdentityStoreRegistry ldapStoreRegistry;
+
     @Override
     public UserFederationProvider create(KeycloakSession session) {
         throw new IllegalAccessError("Illegal to call this method");
@@ -48,13 +45,13 @@ public class LDAPFederationProviderFactory implements UserFederationProviderFact
 
     @Override
     public LDAPFederationProvider getInstance(KeycloakSession session, UserFederationProviderModel model) {
-        PartitionManagerProvider idmProvider = session.getProvider(PartitionManagerProvider.class);
-        PartitionManager partition = idmProvider.getPartitionManager(model);
-        return new LDAPFederationProvider(this, session, model, partition);
+        LDAPIdentityStore ldapIdentityStore = this.ldapStoreRegistry.getLdapStore(model);
+        return new LDAPFederationProvider(this, session, model, ldapIdentityStore);
     }
 
     @Override
     public void init(Config.Scope config) {
+        this.ldapStoreRegistry = new LDAPIdentityStoreRegistry();
     }
 
     @Override
@@ -64,7 +61,7 @@ public class LDAPFederationProviderFactory implements UserFederationProviderFact
 
     @Override
     public void close() {
-
+        this.ldapStoreRegistry = null;
     }
 
     @Override
@@ -81,9 +78,8 @@ public class LDAPFederationProviderFactory implements UserFederationProviderFact
     public void syncAllUsers(KeycloakSessionFactory sessionFactory, String realmId, UserFederationProviderModel model) {
         logger.infof("Sync all users from LDAP to local store: realm: %s, federation provider: %s, current time: " + new Date(), realmId, model.getDisplayName());
 
-        PartitionManagerProvider idmProvider = sessionFactory.create().getProvider(PartitionManagerProvider.class);
-        PartitionManager partitionMgr = idmProvider.getPartitionManager(model);
-        IdentityQuery<User> userQuery = partitionMgr.createIdentityManager().createIdentityQuery(User.class);
+        LDAPIdentityStore ldapIdentityStore = this.ldapStoreRegistry.getLdapStore(model);
+        IdentityQuery<LDAPUser> userQuery = ldapIdentityStore.createQueryBuilder().createIdentityQuery(LDAPUser.class);
         syncImpl(sessionFactory, userQuery, realmId, model);
 
         // TODO: Remove all existing keycloak users, which have federation links, but are not in LDAP. Perhaps don't check users, which were just added or updated during this sync?
@@ -91,26 +87,23 @@ public class LDAPFederationProviderFactory implements UserFederationProviderFact
 
     @Override
     public void syncChangedUsers(KeycloakSessionFactory sessionFactory, String realmId, UserFederationProviderModel model, Date lastSync) {
-        logger.infof("Sync changed users from LDAP to local store: realm: %s, federation provider: %s, current time: " + new Date() + ", last sync time: " + lastSync, realmId, model.getDisplayName());
+        logger.infof("Sync changed users from LDAP to local store: realm: %s, federation provider: %s, current time: %s, last sync time: " + lastSync, realmId, model.getDisplayName(), new Date().toString());
 
-        PartitionManagerProvider idmProvider = sessionFactory.create().getProvider(PartitionManagerProvider.class);
-        PartitionManager partitionMgr = idmProvider.getPartitionManager(model);
+        LDAPIdentityStore ldapIdentityStore = this.ldapStoreRegistry.getLdapStore(model);
 
         // Sync newly created users
-        IdentityManager identityManager = partitionMgr.createIdentityManager();
-        IdentityQueryBuilder queryBuilder = identityManager.getQueryBuilder();
+        IdentityQueryBuilder queryBuilder = ldapIdentityStore.createQueryBuilder();
         Condition condition = queryBuilder.greaterThanOrEqualTo(IdentityType.CREATED_DATE, lastSync);
-        IdentityQuery<User> userQuery = queryBuilder.createIdentityQuery(User.class).where(condition);
+        IdentityQuery<LDAPUser> userQuery = queryBuilder.createIdentityQuery(LDAPUser.class).where(condition);
         syncImpl(sessionFactory, userQuery, realmId, model);
 
         // Sync updated users
-        queryBuilder = identityManager.getQueryBuilder();
         condition = queryBuilder.greaterThanOrEqualTo(LDAPUtils.MODIFY_DATE, lastSync);
-        userQuery = queryBuilder.createIdentityQuery(User.class).where(condition);
+        userQuery = queryBuilder.createIdentityQuery(LDAPUser.class).where(condition);
         syncImpl(sessionFactory, userQuery, realmId, model);
     }
 
-    protected void syncImpl(KeycloakSessionFactory sessionFactory, IdentityQuery<User> userQuery, final String realmId, final UserFederationProviderModel fedModel) {
+    protected void syncImpl(KeycloakSessionFactory sessionFactory, IdentityQuery<LDAPUser> userQuery, final String realmId, final UserFederationProviderModel fedModel) {
         boolean pagination = Boolean.parseBoolean(fedModel.getConfig().get(LDAPConstants.PAGINATION));
 
         if (pagination) {
@@ -119,36 +112,36 @@ public class LDAPFederationProviderFactory implements UserFederationProviderFact
             boolean nextPage = true;
             while (nextPage) {
                 userQuery.setLimit(pageSize);
-                final List<User> users = userQuery.getResultList();
+                final List<LDAPUser> users = userQuery.getResultList();
                 nextPage = userQuery.getPaginationContext() != null;
 
                 KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
 
                     @Override
                     public void run(KeycloakSession session) {
-                        importPicketlinkUsers(session, realmId, fedModel, users);
+                        importLdapUsers(session, realmId, fedModel, users);
                     }
 
                 });
             }
         } else {
             // LDAP pagination not available. Do everything in single transaction
-            final List<User> users = userQuery.getResultList();
+            final List<LDAPUser> users = userQuery.getResultList();
             KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
 
                 @Override
                 public void run(KeycloakSession session) {
-                    importPicketlinkUsers(session, realmId, fedModel, users);
+                    importLdapUsers(session, realmId, fedModel, users);
                 }
 
             });
         }
     }
 
-    protected void importPicketlinkUsers(KeycloakSession session, String realmId, UserFederationProviderModel fedModel, List<User> users) {
+    protected void importLdapUsers(KeycloakSession session, String realmId, UserFederationProviderModel fedModel, List<LDAPUser> ldapUsers) {
         RealmModel realm = session.realms().getRealm(realmId);
         LDAPFederationProvider ldapFedProvider = getInstance(session, fedModel);
-        ldapFedProvider.importPicketlinkUsers(realm, users, fedModel);
+        ldapFedProvider.importLDAPUsers(realm, ldapUsers, fedModel);
     }
 
     protected SPNEGOAuthenticator createSPNEGOAuthenticator(String spnegoToken, CommonKerberosConfig kerberosConfig) {
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPIdentityStoreRegistry.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPIdentityStoreRegistry.java
new file mode 100644
index 0000000..22aa55a
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPIdentityStoreRegistry.java
@@ -0,0 +1,165 @@
+package org.keycloak.federation.ldap;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.jboss.logging.Logger;
+import org.keycloak.federation.ldap.idm.model.LDAPUser;
+import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore;
+import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStoreConfiguration;
+import org.keycloak.federation.ldap.idm.store.ldap.LDAPMappingConfiguration;
+import org.keycloak.models.LDAPConstants;
+import org.keycloak.models.UserFederationProviderModel;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class LDAPIdentityStoreRegistry {
+
+    private static final Logger logger = Logger.getLogger(LDAPIdentityStoreRegistry.class);
+
+    private Map<String, LDAPIdentityStoreContext> ldapStores = new ConcurrentHashMap<String, LDAPIdentityStoreContext>();
+
+    public LDAPIdentityStore getLdapStore(UserFederationProviderModel model) {
+        LDAPIdentityStoreContext context = ldapStores.get(model.getId());
+
+        // Ldap config might have changed for the realm. In this case, we must re-initialize
+        Map<String, String> config = model.getConfig();
+        if (context == null || !config.equals(context.config)) {
+            logLDAPConfig(model.getId(), config);
+
+            LDAPIdentityStore store = createLdapIdentityStore(config);
+            context = new LDAPIdentityStoreContext(config, store);
+            ldapStores.put(model.getId(), context);
+        }
+        return context.store;
+    }
+
+    // Don't log LDAP password
+    private void logLDAPConfig(String fedProviderId, Map<String, String> ldapConfig) {
+        Map<String, String> copy = new HashMap<String, String>(ldapConfig);
+        copy.remove(LDAPConstants.BIND_CREDENTIAL);
+        logger.infof("Creating new LDAP based partition manager for the Federation provider: " + fedProviderId + ", LDAP Configuration: " + copy);
+    }
+
+    /**
+     * @param ldapConfig from realm
+     * @return PartitionManager instance based on LDAP store
+     */
+    public static LDAPIdentityStore createLdapIdentityStore(Map<String,String> ldapConfig) {
+        Properties connectionProps = new Properties();
+        if (ldapConfig.containsKey(LDAPConstants.CONNECTION_POOLING)) {
+            connectionProps.put("com.sun.jndi.ldap.connect.pool", ldapConfig.get(LDAPConstants.CONNECTION_POOLING));
+        }
+
+        checkSystemProperty("com.sun.jndi.ldap.connect.pool.authentication", "none simple");
+        checkSystemProperty("com.sun.jndi.ldap.connect.pool.initsize", "1");
+        checkSystemProperty("com.sun.jndi.ldap.connect.pool.maxsize", "1000");
+        checkSystemProperty("com.sun.jndi.ldap.connect.pool.prefsize", "5");
+        checkSystemProperty("com.sun.jndi.ldap.connect.pool.timeout", "300000");
+        checkSystemProperty("com.sun.jndi.ldap.connect.pool.protocol", "plain");
+        checkSystemProperty("com.sun.jndi.ldap.connect.pool.debug", "off");
+
+        String vendor = ldapConfig.get(LDAPConstants.VENDOR);
+
+        boolean activeDirectory = vendor != null && vendor.equals(LDAPConstants.VENDOR_ACTIVE_DIRECTORY);
+
+        String ldapLoginNameMapping = ldapConfig.get(LDAPConstants.USERNAME_LDAP_ATTRIBUTE);
+        if (ldapLoginNameMapping == null) {
+            ldapLoginNameMapping = activeDirectory ? LDAPConstants.CN : LDAPConstants.UID;
+        }
+
+        String ldapFirstNameMapping = activeDirectory ?  "givenName" : LDAPConstants.CN;
+        String createTimestampMapping = activeDirectory ? "whenCreated" : LDAPConstants.CREATE_TIMESTAMP;
+        String modifyTimestampMapping = activeDirectory ? "whenChanged" : LDAPConstants.MODIFY_TIMESTAMP;
+        String[] userObjectClasses = getUserObjectClasses(ldapConfig);
+
+        boolean pagination = ldapConfig.containsKey(LDAPConstants.PAGINATION) ? Boolean.parseBoolean(ldapConfig.get(LDAPConstants.PAGINATION)) : false;
+        boolean userAccountControlsAfterPasswordUpdate = ldapConfig.containsKey(LDAPConstants.USER_ACCOUNT_CONTROLS_AFTER_PASSWORD_UPDATE) ?
+                Boolean.parseBoolean(ldapConfig.get(LDAPConstants.USER_ACCOUNT_CONTROLS_AFTER_PASSWORD_UPDATE)) : false;
+
+        // Differences of unique attribute among various vendors
+        String uniqueIdentifierAttributeName = LDAPConstants.ENTRY_UUID;
+        if (vendor != null) {
+            switch (vendor) {
+                case LDAPConstants.VENDOR_RHDS:
+                    uniqueIdentifierAttributeName = "nsuniqueid";
+                    break;
+                case LDAPConstants.VENDOR_TIVOLI:
+                    uniqueIdentifierAttributeName = "uniqueidentifier";
+                    break;
+                case LDAPConstants.VENDOR_ACTIVE_DIRECTORY:
+                    uniqueIdentifierAttributeName = LDAPConstants.OBJECT_GUID;
+            }
+        }
+
+        LDAPIdentityStoreConfiguration ldapStoreConfig = new LDAPIdentityStoreConfiguration()
+                .setConnectionProperties(connectionProps)
+                .setBaseDN(ldapConfig.get(LDAPConstants.BASE_DN))
+                .setBindDN(ldapConfig.get(LDAPConstants.BIND_DN))
+                .setBindCredential(ldapConfig.get(LDAPConstants.BIND_CREDENTIAL))
+                .setLdapURL(ldapConfig.get(LDAPConstants.CONNECTION_URL))
+                .setActiveDirectory(activeDirectory)
+                .setPagination(pagination)
+                .setUniqueIdentifierAttributeName(uniqueIdentifierAttributeName)
+                .setFactoryName("com.sun.jndi.ldap.LdapCtxFactory")
+                .setAuthType("simple")
+                .setUserAccountControlsAfterPasswordUpdate(userAccountControlsAfterPasswordUpdate);
+
+        LDAPMappingConfiguration ldapUserMappingConfig = ldapStoreConfig
+                .mappingConfig(LDAPUser.class)
+                .setBaseDN(ldapConfig.get(LDAPConstants.USER_DN_SUFFIX))
+                .setObjectClasses(new HashSet<String>(Arrays.asList(userObjectClasses)))
+                .setIdPropertyName("loginName")
+                .addAttributeMapping("loginName", ldapLoginNameMapping)
+                .addAttributeMapping("firstName", ldapFirstNameMapping)
+                .addAttributeMapping("lastName", LDAPConstants.SN)
+                .addAttributeMapping("email", LDAPConstants.EMAIL)
+                .addReadOnlyAttributeMapping("createdDate", createTimestampMapping)
+                .addReadOnlyAttributeMapping("modifyDate", modifyTimestampMapping);
+
+        if (activeDirectory && ldapLoginNameMapping.equals("sAMAccountName")) {
+            ldapUserMappingConfig.setBindingPropertyName("fullName");
+            ldapUserMappingConfig.addAttributeMapping("fullName", LDAPConstants.CN);
+            logger.infof("Using 'cn' attribute for DN of user and 'sAMAccountName' for username");
+        }
+
+        return new LDAPIdentityStore(ldapStoreConfig);
+    }
+
+    private static void checkSystemProperty(String name, String defaultValue) {
+        if (System.getProperty(name) == null) {
+            System.setProperty(name, defaultValue);
+        }
+    }
+
+    // Parse array of strings like [ "inetOrgPerson", "organizationalPerson" ] from the string like: "inetOrgPerson, organizationalPerson"
+    private static String[] getUserObjectClasses(Map<String,String> ldapConfig) {
+        String objClassesCfg = ldapConfig.get(LDAPConstants.USER_OBJECT_CLASSES);
+        String objClassesStr = (objClassesCfg != null && objClassesCfg.length() > 0) ? objClassesCfg.trim() : "inetOrgPerson, organizationalPerson";
+
+        String[] objectClasses = objClassesStr.split(",");
+
+        // Trim them
+        String[] userObjectClasses = new String[objectClasses.length];
+        for (int i=0 ; i<objectClasses.length ; i++) {
+            userObjectClasses[i] = objectClasses[i].trim();
+        }
+        return userObjectClasses;
+    }
+
+    private class LDAPIdentityStoreContext {
+
+        private LDAPIdentityStoreContext(Map<String,String> config, LDAPIdentityStore store) {
+            this.config = config;
+            this.store = store;
+        }
+
+        private Map<String,String> config;
+        private LDAPIdentityStore store;
+    }
+}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPUtils.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPUtils.java
index db0e9b8..9753592 100755
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPUtils.java
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPUtils.java
@@ -1,22 +1,21 @@
 package org.keycloak.federation.ldap;
 
+import org.keycloak.federation.ldap.idm.model.Attribute;
+import org.keycloak.federation.ldap.idm.model.LDAPUser;
+import org.keycloak.federation.ldap.idm.query.AttributeParameter;
+import org.keycloak.federation.ldap.idm.query.IdentityQuery;
+import org.keycloak.federation.ldap.idm.query.IdentityQueryBuilder;
+import org.keycloak.federation.ldap.idm.query.QueryParameter;
+import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore;
+import org.keycloak.models.LDAPConstants;
 import org.keycloak.models.ModelDuplicateException;
-import org.picketlink.idm.IdentityManagementException;
-import org.picketlink.idm.IdentityManager;
-import org.picketlink.idm.PartitionManager;
-import org.picketlink.idm.credential.Credentials;
-import org.picketlink.idm.credential.Password;
-import org.picketlink.idm.credential.UsernamePasswordCredentials;
-import org.picketlink.idm.model.Attribute;
-import org.picketlink.idm.model.basic.BasicModel;
-import org.picketlink.idm.model.basic.User;
-import org.picketlink.idm.query.AttributeParameter;
-import org.picketlink.idm.query.QueryParameter;
+import org.keycloak.models.UserModel;
 
 import java.util.List;
 
 /**
- * Allow to directly call some operations against Picketlink IDM PartitionManager (hence LDAP).
+ * Allow to directly call some operations against LDAPIdentityStore.
+ * TODO: Is this class still needed?
  *
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
  */
@@ -24,99 +23,102 @@ public class LDAPUtils {
 
     public static QueryParameter MODIFY_DATE = new AttributeParameter("modifyDate");
 
-    public static User addUser(PartitionManager partitionManager, String username, String firstName, String lastName, String email) {
-        IdentityManager identityManager = getIdentityManager(partitionManager);
-
-        if (BasicModel.getUser(identityManager, username) != null) {
+    public static LDAPUser addUser(LDAPIdentityStore ldapIdentityStore, String username, String firstName, String lastName, String email) {
+        if (getUser(ldapIdentityStore, username) != null) {
             throw new ModelDuplicateException("User with same username already exists");
         }
-        if (getUserByEmail(identityManager, email) != null) {
+        if (getUserByEmail(ldapIdentityStore, email) != null) {
             throw new ModelDuplicateException("User with same email already exists");
         }
 
-        User picketlinkUser = new User(username);
-        picketlinkUser.setFirstName(firstName);
-        picketlinkUser.setLastName(lastName);
-        picketlinkUser.setEmail(email);
-        picketlinkUser.setAttribute(new Attribute("fullName", getFullName(username, firstName, lastName)));
-        identityManager.add(picketlinkUser);
-        return picketlinkUser;
+        LDAPUser ldapUser = new LDAPUser(username);
+        ldapUser.setFirstName(firstName);
+        ldapUser.setLastName(lastName);
+        ldapUser.setEmail(email);
+        ldapUser.setAttribute(new Attribute<String>("fullName", getFullName(username, firstName, lastName)));
+        ldapIdentityStore.add(ldapUser);
+        return ldapUser;
     }
 
-    public static User updateUser(PartitionManager partitionManager, String username, String firstName, String lastName, String email) {
-        IdentityManager idmManager = getIdentityManager(partitionManager);
-        User picketlinkUser = BasicModel.getUser(idmManager, username);
-        picketlinkUser.setFirstName(firstName);
-        picketlinkUser.setLastName(lastName);
-        picketlinkUser.setEmail(email);
-        idmManager.update(picketlinkUser);
-        return picketlinkUser;
+    public static LDAPUser updateUser(LDAPIdentityStore ldapIdentityStore, String username, String firstName, String lastName, String email) {
+        LDAPUser ldapUser = getUser(ldapIdentityStore, username);
+        ldapUser.setFirstName(firstName);
+        ldapUser.setLastName(lastName);
+        ldapUser.setEmail(email);
+        ldapIdentityStore.update(ldapUser);
+        return ldapUser;
     }
 
-    public static void updatePassword(PartitionManager partitionManager, User picketlinkUser, String password) {
-        IdentityManager idmManager = getIdentityManager(partitionManager);
-        idmManager.updateCredential(picketlinkUser, new Password(password.toCharArray()));
+    public static void updatePassword(LDAPIdentityStore ldapIdentityStore, UserModel user, String password) {
+        LDAPUser ldapUser = convertUserForPasswordUpdate(user);
+
+        ldapIdentityStore.updatePassword(ldapUser, password);
     }
 
-    public static boolean validatePassword(PartitionManager partitionManager, String username, String password) {
-        IdentityManager idmManager = getIdentityManager(partitionManager);
+    public static void updatePassword(LDAPIdentityStore ldapIdentityStore, LDAPUser user, String password) {
+        ldapIdentityStore.updatePassword(user, password);
+    }
 
-        UsernamePasswordCredentials credential = new UsernamePasswordCredentials();
-        credential.setUsername(username);
-        credential.setPassword(new Password(password.toCharArray()));
-        idmManager.validateCredentials(credential);
-        if (credential.getStatus() == Credentials.Status.VALID) {
-            return true;
-        } else {
-            return false;
-        }
+    public static boolean validatePassword(LDAPIdentityStore ldapIdentityStore, UserModel user, String password) {
+        LDAPUser ldapUser = convertUserForPasswordUpdate(user);
+
+        return ldapIdentityStore.validatePassword(ldapUser, password);
     }
 
-    public static User getUser(PartitionManager partitionManager, String username) {
-        IdentityManager idmManager = getIdentityManager(partitionManager);
-        return BasicModel.getUser(idmManager, username);
+    public static boolean validatePassword(LDAPIdentityStore ldapIdentityStore, LDAPUser user, String password) {
+        return ldapIdentityStore.validatePassword(user, password);
     }
 
+    public static LDAPUser getUser(LDAPIdentityStore ldapIdentityStore, String username) {
+        return ldapIdentityStore.getUser(username);
+    }
+
+    // Put just username and entryDN as these are needed by LDAPIdentityStore for passwordUpdate
+    private static LDAPUser convertUserForPasswordUpdate(UserModel kcUser) {
+        LDAPUser ldapUser = new LDAPUser(kcUser.getUsername());
+        String ldapEntryDN = kcUser.getAttribute(LDAPConstants.LDAP_ENTRY_DN);
+        if (ldapEntryDN != null) {
+            ldapUser.setEntryDN(ldapEntryDN);
+        }
+        return ldapUser;
+    }
 
-    public static User getUserByEmail(IdentityManager idmManager, String email) throws IdentityManagementException {
-        List<User> agents = idmManager.createIdentityQuery(User.class)
-                .setParameter(User.EMAIL, email).getResultList();
 
-        if (agents.isEmpty()) {
+    public static LDAPUser getUserByEmail(LDAPIdentityStore ldapIdentityStore, String email) {
+        IdentityQueryBuilder queryBuilder = ldapIdentityStore.createQueryBuilder();
+        IdentityQuery<LDAPUser> query = queryBuilder.createIdentityQuery(LDAPUser.class)
+                .where(queryBuilder.equal(LDAPUser.EMAIL, email));
+        List<LDAPUser> users = query.getResultList();
+
+        if (users.isEmpty()) {
             return null;
-        } else if (agents.size() == 1) {
-            return agents.get(0);
+        } else if (users.size() == 1) {
+            return users.get(0);
         } else {
-            throw new IdentityManagementException("Error - multiple users found with same email");
+            throw new ModelDuplicateException("Error - multiple users found with same email " + email);
         }
     }
 
-    public static boolean removeUser(PartitionManager partitionManager, String username) {
-        IdentityManager idmManager = getIdentityManager(partitionManager);
-        User picketlinkUser = BasicModel.getUser(idmManager, username);
-        if (picketlinkUser == null) {
+    public static boolean removeUser(LDAPIdentityStore ldapIdentityStore, String username) {
+        LDAPUser ldapUser = getUser(ldapIdentityStore, username);
+        if (ldapUser == null) {
             return false;
         }
-        idmManager.remove(picketlinkUser);
+        ldapIdentityStore.remove(ldapUser);
         return true;
     }
 
-    public static void removeAllUsers(PartitionManager partitionManager) {
-        IdentityManager idmManager = getIdentityManager(partitionManager);
-        List<User> users = idmManager.createIdentityQuery(User.class).getResultList();
+    public static void removeAllUsers(LDAPIdentityStore ldapIdentityStore) {
+        List<LDAPUser> allUsers = getAllUsers(ldapIdentityStore);
 
-        for (User user : users) {
-            idmManager.remove(user);
+        for (LDAPUser user : allUsers) {
+            ldapIdentityStore.remove(user);
         }
     }
 
-    public static List<User> getAllUsers(PartitionManager partitionManager) {
-        IdentityManager idmManager = getIdentityManager(partitionManager);
-        return idmManager.createIdentityQuery(User.class).getResultList();
-    }
-
-    private static IdentityManager getIdentityManager(PartitionManager partitionManager) {
-        return partitionManager.createIdentityManager();
+    public static List<LDAPUser> getAllUsers(LDAPIdentityStore ldapIdentityStore) {
+        IdentityQuery<LDAPUser> userQuery = ldapIdentityStore.createQueryBuilder().createIdentityQuery(LDAPUser.class);
+        return userQuery.getResultList();
     }
 
     // Needed for ActiveDirectory updates
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/WritableLDAPUserModelDelegate.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/WritableLDAPUserModelDelegate.java
index 9a68f6a..4debf0e 100755
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/WritableLDAPUserModelDelegate.java
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/WritableLDAPUserModelDelegate.java
@@ -1,16 +1,11 @@
 package org.keycloak.federation.ldap;
 
 import org.jboss.logging.Logger;
-import org.keycloak.models.ModelException;
+import org.keycloak.federation.ldap.idm.model.LDAPUser;
+import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore;
 import org.keycloak.models.UserCredentialModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.utils.UserModelDelegate;
-import org.picketlink.idm.IdentityManagementException;
-import org.picketlink.idm.IdentityManager;
-import org.picketlink.idm.credential.Password;
-import org.picketlink.idm.credential.TOTPCredential;
-import org.picketlink.idm.model.basic.BasicModel;
-import org.picketlink.idm.model.basic.User;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -28,52 +23,43 @@ public class WritableLDAPUserModelDelegate extends UserModelDelegate implements 
 
     @Override
     public void setUsername(String username) {
-        IdentityManager identityManager = provider.getIdentityManager();
-
-        try {
-            User picketlinkUser = BasicModel.getUser(identityManager, delegate.getUsername());
-            if (picketlinkUser == null) {
-                throw new IllegalStateException("User not found in LDAP storage!");
-            }
-            picketlinkUser.setLoginName(username);
-            identityManager.update(picketlinkUser);
-        } catch (IdentityManagementException ie) {
-            throw new ModelException(ie);
+        LDAPIdentityStore ldapIdentityStore = provider.getLdapIdentityStore();
+
+        LDAPUser ldapUser = LDAPUtils.getUser(ldapIdentityStore, delegate.getUsername());
+        if (ldapUser == null) {
+            throw new IllegalStateException("User not found in LDAP storage!");
         }
+        ldapUser.setLoginName(username);
+        ldapIdentityStore.update(ldapUser);
+
         delegate.setUsername(username);
     }
 
     @Override
     public void setLastName(String lastName) {
-        IdentityManager identityManager = provider.getIdentityManager();
-
-        try {
-            User picketlinkUser = BasicModel.getUser(identityManager, delegate.getUsername());
-            if (picketlinkUser == null) {
-                throw new IllegalStateException("User not found in LDAP storage!");
-            }
-            picketlinkUser.setLastName(lastName);
-            identityManager.update(picketlinkUser);
-        } catch (IdentityManagementException ie) {
-            throw new ModelException(ie);
+        LDAPIdentityStore ldapIdentityStore = provider.getLdapIdentityStore();
+
+        LDAPUser ldapUser = LDAPUtils.getUser(ldapIdentityStore, delegate.getUsername());
+        if (ldapUser == null) {
+            throw new IllegalStateException("User not found in LDAP storage!");
         }
+        ldapUser.setLastName(lastName);
+        ldapIdentityStore.update(ldapUser);
+
         delegate.setLastName(lastName);
     }
 
     @Override
     public void setFirstName(String first) {
-        IdentityManager identityManager = provider.getIdentityManager();
-
-        try {
-            User picketlinkUser = BasicModel.getUser(identityManager, delegate.getUsername());
-            if (picketlinkUser == null) {
-                throw new IllegalStateException("User not found in LDAP storage!");
-            }
-            picketlinkUser.setFirstName(first);
-            identityManager.update(picketlinkUser);
-        } catch (IdentityManagementException ie) {
-            throw new ModelException(ie);
+        LDAPIdentityStore ldapIdentityStore = provider.getLdapIdentityStore();
+
+        LDAPUser ldapUser = LDAPUtils.getUser(ldapIdentityStore, delegate.getUsername());
+        if (ldapUser == null) {
+            throw new IllegalStateException("User not found in LDAP storage!");
         }
+        ldapUser.setFirstName(first);
+        ldapIdentityStore.update(ldapUser);
+
         delegate.setFirstName(first);
     }
 
@@ -83,41 +69,31 @@ public class WritableLDAPUserModelDelegate extends UserModelDelegate implements 
             delegate.updateCredential(cred);
             return;
         }
-        IdentityManager identityManager = provider.getIdentityManager();
-
-        try {
-            User picketlinkUser = BasicModel.getUser(identityManager, getUsername());
-            if (picketlinkUser == null) {
-                logger.debugf("User '%s' doesn't exists. Skip password update", getUsername());
-                throw new IllegalStateException("User doesn't exist in LDAP storage");
-            }
-            if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
-                identityManager.updateCredential(picketlinkUser, new Password(cred.getValue().toCharArray()));
-            } else if (cred.getType().equals(UserCredentialModel.TOTP)) {
-                TOTPCredential credential = new TOTPCredential(cred.getValue());
-                credential.setDevice(cred.getDevice());
-                identityManager.updateCredential(picketlinkUser, credential);
-            }
-        } catch (IdentityManagementException ie) {
-            throw new ModelException(ie);
+
+        LDAPIdentityStore ldapIdentityStore = provider.getLdapIdentityStore();
+        LDAPUser ldapUser = LDAPUtils.getUser(ldapIdentityStore, delegate.getUsername());
+        if (ldapUser == null) {
+            throw new IllegalStateException("User " + delegate.getUsername() + " not found in LDAP storage!");
         }
 
+        if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
+            LDAPUtils.updatePassword(ldapIdentityStore, delegate, cred.getValue());
+        } else {
+            logger.warnf("Don't know how to update credential of type [%s] for user [%s]", cred.getType(), delegate.getUsername());
+        }
     }
 
     @Override
     public void setEmail(String email) {
-        IdentityManager identityManager = provider.getIdentityManager();
-
-        try {
-            User picketlinkUser = BasicModel.getUser(identityManager, delegate.getUsername());
-            if (picketlinkUser == null) {
-                throw new IllegalStateException("User not found in LDAP storage!");
-            }
-            picketlinkUser.setEmail(email);
-            identityManager.update(picketlinkUser);
-        } catch (IdentityManagementException ie) {
-            throw new ModelException(ie);
+        LDAPIdentityStore ldapIdentityStore = provider.getLdapIdentityStore();
+
+        LDAPUser ldapUser = LDAPUtils.getUser(ldapIdentityStore, delegate.getUsername());
+        if (ldapUser == null) {
+            throw new IllegalStateException("User not found in LDAP storage!");
         }
+        ldapUser.setEmail(email);
+        ldapIdentityStore.update(ldapUser);
+
         delegate.setEmail(email);
     }
 
diff --git a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/SessionsBean.java b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/SessionsBean.java
index 03ba5b3..646b44b 100755
--- a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/SessionsBean.java
+++ b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/SessionsBean.java
@@ -1,14 +1,11 @@
 package org.keycloak.account.freemarker.model;
 
-import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserSessionModel;
 import org.keycloak.util.Time;
 
-import java.util.ArrayList;
 import java.util.Date;
 import java.util.HashSet;
 import java.util.LinkedList;
@@ -63,23 +60,14 @@ public class SessionsBean {
             return Time.toDate(max);
         }
 
-        public Set<String> getApplications() {
-            Set<String> apps = new HashSet<String>();
+        public Set<String> getClients() {
+            Set<String> clients = new HashSet<String>();
             for (ClientSessionModel clientSession : session.getClientSessions()) {
                 ClientModel client = clientSession.getClient();
-                if (client instanceof ApplicationModel) apps.add(client.getClientId());
+                clients.add(client.getClientId());
             }
-            return apps;
+            return clients;
         }
-        public List<String> getClients() {
-            List<String> apps = new ArrayList<String>();
-            for (ClientSessionModel clientSession : session.getClientSessions()) {
-                ClientModel client = clientSession.getClient();
-                if (client instanceof OAuthClientModel) apps.add(client.getClientId());
-            }
-            return apps;
-        }
-
     }
 
 }
diff --git a/forms/common-themes/src/main/resources/theme/base/account/sessions.ftl b/forms/common-themes/src/main/resources/theme/base/account/sessions.ftl
index c781c79..1c0ef1b 100755
--- a/forms/common-themes/src/main/resources/theme/base/account/sessions.ftl
+++ b/forms/common-themes/src/main/resources/theme/base/account/sessions.ftl
@@ -14,7 +14,6 @@
             <td>${msg("started")}</td>
             <td>${msg("lastAccess")}</td>
             <td>${msg("expires")}</td>
-            <td>${msg("applications")}</td>
             <td>${msg("clients")}</td>
         </tr>
         </thead>
@@ -27,11 +26,6 @@
                 <td>${session.lastAccess?datetime}</td>
                 <td>${session.expires?datetime}</td>
                 <td>
-                    <#list session.applications as app>
-                        ${app}<br/>
-                    </#list>
-                </td>
-                <td>
                     <#list session.clients as client>
                         ${client}<br/>
                     </#list>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/index.ftl b/forms/common-themes/src/main/resources/theme/base/admin/index.ftl
index 161acda..20e21b7 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/index.ftl
+++ b/forms/common-themes/src/main/resources/theme/base/admin/index.ftl
@@ -30,8 +30,7 @@
 
     <script src="${resourceUrl}/js/app.js" type="text/javascript"></script>
     <script src="${resourceUrl}/js/controllers/realm.js" type="text/javascript"></script>
-    <script src="${resourceUrl}/js/controllers/applications.js" type="text/javascript"></script>
-    <script src="${resourceUrl}/js/controllers/oauth-clients.js" type="text/javascript"></script>
+    <script src="${resourceUrl}/js/controllers/clients.js" type="text/javascript"></script>
     <script src="${resourceUrl}/js/controllers/users.js" type="text/javascript"></script>
     <script src="${resourceUrl}/js/loaders.js" type="text/javascript"></script>
     <script src="${resourceUrl}/js/services.js" type="text/javascript"></script>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js
index e38c29c..f45453c 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js
@@ -212,8 +212,8 @@ module.config([ '$routeProvider', function($routeProvider) {
                 realm : function(RealmLoader) {
                     return RealmLoader();
                 },
-                applications : function(ApplicationListLoader) {
-                    return ApplicationListLoader();
+                clients : function(ClientListLoader) {
+                    return ClientListLoader();
                 },
                 roles : function(RoleListLoader) {
                     return RoleListLoader();
@@ -311,8 +311,8 @@ module.config([ '$routeProvider', function($routeProvider) {
                 user : function(UserLoader) {
                     return UserLoader();
                 },
-                applications : function(ApplicationListLoader) {
-                    return ApplicationListLoader();
+                clients : function(ClientListLoader) {
+                    return ClientListLoader();
                 }
             },
             controller : 'UserRoleMappingCtrl'
@@ -369,8 +369,8 @@ module.config([ '$routeProvider', function($routeProvider) {
                 roles : function(RoleListLoader) {
                     return RoleListLoader();
                 },
-                applications : function(ApplicationListLoader) {
-                    return ApplicationListLoader();
+                clients : function(ClientListLoader) {
+                    return ClientListLoader();
                 }
             },
             controller : 'RoleDetailCtrl'
@@ -387,8 +387,8 @@ module.config([ '$routeProvider', function($routeProvider) {
                 roles : function(RoleListLoader) {
                     return RoleListLoader();
                 },
-                applications : function(ApplicationListLoader) {
-                    return ApplicationListLoader();
+                clients : function(ClientListLoader) {
+                    return ClientListLoader();
                 }
             },
             controller : 'RoleDetailCtrl'
@@ -406,14 +406,14 @@ module.config([ '$routeProvider', function($routeProvider) {
             controller : 'RoleListCtrl'
         })
 
-        .when('/create/role/:realm/applications/:application', {
-            templateUrl : resourceUrl + '/partials/application-role-detail.html',
+        .when('/create/role/:realm/clients/:client', {
+            templateUrl : resourceUrl + '/partials/client-role-detail.html',
             resolve : {
                 realm : function(RealmLoader) {
                     return RealmLoader();
                 },
-                application : function(ApplicationLoader) {
-                    return ApplicationLoader();
+                client : function(ClientLoader) {
+                    return ClientLoader();
                 },
                 role : function() {
                     return {};
@@ -421,56 +421,56 @@ module.config([ '$routeProvider', function($routeProvider) {
                 roles : function(RoleListLoader) {
                     return RoleListLoader();
                 },
-                applications : function(ApplicationListLoader) {
-                    return ApplicationListLoader();
+                clients : function(ClientListLoader) {
+                    return ClientListLoader();
                 }
             },
-            controller : 'ApplicationRoleDetailCtrl'
+            controller : 'ClientRoleDetailCtrl'
         })
-        .when('/realms/:realm/applications/:application/roles/:role', {
-            templateUrl : resourceUrl + '/partials/application-role-detail.html',
+        .when('/realms/:realm/clients/:client/roles/:role', {
+            templateUrl : resourceUrl + '/partials/client-role-detail.html',
             resolve : {
                 realm : function(RealmLoader) {
                     return RealmLoader();
                 },
-                application : function(ApplicationLoader) {
-                    return ApplicationLoader();
+                client : function(ClientLoader) {
+                    return ClientLoader();
                 },
-                role : function(ApplicationRoleLoader) {
-                    return ApplicationRoleLoader();
+                role : function(ClientRoleLoader) {
+                    return ClientRoleLoader();
                 },
                 roles : function(RoleListLoader) {
                     return RoleListLoader();
                 },
-                applications : function(ApplicationListLoader) {
-                    return ApplicationListLoader();
+                clients : function(ClientListLoader) {
+                    return ClientListLoader();
                 }
             },
-            controller : 'ApplicationRoleDetailCtrl'
+            controller : 'ClientRoleDetailCtrl'
         })
-        .when('/realms/:realm/applications/:application/mappers', {
-            templateUrl : resourceUrl + '/partials/application-mappers.html',
+        .when('/realms/:realm/clients/:client/mappers', {
+            templateUrl : resourceUrl + '/partials/client-mappers.html',
             resolve : {
                 realm : function(RealmLoader) {
                     return RealmLoader();
                 },
-                application : function(ApplicationLoader) {
-                    return ApplicationLoader();
+                client : function(ClientLoader) {
+                    return ClientLoader();
                 },
                 serverInfo : function(ServerInfoLoader) {
                     return ServerInfoLoader();
                 }
             },
-            controller : 'ApplicationProtocolMapperListCtrl'
+            controller : 'ClientProtocolMapperListCtrl'
         })
-        .when('/realms/:realm/applications/:application/add-mappers', {
-            templateUrl : resourceUrl + '/partials/application-mappers-add.html',
+        .when('/realms/:realm/clients/:client/add-mappers', {
+            templateUrl : resourceUrl + '/partials/client-mappers-add.html',
             resolve : {
                 realm : function(RealmLoader) {
                     return RealmLoader();
                 },
-                application : function(ApplicationLoader) {
-                    return ApplicationLoader();
+                client : function(ClientLoader) {
+                    return ClientLoader();
                 },
                 serverInfo : function(ServerInfoLoader) {
                     return ServerInfoLoader();
@@ -478,26 +478,26 @@ module.config([ '$routeProvider', function($routeProvider) {
             },
             controller : 'AddBuiltinProtocolMapperCtrl'
         })
-        .when('/realms/:realm/applications/:application/mappers/:id', {
+        .when('/realms/:realm/clients/:client/mappers/:id', {
             templateUrl : resourceUrl + '/partials/protocol-mapper-detail.html',
             resolve : {
                 realm : function(RealmLoader) {
                     return RealmLoader();
                 },
-                application : function(ApplicationLoader) {
-                    return ApplicationLoader();
+                client : function(ClientLoader) {
+                    return ClientLoader();
                 },
                 serverInfo : function(ServerInfoLoader) {
                     return ServerInfoLoader();
                 },
-                mapper : function(ApplicationProtocolMapperLoader) {
-                    return ApplicationProtocolMapperLoader();
+                mapper : function(ClientProtocolMapperLoader) {
+                    return ClientProtocolMapperLoader();
                 }
 
             },
-            controller : 'ApplicationProtocolMapperCtrl'
+            controller : 'ClientProtocolMapperCtrl'
         })
-        .when('/create/application/:realm/:application/mappers', {
+        .when('/create/client/:realm/:client/mappers', {
             templateUrl : resourceUrl + '/partials/protocol-mapper-detail.html',
             resolve : {
                 realm : function(RealmLoader) {
@@ -506,297 +506,231 @@ module.config([ '$routeProvider', function($routeProvider) {
                 serverInfo : function(ServerInfoLoader) {
                     return ServerInfoLoader();
                 },
-                application : function(ApplicationLoader) {
-                    return ApplicationLoader();
+                client : function(ClientLoader) {
+                    return ClientLoader();
                 }
             },
-            controller : 'ApplicationProtocolMapperCreateCtrl'
-        })
-
-        .when('/realms/:realm/oauth-clients/:oauth/mappers', {
-                templateUrl : resourceUrl + '/partials/oauth-client-mappers.html',
-                resolve : {
-                    realm : function(RealmLoader) {
-                        return RealmLoader();
-                    },
-                    oauth : function(OAuthClientLoader) {
-                        return OAuthClientLoader();
-                    },
-                    serverInfo : function(ServerInfoLoader) {
-                        return ServerInfoLoader();
-                    }
-                },
-                controller : 'OAuthClientProtocolMapperListCtrl'
-            })
-            .when('/realms/:realm/oauth-clients/:oauth/add-mappers', {
-                templateUrl : resourceUrl + '/partials/oauth-client-mappers-add.html',
-                resolve : {
-                    realm : function(RealmLoader) {
-                        return RealmLoader();
-                    },
-                    oauth : function(OAuthClientLoader) {
-                        return OAuthClientLoader();
-                    },
-                    serverInfo : function(ServerInfoLoader) {
-                        return ServerInfoLoader();
-                    }
-                },
-                controller : 'OAuthClientAddBuiltinProtocolMapperCtrl'
-            })
-            .when('/realms/:realm/oauth-clients/:oauth/mappers/:id', {
-                templateUrl : resourceUrl + '/partials/oauth-client-protocol-mapper-detail.html',
-                resolve : {
-                    realm : function(RealmLoader) {
-                        return RealmLoader();
-                    },
-                    oauth : function(OAuthClientLoader) {
-                        return OAuthClientLoader();
-                    },
-                    serverInfo : function(ServerInfoLoader) {
-                        return ServerInfoLoader();
-                    },
-                    mapper : function(OAuthClientProtocolMapperLoader) {
-                        return OAuthClientProtocolMapperLoader();
-                    }
-
-                },
-                controller : 'OAuthClientProtocolMapperCtrl'
-            })
-            .when('/create/oauth-client/:realm/:oauth/mappers', {
-                templateUrl : resourceUrl + '/partials/oauth-client-protocol-mapper-detail.html',
-                resolve : {
-                    realm : function(RealmLoader) {
-                        return RealmLoader();
-                    },
-                    serverInfo : function(ServerInfoLoader) {
-                        return ServerInfoLoader();
-                    },
-                    oauth : function(OAuthClientLoader) {
-                        return OAuthClientLoader();
-                    }
-                },
-                controller : 'OAuthClientProtocolMapperCreateCtrl'
-            })
-
-        .when('/realms/:realm/applications/:application/sessions', {
-            templateUrl : resourceUrl + '/partials/application-sessions.html',
+            controller : 'ClientProtocolMapperCreateCtrl'
+        })
+        .when('/realms/:realm/clients/:client/sessions', {
+            templateUrl : resourceUrl + '/partials/client-sessions.html',
             resolve : {
                 realm : function(RealmLoader) {
                     return RealmLoader();
                 },
-                application : function(ApplicationLoader) {
-                    return ApplicationLoader();
+                client : function(ClientLoader) {
+                    return ClientLoader();
                 },
-                sessionCount : function(ApplicationSessionCountLoader) {
-                    return ApplicationSessionCountLoader();
+                sessionCount : function(ClientSessionCountLoader) {
+                    return ClientSessionCountLoader();
                 }
             },
-            controller : 'ApplicationSessionsCtrl'
+            controller : 'ClientSessionsCtrl'
         })
-        .when('/realms/:realm/applications/:application/credentials', {
-            templateUrl : resourceUrl + '/partials/application-credentials.html',
+        .when('/realms/:realm/clients/:client/credentials', {
+            templateUrl : resourceUrl + '/partials/client-credentials.html',
             resolve : {
                 realm : function(RealmLoader) {
                     return RealmLoader();
                 },
-                application : function(ApplicationLoader) {
-                    return ApplicationLoader();
+                client : function(ClientLoader) {
+                    return ClientLoader();
                 }
             },
-            controller : 'ApplicationCredentialsCtrl'
+            controller : 'ClientCredentialsCtrl'
         })
-        .when('/realms/:realm/applications/:application/identity-provider', {
-            templateUrl : resourceUrl + '/partials/application-identity-provider.html',
+        .when('/realms/:realm/clients/:client/identity-provider', {
+            templateUrl : resourceUrl + '/partials/client-identity-provider.html',
             resolve : {
                 realm : function(RealmLoader) {
                     return RealmLoader();
                 },
-                application : function(ApplicationLoader) {
-                    return ApplicationLoader();
+                client : function(ClientLoader) {
+                    return ClientLoader();
                 }
             },
-            controller : 'ApplicationIdentityProviderCtrl'
+            controller : 'ClientIdentityProviderCtrl'
         })
-        .when('/realms/:realm/applications/:application/clustering', {
-            templateUrl : resourceUrl + '/partials/application-clustering.html',
+        .when('/realms/:realm/clients/:client/clustering', {
+            templateUrl : resourceUrl + '/partials/client-clustering.html',
             resolve : {
                 realm : function(RealmLoader) {
                     return RealmLoader();
                 },
-                application : function(ApplicationLoader) {
-                    return ApplicationLoader();
+                client : function(ClientLoader) {
+                    return ClientLoader();
                 }
             },
-            controller : 'ApplicationClusteringCtrl'
+            controller : 'ClientClusteringCtrl'
         })
-        .when('/register-node/realms/:realm/applications/:application/clustering', {
-            templateUrl : resourceUrl + '/partials/application-clustering-node.html',
+        .when('/register-node/realms/:realm/clients/:client/clustering', {
+            templateUrl : resourceUrl + '/partials/client-clustering-node.html',
             resolve : {
                 realm : function(RealmLoader) {
                     return RealmLoader();
                 },
-                application : function(ApplicationLoader) {
-                    return ApplicationLoader();
+                client : function(ClientLoader) {
+                    return ClientLoader();
                 }
             },
-            controller : 'ApplicationClusteringNodeCtrl'
+            controller : 'ClientClusteringNodeCtrl'
         })
-        .when('/realms/:realm/applications/:application/clustering/:node', {
-            templateUrl : resourceUrl + '/partials/application-clustering-node.html',
+        .when('/realms/:realm/clients/:client/clustering/:node', {
+            templateUrl : resourceUrl + '/partials/client-clustering-node.html',
             resolve : {
                 realm : function(RealmLoader) {
                     return RealmLoader();
                 },
-                application : function(ApplicationLoader) {
-                    return ApplicationLoader();
+                client : function(ClientLoader) {
+                    return ClientLoader();
                 }
             },
-            controller : 'ApplicationClusteringNodeCtrl'
+            controller : 'ClientClusteringNodeCtrl'
         })
-        .when('/realms/:realm/applications/:application/saml/keys', {
-            templateUrl : resourceUrl + '/partials/application-saml-keys.html',
+        .when('/realms/:realm/clients/:client/saml/keys', {
+            templateUrl : resourceUrl + '/partials/client-saml-keys.html',
             resolve : {
                 realm : function(RealmLoader) {
                     return RealmLoader();
                 },
-                application : function(ApplicationLoader) {
-                    return ApplicationLoader();
+                client : function(ClientLoader) {
+                    return ClientLoader();
                 }
             },
-            controller : 'ApplicationSamlKeyCtrl'
+            controller : 'ClientSamlKeyCtrl'
         })
-        .when('/realms/:realm/applications/:application/saml/:keyType/import/:attribute', {
-            templateUrl : resourceUrl + '/partials/application-saml-key-import.html',
+        .when('/realms/:realm/clients/:client/saml/:keyType/import/:attribute', {
+            templateUrl : resourceUrl + '/partials/client-saml-key-import.html',
             resolve : {
                 realm : function(RealmLoader) {
                     return RealmLoader();
                 },
-                application : function(ApplicationLoader) {
-                    return ApplicationLoader();
+                client : function(ClientLoader) {
+                    return ClientLoader();
                 }
             },
-            controller : 'ApplicationCertificateImportCtrl'
+            controller : 'ClientCertificateImportCtrl'
         })
-        .when('/realms/:realm/applications/:application/saml/:keyType/export/:attribute', {
-            templateUrl : resourceUrl + '/partials/application-saml-key-export.html',
+        .when('/realms/:realm/clients/:client/saml/:keyType/export/:attribute', {
+            templateUrl : resourceUrl + '/partials/client-saml-key-export.html',
             resolve : {
                 realm : function(RealmLoader) {
                     return RealmLoader();
                 },
-                application : function(ApplicationLoader) {
-                    return ApplicationLoader();
+                client : function(ClientLoader) {
+                    return ClientLoader();
                 }
             },
-            controller : 'ApplicationCertificateExportCtrl'
+            controller : 'ClientCertificateExportCtrl'
         })
-        .when('/realms/:realm/applications/:application/roles', {
-            templateUrl : resourceUrl + '/partials/application-role-list.html',
+        .when('/realms/:realm/clients/:client/roles', {
+            templateUrl : resourceUrl + '/partials/client-role-list.html',
             resolve : {
                 realm : function(RealmLoader) {
                     return RealmLoader();
                 },
-                application : function(ApplicationLoader) {
-                    return ApplicationLoader();
+                client : function(ClientLoader) {
+                    return ClientLoader();
                 },
-                roles : function(ApplicationRoleListLoader) {
-                    return ApplicationRoleListLoader();
+                roles : function(ClientRoleListLoader) {
+                    return ClientRoleListLoader();
                 }
             },
-            controller : 'ApplicationRoleListCtrl'
+            controller : 'ClientRoleListCtrl'
         })
-        .when('/realms/:realm/applications/:application/revocation', {
-            templateUrl : resourceUrl + '/partials/application-revocation.html',
+        .when('/realms/:realm/clients/:client/revocation', {
+            templateUrl : resourceUrl + '/partials/client-revocation.html',
             resolve : {
                 realm : function(RealmLoader) {
                     return RealmLoader();
                 },
-                application : function(ApplicationLoader) {
-                    return ApplicationLoader();
+                client : function(ClientLoader) {
+                    return ClientLoader();
                 }
             },
-            controller : 'ApplicationRevocationCtrl'
+            controller : 'ClientRevocationCtrl'
         })
-        .when('/realms/:realm/applications/:application/scope-mappings', {
-            templateUrl : resourceUrl + '/partials/application-scope-mappings.html',
+        .when('/realms/:realm/clients/:client/scope-mappings', {
+            templateUrl : resourceUrl + '/partials/client-scope-mappings.html',
             resolve : {
                 realm : function(RealmLoader) {
                     return RealmLoader();
                 },
-                application : function(ApplicationLoader) {
-                    return ApplicationLoader();
+                client : function(ClientLoader) {
+                    return ClientLoader();
                 },
-                applications : function(ApplicationListLoader) {
-                    return ApplicationListLoader();
+                clients : function(ClientListLoader) {
+                    return ClientListLoader();
                 }
             },
-            controller : 'ApplicationScopeMappingCtrl'
+            controller : 'ClientScopeMappingCtrl'
         })
-        .when('/realms/:realm/applications/:application/installation', {
-            templateUrl : resourceUrl + '/partials/application-installation.html',
+        .when('/realms/:realm/clients/:client/installation', {
+            templateUrl : resourceUrl + '/partials/client-installation.html',
             resolve : {
                 realm : function(RealmLoader) {
                     return RealmLoader();
                 },
-                application : function(ApplicationLoader) {
-                    return ApplicationLoader();
+                client : function(ClientLoader) {
+                    return ClientLoader();
                 }
             },
-            controller : 'ApplicationInstallationCtrl'
+            controller : 'ClientInstallationCtrl'
         })
-        .when('/create/application/:realm', {
-            templateUrl : resourceUrl + '/partials/application-detail.html',
+        .when('/create/client/:realm', {
+            templateUrl : resourceUrl + '/partials/client-detail.html',
             resolve : {
                 realm : function(RealmLoader) {
                     return RealmLoader();
                 },
-                applications : function(ApplicationListLoader) {
-                    return ApplicationListLoader();
+                clients : function(ClientListLoader) {
+                    return ClientListLoader();
                 },
-                application : function() {
+                client : function() {
                     return {};
                 },
                 serverInfo : function(ServerInfoLoader) {
                     return ServerInfoLoader();
                 }
             },
-            controller : 'ApplicationDetailCtrl'
+            controller : 'ClientDetailCtrl'
         })
-        .when('/realms/:realm/applications/:application', {
-            templateUrl : resourceUrl + '/partials/application-detail.html',
+        .when('/realms/:realm/clients/:client', {
+            templateUrl : resourceUrl + '/partials/client-detail.html',
             resolve : {
                 realm : function(RealmLoader) {
                     return RealmLoader();
                 },
-                applications : function(ApplicationListLoader) {
-                    return ApplicationListLoader();
+                clients : function(ClientListLoader) {
+                    return ClientListLoader();
                 },
-                application : function(ApplicationLoader) {
-                    return ApplicationLoader();
+                client : function(ClientLoader) {
+                    return ClientLoader();
                 },
                 serverInfo : function(ServerInfoLoader) {
                     return ServerInfoLoader();
                 }
             },
-            controller : 'ApplicationDetailCtrl'
+            controller : 'ClientDetailCtrl'
         })
-        .when('/realms/:realm/applications', {
-            templateUrl : resourceUrl + '/partials/application-list.html',
+        .when('/realms/:realm/clients', {
+            templateUrl : resourceUrl + '/partials/client-list.html',
             resolve : {
                 realm : function(RealmLoader) {
                     return RealmLoader();
                 },
-                applications : function(ApplicationListLoader) {
-                    return ApplicationListLoader();
+                clients : function(ClientListLoader) {
+                    return ClientListLoader();
                 },
                 serverInfo : function(ServerInfoLoader) {
                     return ServerInfoLoader();
                 }
 
             },
-            controller : 'ApplicationListCtrl'
+            controller : 'ClientListCtrl'
         })
-        .when('/import/application/:realm', {
-            templateUrl : resourceUrl + '/partials/application-import.html',
+        .when('/import/client/:realm', {
+            templateUrl : resourceUrl + '/partials/client-import.html',
             resolve : {
                 realm : function(RealmLoader) {
                     return RealmLoader();
@@ -805,129 +739,8 @@ module.config([ '$routeProvider', function($routeProvider) {
                     return ServerInfoLoader();
                 }
             },
-            controller : 'ApplicationImportCtrl'
-        })
-
-        // OAUTH Client
-
-        .when('/realms/:realm/oauth-clients/:oauth/claims', {
-            templateUrl : resourceUrl + '/partials/oauth-client-claims.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                oauth : function(OAuthClientLoader) {
-                    return OAuthClientLoader();
-                },
-                claims : function(OAuthClientClaimsLoader) {
-                    return OAuthClientClaimsLoader();
-                }
-            },
-            controller : 'OAuthClientClaimsCtrl'
-        })
-        .when('/realms/:realm/oauth-clients/:oauth/revocation', {
-            templateUrl : resourceUrl + '/partials/oauth-client-revocation.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                oauth : function(OAuthClientLoader) {
-                    return OAuthClientLoader();
-                }
-            },
-            controller : 'OAuthClientRevocationCtrl'
-        })
-        .when('/realms/:realm/oauth-clients/:oauth/credentials', {
-            templateUrl : resourceUrl + '/partials/oauth-client-credentials.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                oauth : function(OAuthClientLoader) {
-                    return OAuthClientLoader();
-                }
-            },
-            controller : 'OAuthClientCredentialsCtrl'
-        })
-        .when('/realms/:realm/oauth-clients/:oauth/scope-mappings', {
-            templateUrl : resourceUrl + '/partials/oauth-client-scope-mappings.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                oauth : function(OAuthClientLoader) {
-                    return OAuthClientLoader();
-                },
-                applications : function(ApplicationListLoader) {
-                    return ApplicationListLoader();
-                }
-            },
-            controller : 'OAuthClientScopeMappingCtrl'
-        })
-        .when('/realms/:realm/oauth-clients/:oauth/installation', {
-            templateUrl : resourceUrl + '/partials/oauth-client-installation.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                oauth : function(OAuthClientLoader) {
-                    return OAuthClientLoader();
-                },
-                installation : function(OAuthClientInstallationLoader) {
-                    return OAuthClientInstallationLoader();
-                }
-            },
-            controller : 'OAuthClientInstallationCtrl'
-        })
-        .when('/create/oauth-client/:realm', {
-            templateUrl : resourceUrl + '/partials/oauth-client-detail.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                oauth : function() {
-                    return {};
-                }
-            },
-            controller : 'OAuthClientDetailCtrl'
-        })
-        .when('/realms/:realm/oauth-clients/:oauth', {
-            templateUrl : resourceUrl + '/partials/oauth-client-detail.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                oauth : function(OAuthClientLoader) {
-                    return OAuthClientLoader();
-                }
-            },
-            controller : 'OAuthClientDetailCtrl'
-        })
-        .when('/realms/:realm/oauth-clients/:oauth/identity-provider', {
-            templateUrl : resourceUrl + '/partials/oauth-client-identity-provider.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                oauth : function(OAuthClientLoader) {
-                    return OAuthClientLoader();
-                }
-            },
-            controller : 'OAuthClientIdentityProviderCtrl'
+            controller : 'ClientImportCtrl'
         })
-        .when('/realms/:realm/oauth-clients', {
-            templateUrl : resourceUrl + '/partials/oauth-client-list.html',
-            resolve : {
-                realm : function(RealmLoader) {
-                    return RealmLoader();
-                },
-                oauthClients : function(OAuthClientListLoader) {
-                    return OAuthClientListLoader();
-                }
-            },
-            controller : 'OAuthClientListCtrl'
-        })
-
         .when('/', {
             templateUrl : resourceUrl + '/partials/home.html',
             controller : 'HomeCtrl'
@@ -959,8 +772,8 @@ module.config([ '$routeProvider', function($routeProvider) {
                 realm : function(RealmLoader) {
                     return RealmLoader();
                 },
-                stats : function(RealmApplicationSessionStatsLoader) {
-                    return RealmApplicationSessionStatsLoader();
+                stats : function(RealmClientSessionStatsLoader) {
+                    return RealmClientSessionStatsLoader();
                 }
             },
             controller : 'RealmSessionStatsCtrl'
@@ -1540,21 +1353,12 @@ module.directive('kcNavigation', function ($compile, Notifications) {
     }
 });
 
-module.directive('kcNavigationApplication', function () {
-    return {
-        scope: true,
-        restrict: 'E',
-        replace: true,
-        templateUrl: resourceUrl + '/templates/kc-navigation-application.html'
-    }
-});
-
-module.directive('kcNavigationOauthClient', function () {
+module.directive('kcNavigationClient', function () {
     return {
         scope: true,
         restrict: 'E',
         replace: true,
-        templateUrl: resourceUrl + '/templates/kc-navigation-oauth-client.html'
+        templateUrl: resourceUrl + '/templates/kc-navigation-client.html'
     }
 });
 
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
index bb7620e..97c1bda 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
@@ -53,10 +53,6 @@ module.controller('GlobalCtrl', function($scope, $http, Auth, WhoAmI, Current, $
             return getAccess('view-realm') || this.manageRealm;
         },
 
-        get viewApplications() {
-            return getAccess('view-applications') || this.manageApplications;
-        },
-
         get viewClients() {
             return getAccess('view-clients') || this.manageClients;
         },
@@ -73,10 +69,6 @@ module.controller('GlobalCtrl', function($scope, $http, Auth, WhoAmI, Current, $
             return getAccess('manage-realm');
         },
 
-        get manageApplications() {
-            return getAccess('manage-applications');
-        },
-
         get manageClients() {
             return getAccess('manage-clients');
         },
@@ -484,7 +476,7 @@ module.controller('RealmRequiredCredentialsCtrl', function($scope, Realm, realm,
     };
 });
 
-module.controller('RealmDefaultRolesCtrl', function ($scope, Realm, realm, applications, roles, Notifications, ApplicationRole, Application) {
+module.controller('RealmDefaultRolesCtrl', function ($scope, Realm, realm, clients, roles, Notifications, ClientRole, Client) {
 
     console.log('RealmDefaultRolesCtrl');
 
@@ -494,17 +486,17 @@ module.controller('RealmDefaultRolesCtrl', function ($scope, Realm, realm, appli
     $scope.selectedRealmRoles = [];
     $scope.selectedRealmDefRoles = [];
 
-    $scope.applications = angular.copy(applications);
-    for (var i = 0; i < applications.length; i++) {
-        if (applications[i].name == 'account') {
-            $scope.application = $scope.applications[i];
+    $scope.clients = angular.copy(clients);
+    for (var i = 0; i < clients.length; i++) {
+        if (clients[i].name == 'account') {
+            $scope.client = $scope.clients[i];
             break;
         }
     }
 
-    $scope.availableAppRoles = [];
-    $scope.selectedAppRoles = [];
-    $scope.selectedAppDefRoles = [];
+    $scope.availableClientRoles = [];
+    $scope.selectedClientRoles = [];
+    $scope.selectedClientDefRoles = [];
 
     if (!$scope.realm.hasOwnProperty('defaultRoles') || $scope.realm.defaultRoles === null) {
         $scope.realm.defaultRoles = [];
@@ -558,81 +550,81 @@ module.controller('RealmDefaultRolesCtrl', function ($scope, Realm, realm, appli
         });
     };
 
-    $scope.changeApplication = function () {
+    $scope.changeClient = function () {
 
-        $scope.selectedAppRoles = [];
-        $scope.selectedAppDefRoles = [];
+        $scope.selectedClientRoles = [];
+        $scope.selectedClientDefRoles = [];
 
-        // Populate available roles for selected application
-        if ($scope.application) {
-            var appDefaultRoles = ApplicationRole.query({realm: $scope.realm.realm, application: $scope.application.id}, function () {
+        // Populate available roles for selected client
+        if ($scope.client) {
+            var appDefaultRoles = ClientRole.query({realm: $scope.realm.realm, client: $scope.client.id}, function () {
 
-                if (!$scope.application.hasOwnProperty('defaultRoles') || $scope.application.defaultRoles === null) {
-                    $scope.application.defaultRoles = [];
+                if (!$scope.client.hasOwnProperty('defaultRoles') || $scope.client.defaultRoles === null) {
+                    $scope.client.defaultRoles = [];
                 }
 
-                $scope.availableAppRoles = [];
+                $scope.availableClientRoles = [];
 
                 for (var i = 0; i < appDefaultRoles.length; i++) {
                     var roleName = appDefaultRoles[i].name;
-                    if ($scope.application.defaultRoles.indexOf(roleName) < 0) {
-                        $scope.availableAppRoles.push(roleName);
+                    if ($scope.client.defaultRoles.indexOf(roleName) < 0) {
+                        $scope.availableClientRoles.push(roleName);
                     }
                 }
             });
         } else {
-            $scope.availableAppRoles = null;
+            $scope.availableClientRoles = null;
         }
     };
 
-    $scope.addAppDefaultRole = function () {
+    $scope.addClientDefaultRole = function () {
 
         // Remove selected roles from the app available roles and add them to app default roles (move from left to right).
-        for (var i = 0; i < $scope.selectedAppRoles.length; i++) {
-            var role = $scope.selectedAppRoles[i];
+        for (var i = 0; i < $scope.selectedClientRoles.length; i++) {
+            var role = $scope.selectedClientRoles[i];
 
-            var idx = $scope.application.defaultRoles.indexOf(role);
+            var idx = $scope.client.defaultRoles.indexOf(role);
             if (idx < 0) {
-                $scope.application.defaultRoles.push(role);
+                $scope.client.defaultRoles.push(role);
             }
 
-            idx = $scope.availableAppRoles.indexOf(role);
+            idx = $scope.availableClientRoles.indexOf(role);
 
             if (idx != -1) {
-                $scope.availableAppRoles.splice(idx, 1);
+                $scope.availableClientRoles.splice(idx, 1);
             }
         }
 
-        // Update/save the selected application with new default roles.
-        Application.update({
+        // Update/save the selected client with new default roles.
+        Client.update({
             realm: $scope.realm.realm,
-            application: $scope.application.id
-        }, $scope.application, function () {
-            Notifications.success("Your changes have been saved to the application.");
+            client: $scope.client.id
+        }, $scope.client, function () {
+            Notifications.success("Your changes have been saved to the client.");
         });
     };
 
-    $scope.rmAppDefaultRole = function () {
+    $scope.rmClientDefaultRole = function () {
 
         // Remove selected roles from the app default roles and add them to app available roles (move from right to left).
-        for (var i = 0; i < $scope.selectedAppDefRoles.length; i++) {
-            var role = $scope.selectedAppDefRoles[i];
-            var idx = $scope.application.defaultRoles.indexOf(role);
+        for (var i = 0; i < $scope.selectedClientDefRoles.length; i++) {
+            var role = $scope.selectedClientDefRoles[i];
+            var idx = $scope.client.defaultRoles.indexOf(role);
             if (idx != -1) {
-                $scope.application.defaultRoles.splice(idx, 1);
+                $scope.client.defaultRoles.splice(idx, 1);
             }
-            idx = $scope.availableAppRoles.indexOf(role);
+            idx = $scope.availableClientRoles.indexOf(role);
             if (idx < 0) {
-                $scope.availableAppRoles.push(role);
+                $scope.availableClientRoles.push(role);
             }
         }
 
-        // Update/save the selected application with new default roles.
-        Application.update({
+        // Update/save the selected client with new default roles.
+        Client.update({
             realm: $scope.realm.realm,
-            application: $scope.application.id
-        }, $scope.application, function () {
-            Notifications.success("Your changes have been saved to the application.");
+            client: $scope.client.id
+        }, $scope.client, function () {
+            Notifications.success("Your changes have been saved to the client.");
         });
     };
 
@@ -856,7 +848,7 @@ module.controller('RealmIdentityProviderCtrl', function($scope, $filter, $upload
                 alias : $scope.identityProvider.alias
             }, function() {
                 $location.url("/realms/" + realm.realm + "/identity-provider-settings");
-                Notifications.success("The application has been deleted.");
+                Notifications.success("The client has been deleted.");
             });
         });
     };
@@ -1016,7 +1008,7 @@ module.controller('RealmKeysDetailCtrl', function($scope, Realm, realm, $http, $
     };
 });
 
-module.controller('RealmSessionStatsCtrl', function($scope, realm, stats, RealmApplicationSessionStats, RealmLogoutAll, Notifications) {
+module.controller('RealmSessionStatsCtrl', function($scope, realm, stats, RealmClientSessionStats, RealmLogoutAll, Notifications) {
     $scope.realm = realm;
     $scope.stats = stats;
 
@@ -1081,7 +1073,7 @@ module.controller('RealmRevocationCtrl', function($scope, Realm, RealmPushRevoca
                 var msgStart = successCount>0 ? 'Successfully push notBefore to: ' + globalReqResult.successRequests + ' . ' : '';
                 Notifications.error(msgStart + 'Failed to push notBefore to: ' + globalReqResult.failedRequests + '. Verify availability of failed hosts and try again');
             } else {
-                Notifications.success('Successfully push notBefore to all configured applications');
+                Notifications.success('Successfully push notBefore to all configured clients');
             }
         });
     }
@@ -1102,8 +1094,8 @@ module.controller('RoleListCtrl', function($scope, $location, realm, roles) {
 });
 
 
-module.controller('RoleDetailCtrl', function($scope, realm, role, roles, applications,
-                                             Role, ApplicationRole, RoleById, RoleRealmComposites, RoleApplicationComposites,
+module.controller('RoleDetailCtrl', function($scope, realm, role, roles, clients,
+                                             Role, ClientRole, RoleById, RoleRealmComposites, RoleClientComposites,
                                              $http, $location, Dialog, Notifications) {
     $scope.realm = realm;
     $scope.role = angular.copy(role);
@@ -1149,8 +1141,8 @@ module.controller('RoleDetailCtrl', function($scope, realm, role, roles, applica
 
 
 
-    roleControl($scope, realm, role, roles, applications,
-        ApplicationRole, RoleById, RoleRealmComposites, RoleApplicationComposites,
+    roleControl($scope, realm, role, roles, clients,
+        ClientRole, RoleById, RoleRealmComposites, RoleClientComposites,
         $http, $location, Notifications, Dialog);
 });
 
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js
index 3d50839..30003bd 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js
@@ -1,17 +1,17 @@
-module.controller('UserRoleMappingCtrl', function($scope, $http, realm, user, applications, Notifications, RealmRoleMapping,
-                                                  ApplicationRoleMapping, AvailableRealmRoleMapping, AvailableApplicationRoleMapping,
-                                                  CompositeRealmRoleMapping, CompositeApplicationRoleMapping) {
+module.controller('UserRoleMappingCtrl', function($scope, $http, realm, user, clients, Notifications, RealmRoleMapping,
+                                                  ClientRoleMapping, AvailableRealmRoleMapping, AvailableClientRoleMapping,
+                                                  CompositeRealmRoleMapping, CompositeClientRoleMapping) {
     $scope.realm = realm;
     $scope.user = user;
     $scope.selectedRealmRoles = [];
     $scope.selectedRealmMappings = [];
     $scope.realmMappings = [];
-    $scope.applications = applications;
-    $scope.applicationRoles = [];
-    $scope.applicationComposite = [];
-    $scope.selectedApplicationRoles = [];
-    $scope.selectedApplicationMappings = [];
-    $scope.applicationMappings = [];
+    $scope.clients = clients;
+    $scope.clientRoles = [];
+    $scope.clientComposite = [];
+    $scope.selectedClientRoles = [];
+    $scope.selectedClientMappings = [];
+    $scope.clientMappings = [];
     $scope.dummymodel = [];
 
     $scope.realmMappings = RealmRoleMapping.query({realm : realm.realm, userId : user.username});
@@ -26,13 +26,13 @@ module.controller('UserRoleMappingCtrl', function($scope, $http, realm, user, ap
                 $scope.realmComposite = CompositeRealmRoleMapping.query({realm : realm.realm, userId : user.username});
                 $scope.selectedRealmMappings = [];
                 $scope.selectRealmRoles = [];
-                if ($scope.application) {
+                if ($scope.client) {
                     console.log('load available');
-                    $scope.applicationComposite = CompositeApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id});
-                    $scope.applicationRoles = AvailableApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id});
-                    $scope.applicationMappings = ApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id});
-                    $scope.selectedApplicationRoles = [];
-                    $scope.selectedApplicationMappings = [];
+                    $scope.clientComposite = CompositeClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id});
+                    $scope.clientRoles = AvailableClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id});
+                    $scope.clientMappings = ClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id});
+                    $scope.selectedClientRoles = [];
+                    $scope.selectedClientMappings = [];
                 }
                 Notifications.success("Role mappings updated.");
 
@@ -47,57 +47,57 @@ module.controller('UserRoleMappingCtrl', function($scope, $http, realm, user, ap
                 $scope.realmComposite = CompositeRealmRoleMapping.query({realm : realm.realm, userId : user.username});
                 $scope.selectedRealmMappings = [];
                 $scope.selectRealmRoles = [];
-                if ($scope.application) {
+                if ($scope.client) {
                     console.log('load available');
-                    $scope.applicationComposite = CompositeApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id});
-                    $scope.applicationRoles = AvailableApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id});
-                    $scope.applicationMappings = ApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id});
-                    $scope.selectedApplicationRoles = [];
-                    $scope.selectedApplicationMappings = [];
+                    $scope.clientComposite = CompositeClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id});
+                    $scope.clientRoles = AvailableClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id});
+                    $scope.clientMappings = ClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id});
+                    $scope.selectedClientRoles = [];
+                    $scope.selectedClientMappings = [];
                 }
                 Notifications.success("Role mappings updated.");
             });
     };
 
-    $scope.addApplicationRole = function() {
-        $http.post(authUrl + '/admin/realms/' + realm.realm + '/users/' + user.username + '/role-mappings/applications-by-id/' + $scope.application.id,
-                $scope.selectedApplicationRoles).success(function() {
-                $scope.applicationMappings = ApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id});
-                $scope.applicationRoles = AvailableApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id});
-                $scope.applicationComposite = CompositeApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id});
-                $scope.selectedApplicationRoles = [];
-                $scope.selectedApplicationMappings = [];
+    $scope.addClientRole = function() {
+        $http.post(authUrl + '/admin/realms/' + realm.realm + '/users/' + user.username + '/role-mappings/clients-by-id/' + $scope.client.id,
+                $scope.selectedClientRoles).success(function() {
+                $scope.clientMappings = ClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id});
+                $scope.clientRoles = AvailableClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id});
+                $scope.clientComposite = CompositeClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id});
+                $scope.selectedClientRoles = [];
+                $scope.selectedClientMappings = [];
                 Notifications.success("Role mappings updated.");
             });
     };
 
-    $scope.deleteApplicationRole = function() {
-        $http.delete(authUrl + '/admin/realms/' + realm.realm + '/users/' + user.username + '/role-mappings/applications-by-id/' + $scope.application.id,
-            {data : $scope.selectedApplicationMappings, headers : {"content-type" : "application/json"}}).success(function() {
-                $scope.applicationMappings = ApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id});
-                $scope.applicationRoles = AvailableApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id});
-                $scope.applicationComposite = CompositeApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id});
-                $scope.selectedApplicationRoles = [];
-                $scope.selectedApplicationMappings = [];
+    $scope.deleteClientRole = function() {
+        $http.delete(authUrl + '/admin/realms/' + realm.realm + '/users/' + user.username + '/role-mappings/clients-by-id/' + $scope.client.id,
+            {data : $scope.selectedClientMappings, headers : {"content-type" : "application/json"}}).success(function() {
+                $scope.clientMappings = ClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id});
+                $scope.clientRoles = AvailableClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id});
+                $scope.clientComposite = CompositeClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id});
+                $scope.selectedClientRoles = [];
+                $scope.selectedClientMappings = [];
                 Notifications.success("Role mappings updated.");
             });
     };
 
 
-    $scope.changeApplication = function() {
-        console.log('changeApplication');
-        if ($scope.application) {
+    $scope.changeClient = function() {
+        console.log('changeClient');
+        if ($scope.client) {
             console.log('load available');
-            $scope.applicationComposite = CompositeApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id});
-            $scope.applicationRoles = AvailableApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id});
-            $scope.applicationMappings = ApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.id});
+            $scope.clientComposite = CompositeClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id});
+            $scope.clientRoles = AvailableClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id});
+            $scope.clientMappings = ClientRoleMapping.query({realm : realm.realm, userId : user.username, client : $scope.client.id});
         } else {
-            $scope.applicationRoles = null;
-            $scope.applicationMappings = null;
-            $scope.applicationComposite = null;
+            $scope.clientRoles = null;
+            $scope.clientMappings = null;
+            $scope.clientComposite = null;
         }
-        $scope.selectedApplicationRoles = [];
-        $scope.selectedApplicationMappings = [];
+        $scope.selectedClientRoles = [];
+        $scope.selectedClientMappings = [];
     };
 
 
@@ -111,7 +111,7 @@ module.controller('UserSessionsCtrl', function($scope, realm, user, sessions, Us
 
     $scope.logoutAll = function() {
         UserLogout.save({realm : realm.realm, user: user.username}, function () {
-            Notifications.success('Logged out user in all applications');
+            Notifications.success('Logged out user in all clients');
             UserSessions.query({realm: realm.realm, user: user.username}, function(updated) {
                 $scope.sessions = updated;
             })
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/loaders.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/loaders.js
index da6873d..b6e0541 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/loaders.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/loaders.js
@@ -71,35 +71,24 @@ module.factory('RealmSessionStatsLoader', function(Loader, RealmSessionStats, $r
     });
 });
 
-module.factory('RealmApplicationSessionStatsLoader', function(Loader, RealmApplicationSessionStats, $route, $q) {
-    return Loader.query(RealmApplicationSessionStats, function() {
+module.factory('RealmClientSessionStatsLoader', function(Loader, RealmClientSessionStats, $route, $q) {
+    return Loader.query(RealmClientSessionStats, function() {
         return {
             realm : $route.current.params.realm
         }
     });
 });
 
-module.factory('ApplicationProtocolMapperLoader', function(Loader, ApplicationProtocolMapper, $route, $q) {
-    return Loader.get(ApplicationProtocolMapper, function() {
+module.factory('ClientProtocolMapperLoader', function(Loader, ClientProtocolMapper, $route, $q) {
+    return Loader.get(ClientProtocolMapper, function() {
         return {
             realm : $route.current.params.realm,
-            application : $route.current.params.application,
+            client : $route.current.params.client,
             id: $route.current.params.id
         }
     });
 });
 
-module.factory('OAuthClientProtocolMapperLoader', function(Loader, OAuthClientProtocolMapper, $route, $q) {
-    return Loader.get(OAuthClientProtocolMapper, function() {
-        return {
-            realm : $route.current.params.realm,
-            oauth : $route.current.params.oauth,
-            id: $route.current.params.id
-        }
-    });
-});
-
-
 module.factory('UserLoader', function(Loader, User, $route, $q) {
     return Loader.get(User, function() {
         return {
@@ -175,74 +164,74 @@ module.factory('RoleListLoader', function(Loader, Role, $route, $q) {
     });
 });
 
-module.factory('ApplicationRoleLoader', function(Loader, RoleById, $route, $q) {
+module.factory('ClientRoleLoader', function(Loader, RoleById, $route, $q) {
     return Loader.get(RoleById, function() {
         return {
             realm : $route.current.params.realm,
-            application : $route.current.params.application,
+            client : $route.current.params.client,
             role : $route.current.params.role
         }
     });
 });
 
-module.factory('ApplicationSessionStatsLoader', function(Loader, ApplicationSessionStats, $route, $q) {
-    return Loader.get(ApplicationSessionStats, function() {
+module.factory('ClientSessionStatsLoader', function(Loader, ClientSessionStats, $route, $q) {
+    return Loader.get(ClientSessionStats, function() {
         return {
             realm : $route.current.params.realm,
-            application : $route.current.params.application
+            client : $route.current.params.client
         }
     });
 });
 
-module.factory('ApplicationSessionCountLoader', function(Loader, ApplicationSessionCount, $route, $q) {
-    return Loader.get(ApplicationSessionCount, function() {
+module.factory('ClientSessionCountLoader', function(Loader, ClientSessionCount, $route, $q) {
+    return Loader.get(ClientSessionCount, function() {
         return {
             realm : $route.current.params.realm,
-            application : $route.current.params.application
+            client : $route.current.params.client
         }
     });
 });
 
-module.factory('ApplicationClaimsLoader', function(Loader, ApplicationClaims, $route, $q) {
-    return Loader.get(ApplicationClaims, function() {
+module.factory('ClientClaimsLoader', function(Loader, ClientClaims, $route, $q) {
+    return Loader.get(ClientClaims, function() {
         return {
             realm : $route.current.params.realm,
-            application : $route.current.params.application
+            client : $route.current.params.client
         }
     });
 });
 
-module.factory('ApplicationInstallationLoader', function(Loader, ApplicationInstallation, $route, $q) {
-    return Loader.get(ApplicationInstallation, function() {
+module.factory('ClientInstallationLoader', function(Loader, ClientInstallation, $route, $q) {
+    return Loader.get(ClientInstallation, function() {
         return {
             realm : $route.current.params.realm,
-            application : $route.current.params.application
+            client : $route.current.params.client
         }
     });
 });
 
-module.factory('ApplicationRoleListLoader', function(Loader, ApplicationRole, $route, $q) {
-    return Loader.query(ApplicationRole, function() {
+module.factory('ClientRoleListLoader', function(Loader, ClientRole, $route, $q) {
+    return Loader.query(ClientRole, function() {
         return {
             realm : $route.current.params.realm,
-            application : $route.current.params.application
+            client : $route.current.params.client
         }
     });
 });
 
 
 
-module.factory('ApplicationLoader', function(Loader, Application, $route, $q) {
-    return Loader.get(Application, function() {
+module.factory('ClientLoader', function(Loader, Client, $route, $q) {
+    return Loader.get(Client, function() {
         return {
             realm : $route.current.params.realm,
-            application : $route.current.params.application
+            client : $route.current.params.client
         }
     });
 });
 
-module.factory('ApplicationListLoader', function(Loader, Application, $route, $q) {
-    return Loader.query(Application, function() {
+module.factory('ClientListLoader', function(Loader, Client, $route, $q) {
+    return Loader.query(Client, function() {
         return {
             realm : $route.current.params.realm
         }
@@ -251,7 +240,7 @@ module.factory('ApplicationListLoader', function(Loader, Application, $route, $q
 
 
 module.factory('RoleMappingLoader', function(Loader, RoleMapping, $route, $q) {
-	var realm = $route.current.params.realm || $route.current.params.application;
+	var realm = $route.current.params.realm || $route.current.params.client;
 
 	return Loader.query(RoleMapping, function() {
 		return {
@@ -261,42 +250,6 @@ module.factory('RoleMappingLoader', function(Loader, RoleMapping, $route, $q) {
 	});
 });
 
-module.factory('OAuthClientLoader', function(Loader, OAuthClient, $route, $q) {
-    return Loader.get(OAuthClient, function() {
-        return {
-            realm : $route.current.params.realm,
-            oauth : $route.current.params.oauth
-        }
-    });
-});
-
-module.factory('OAuthClientClaimsLoader', function(Loader, OAuthClientClaims, $route, $q) {
-    return Loader.get(OAuthClientClaims, function() {
-        return {
-            realm : $route.current.params.realm,
-            oauth : $route.current.params.oauth
-        }
-    });
-});
-
-
-module.factory('OAuthClientListLoader', function(Loader, OAuthClient, $route, $q) {
-    return Loader.query(OAuthClient, function() {
-        return {
-            realm : $route.current.params.realm
-        }
-    });
-});
-
-module.factory('OAuthClientInstallationLoader', function(Loader, OAuthClientInstallation, $route, $q) {
-    return Loader.get(OAuthClientInstallation, function() {
-        return {
-            realm : $route.current.params.realm,
-            oauth : $route.current.params.oauth
-        }
-    });
-});
-
 module.factory('IdentityProviderLoader', function(Loader, IdentityProvider, $route, $q) {
     return Loader.get(IdentityProvider, function () {
         return {
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js
index d783324..da0b2eb 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/services.js
@@ -190,10 +190,10 @@ module.factory('ServerInfo', function($resource) {
 
 
 
-module.factory('ApplicationProtocolMapper', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/protocol-mappers/models/:id', {
+module.factory('ClientProtocolMapper', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/protocol-mappers/models/:id', {
         realm : '@realm',
-        application: '@application',
+        client: '@client',
         id : "@id"
     }, {
         update : {
@@ -202,29 +202,6 @@ module.factory('ApplicationProtocolMapper', function($resource) {
     });
 });
 
-module.factory('OAuthClientProtocolMapper', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth/protocol-mappers/models/:id', {
-        realm : '@realm',
-        oauth: '@oauth',
-        id : "@id"
-    }, {
-        update : {
-            method : 'PUT'
-        }
-    });
-});
-
-module.factory('OAuthClientProtocolMappersByProtocol', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth/protocol-mappers/protocol/:protocol', {
-        realm : '@realm',
-        oauth : "@oauth",
-        protocol : "@protocol"
-    });
-});
-
-
-
-
 module.factory('User', function($resource) {
     return $resource(authUrl + '/admin/realms/:realm/users/:userId', {
         realm : '@realm',
@@ -347,72 +324,72 @@ module.factory('AvailableRealmRoleMapping', function($resource) {
 });
 
 
-module.factory('ApplicationRoleMapping', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/users/:userId/role-mappings/applications-by-id/:application', {
+module.factory('ClientRoleMapping', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/users/:userId/role-mappings/clients-by-id/:client', {
         realm : '@realm',
         userId : '@userId',
-        application : "@application"
+        client : "@client"
     });
 });
 
-module.factory('AvailableApplicationRoleMapping', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/users/:userId/role-mappings/applications-by-id/:application/available', {
+module.factory('AvailableClientRoleMapping', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/users/:userId/role-mappings/clients-by-id/:client/available', {
         realm : '@realm',
         userId : '@userId',
-        application : "@application"
+        client : "@client"
     });
 });
 
-module.factory('CompositeApplicationRoleMapping', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/users/:userId/role-mappings/applications-by-id/:application/composite', {
+module.factory('CompositeClientRoleMapping', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/users/:userId/role-mappings/clients-by-id/:client/composite', {
         realm : '@realm',
         userId : '@userId',
-        application : "@application"
+        client : "@client"
     });
 });
 
-module.factory('ApplicationRealmScopeMapping', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/scope-mappings/realm', {
+module.factory('ClientRealmScopeMapping', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/scope-mappings/realm', {
         realm : '@realm',
-        application : '@application'
+        client : '@client'
     });
 });
 
-module.factory('ApplicationAvailableRealmScopeMapping', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/scope-mappings/realm/available', {
+module.factory('ClientAvailableRealmScopeMapping', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/scope-mappings/realm/available', {
         realm : '@realm',
-        application : '@application'
+        client : '@client'
     });
 });
 
-module.factory('ApplicationCompositeRealmScopeMapping', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/scope-mappings/realm/composite', {
+module.factory('ClientCompositeRealmScopeMapping', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/scope-mappings/realm/composite', {
         realm : '@realm',
-        application : '@application'
+        client : '@client'
     });
 });
 
-module.factory('ApplicationApplicationScopeMapping', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/scope-mappings/applications-by-id/:targetApp', {
+module.factory('ClientClientScopeMapping', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/scope-mappings/clients-by-id/:targetClient', {
         realm : '@realm',
-        application : '@application',
-        targetApp : '@targetApp'
+        client : '@client',
+        targetClient : '@targetClient'
     });
 });
 
-module.factory('ApplicationAvailableApplicationScopeMapping', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/scope-mappings/applications-by-id/:targetApp/available', {
+module.factory('ClientAvailableClientScopeMapping', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/scope-mappings/clients-by-id/:targetClient/available', {
         realm : '@realm',
-        application : '@application',
-        targetApp : '@targetApp'
+        client : '@client',
+        targetClient : '@targetClient'
     });
 });
 
-module.factory('ApplicationCompositeApplicationScopeMapping', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/scope-mappings/applications-by-id/:targetApp/composite', {
+module.factory('ClientCompositeClientScopeMapping', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/scope-mappings/clients-by-id/:targetClient/composite', {
         realm : '@realm',
-        application : '@application',
-        targetApp : '@targetApp'
+        client : '@client',
+        targetClient : '@targetClient'
     });
 });
 
@@ -443,24 +420,24 @@ module.factory('RealmSessionStats', function($resource) {
     });
 });
 
-module.factory('RealmApplicationSessionStats', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/application-by-id-session-stats', {
+module.factory('RealmClientSessionStats', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/client-by-id-session-stats', {
         realm : '@realm'
     });
 });
 
 
-module.factory('RoleApplicationComposites', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/roles-by-id/:role/composites/applications-by-id/:application', {
+module.factory('RoleClientComposites', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/roles-by-id/:role/composites/clients-by-id/:client', {
         realm : '@realm',
         role : '@role',
-        application : "@application"
+        client : "@client"
     });
 });
 
 
-function roleControl($scope, realm, role, roles, applications,
-                     ApplicationRole, RoleById, RoleRealmComposites, RoleApplicationComposites,
+function roleControl($scope, realm, role, roles, clients,
+                     ClientRole, RoleById, RoleRealmComposites, RoleClientComposites,
                      $http, $location, Notifications, Dialog) {
 
     $scope.$watch(function () {
@@ -499,11 +476,11 @@ function roleControl($scope, realm, role, roles, applications,
     $scope.selectedRealmRoles = [];
     $scope.selectedRealmMappings = [];
     $scope.realmMappings = [];
-    $scope.applications = applications;
-    $scope.applicationRoles = [];
-    $scope.selectedApplicationRoles = [];
-    $scope.selectedApplicationMappings = [];
-    $scope.applicationMappings = [];
+    $scope.clients = clients;
+    $scope.clientRoles = [];
+    $scope.selectedClientRoles = [];
+    $scope.selectedClientMappings = [];
+    $scope.clientMappings = [];
 
     for (var j = 0; j < $scope.realmRoles.length; j++) {
         if ($scope.realmRoles[j].id == role.id) {
@@ -563,61 +540,61 @@ function roleControl($scope, realm, role, roles, applications,
             });
     };
 
-    $scope.addApplicationRole = function() {
+    $scope.addClientRole = function() {
         $scope.compositeSwitchDisabled=true;
         $http.post(authUrl + '/admin/realms/' + realm.realm + '/roles-by-id/' + role.id + '/composites',
-                $scope.selectedApplicationRoles).success(function() {
-                for (var i = 0; i < $scope.selectedApplicationRoles.length; i++) {
-                    var role = $scope.selectedApplicationRoles[i];
-                    var idx = $scope.applicationRoles.indexOf($scope.selectedApplicationRoles[i]);
+                $scope.selectedClientRoles).success(function() {
+                for (var i = 0; i < $scope.selectedClientRoles.length; i++) {
+                    var role = $scope.selectedClientRoles[i];
+                    var idx = $scope.clientRoles.indexOf($scope.selectedClientRoles[i]);
                     if (idx != -1) {
-                        $scope.applicationRoles.splice(idx, 1);
-                        $scope.applicationMappings.push(role);
+                        $scope.clientRoles.splice(idx, 1);
+                        $scope.clientMappings.push(role);
                     }
                 }
-                $scope.selectedApplicationRoles = [];
+                $scope.selectedClientRoles = [];
             });
     };
 
-    $scope.deleteApplicationRole = function() {
+    $scope.deleteClientRole = function() {
         $scope.compositeSwitchDisabled=true;
         $http.delete(authUrl + '/admin/realms/' + realm.realm + '/roles-by-id/' + role.id + '/composites',
-            {data : $scope.selectedApplicationMappings, headers : {"content-type" : "application/json"}}).success(function() {
-                for (var i = 0; i < $scope.selectedApplicationMappings.length; i++) {
-                    var role = $scope.selectedApplicationMappings[i];
-                    var idx = $scope.applicationMappings.indexOf($scope.selectedApplicationMappings[i]);
+            {data : $scope.selectedClientMappings, headers : {"content-type" : "application/json"}}).success(function() {
+                for (var i = 0; i < $scope.selectedClientMappings.length; i++) {
+                    var role = $scope.selectedClientMappings[i];
+                    var idx = $scope.clientMappings.indexOf($scope.selectedClientMappings[i]);
                     if (idx != -1) {
-                        $scope.applicationMappings.splice(idx, 1);
-                        $scope.applicationRoles.push(role);
+                        $scope.clientMappings.splice(idx, 1);
+                        $scope.clientRoles.push(role);
                     }
                 }
-                $scope.selectedApplicationMappings = [];
+                $scope.selectedClientMappings = [];
             });
     };
 
 
-    $scope.changeApplication = function() {
-        $scope.applicationRoles = ApplicationRole.query({realm : realm.realm, application : $scope.compositeApp.id}, function() {
-                $scope.applicationMappings = RoleApplicationComposites.query({realm : realm.realm, role : role.id, application : $scope.compositeApp.id}, function(){
-                    for (var i = 0; i < $scope.applicationMappings.length; i++) {
-                        var role = $scope.applicationMappings[i];
-                        for (var j = 0; j < $scope.applicationRoles.length; j++) {
-                            var realmRole = $scope.applicationRoles[j];
+    $scope.changeClient = function() {
+        $scope.clientRoles = ClientRole.query({realm : realm.realm, client : $scope.compositeClient.id}, function() {
+                $scope.clientMappings = RoleClientComposites.query({realm : realm.realm, role : role.id, client : $scope.compositeClient.id}, function(){
+                    for (var i = 0; i < $scope.clientMappings.length; i++) {
+                        var role = $scope.clientMappings[i];
+                        for (var j = 0; j < $scope.clientRoles.length; j++) {
+                            var realmRole = $scope.clientRoles[j];
                             if (realmRole.id == role.id) {
-                                var idx = $scope.applicationRoles.indexOf(realmRole);
+                                var idx = $scope.clientRoles.indexOf(realmRole);
                                 if (idx != -1) {
-                                    $scope.applicationRoles.splice(idx, 1);
+                                    $scope.clientRoles.splice(idx, 1);
                                     break;
                                 }
                             }
                         }
                     }
                 });
-                for (var j = 0; j < $scope.applicationRoles.length; j++) {
-                    if ($scope.applicationRoles[j] == role.id) {
-                        var appRole = $scope.applicationRoles[j];
-                        var idx = $scope.applicationRoles.indexof(appRole);
-                        $scope.applicationRoles.splice(idx, 1);
+                for (var j = 0; j < $scope.clientRoles.length; j++) {
+                    if ($scope.clientRoles[j] == role.id) {
+                        var appRole = $scope.clientRoles[j];
+                        var idx = $scope.clientRoles.indexof(appRole);
+                        $scope.clientRoles.splice(idx, 1);
                         break;
                     }
                 }
@@ -653,10 +630,10 @@ module.factory('RoleById', function($resource) {
     });
 });
 
-module.factory('ApplicationRole', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/roles/:role', {
+module.factory('ClientRole', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/roles/:role', {
         realm : '@realm',
-        application : "@application",
+        client : "@client",
         role : '@role'
     },  {
         update : {
@@ -665,10 +642,10 @@ module.factory('ApplicationRole', function($resource) {
     });
 });
 
-module.factory('ApplicationClaims', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/claims', {
+module.factory('ClientClaims', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/claims', {
         realm : '@realm',
-        application : "@application"
+        client : "@client"
     },  {
         update : {
             method : 'PUT'
@@ -676,52 +653,52 @@ module.factory('ApplicationClaims', function($resource) {
     });
 });
 
-module.factory('ApplicationProtocolMappersByProtocol', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/protocol-mappers/protocol/:protocol', {
+module.factory('ClientProtocolMappersByProtocol', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/protocol-mappers/protocol/:protocol', {
         realm : '@realm',
-        application : "@application",
+        client : "@client",
         protocol : "@protocol"
     });
 });
 
-module.factory('ApplicationSessionStats', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/session-stats', {
+module.factory('ClientSessionStats', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/session-stats', {
         realm : '@realm',
-        application : "@application"
+        client : "@client"
     });
 });
 
-module.factory('ApplicationSessionStatsWithUsers', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/session-stats?users=true', {
+module.factory('ClientSessionStatsWithUsers', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/session-stats?users=true', {
         realm : '@realm',
-        application : "@application"
+        client : "@client"
     });
 });
 
-module.factory('ApplicationSessionCount', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/session-count', {
+module.factory('ClientSessionCount', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/session-count', {
         realm : '@realm',
-        application : "@application"
+        client : "@client"
     });
 });
 
-module.factory('ApplicationUserSessions', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/user-sessions', {
+module.factory('ClientUserSessions', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/user-sessions', {
         realm : '@realm',
-        application : "@application"
+        client : "@client"
     });
 });
 
-module.factory('ApplicationLogoutAll', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/logout-all', {
+module.factory('ClientLogoutAll', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/logout-all', {
         realm : '@realm',
-        application : "@application"
+        client : "@client"
     });
 });
-module.factory('ApplicationLogoutUser', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/logout-user/:user', {
+module.factory('ClientLogoutUser', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/logout-user/:user', {
         realm : '@realm',
-        application : "@application",
+        client : "@client",
         user : "@user"
     });
 });
@@ -731,39 +708,39 @@ module.factory('RealmLogoutAll', function($resource) {
     });
 });
 
-module.factory('ApplicationPushRevocation', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/push-revocation', {
+module.factory('ClientPushRevocation', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/push-revocation', {
         realm : '@realm',
-        application : "@application"
+        client : "@client"
     });
 });
 
-module.factory('ApplicationClusterNode', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/nodes/:node', {
+module.factory('ClientClusterNode', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/nodes/:node', {
         realm : '@realm',
-        application : "@application"
+        client : "@client"
     });
 });
 
-module.factory('ApplicationTestNodesAvailable', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/test-nodes-available', {
+module.factory('ClientTestNodesAvailable', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/test-nodes-available', {
         realm : '@realm',
-        application : "@application"
+        client : "@client"
     });
 });
 
-module.factory('ApplicationCertificate', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/certificates/:attribute', {
+module.factory('ClientCertificate', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/certificates/:attribute', {
             realm : '@realm',
-            application : "@application",
+            client : "@client",
             attribute: "@attribute"
         });
 });
 
-module.factory('ApplicationCertificateGenerate', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/certificates/:attribute/generate', {
+module.factory('ClientCertificateGenerate', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/certificates/:attribute/generate', {
             realm : '@realm',
-            application : "@application",
+            client : "@client",
             attribute: "@attribute"
         },
         {
@@ -773,10 +750,10 @@ module.factory('ApplicationCertificateGenerate', function($resource) {
         });
 });
 
-module.factory('ApplicationCertificateDownload', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/certificates/:attribute/download', {
+module.factory('ClientCertificateDownload', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/certificates/:attribute/download', {
         realm : '@realm',
-        application : "@application",
+        client : "@client",
         attribute: "@attribute"
     },
         {
@@ -787,10 +764,10 @@ module.factory('ApplicationCertificateDownload', function($resource) {
         });
 });
 
-module.factory('Application', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application', {
+module.factory('Client', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client', {
         realm : '@realm',
-        application : '@application'
+        client : '@client'
     },  {
         update : {
             method : 'PUT'
@@ -798,29 +775,29 @@ module.factory('Application', function($resource) {
     });
 });
 
-module.factory('ApplicationInstallation', function($resource) {
-    var url = authUrl + '/admin/realms/:realm/applications-by-id/:application/installation/json';
+module.factory('ClientInstallation', function($resource) {
+    var url = authUrl + '/admin/realms/:realm/clients-by-id/:client/installation/json';
     return {
         url : function(parameters)
         {
-            return url.replace(':realm', parameters.realm).replace(':application', parameters.application);
+            return url.replace(':realm', parameters.realm).replace(':client', parameters.client);
         }
     }
 });
-module.factory('ApplicationInstallationJBoss', function($resource) {
-    var url = authUrl + '/admin/realms/:realm/applications-by-id/:application/installation/jboss';
+module.factory('ClientInstallationJBoss', function($resource) {
+    var url = authUrl + '/admin/realms/:realm/clients-by-id/:client/installation/jboss';
     return {
         url : function(parameters)
      {
-        return url.replace(':realm', parameters.realm).replace(':application', parameters.application);
+        return url.replace(':realm', parameters.realm).replace(':client', parameters.client);
     }
     }
 });
 
-module.factory('ApplicationCredentials', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/client-secret', {
+module.factory('ClientCredentials', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/client-secret', {
         realm : '@realm',
-        application : '@application'
+        client : '@client'
     },  {
         update : {
             method : 'POST'
@@ -828,10 +805,10 @@ module.factory('ApplicationCredentials', function($resource) {
     });
 });
 
-module.factory('ApplicationOrigins', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/applications-by-id/:application/allowed-origins', {
+module.factory('ClientOrigins', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/clients-by-id/:client/allowed-origins', {
         realm : '@realm',
-        application : '@application'
+        client : '@client'
     },  {
         update : {
             method : 'PUT',
@@ -840,127 +817,13 @@ module.factory('ApplicationOrigins', function($resource) {
     });
 });
 
-module.factory('OAuthClient', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth', {
-        realm : '@realm',
-        oauth : '@oauth'
-    },  {
-        update : {
-            method : 'PUT'
-        }
-    });
-});
-
-module.factory('OAuthClientClaims', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth/claims', {
-        realm : '@realm',
-        oauth : "@oauth"
-    },  {
-        update : {
-            method : 'PUT'
-        }
-    });
-});
-
-
-module.factory('OAuthClientCredentials', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth/client-secret', {
-        realm : '@realm',
-        oauth : '@oauth'
-    },  {
-        update : {
-            method : 'POST'
-        }
-    });
-
-});
-
-module.factory('OAuthCertificate', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth/certificates', {
-        realm : '@realm',
-        oauth : '@oauth'
-    });
-});
-
-module.factory('OAuthCertificateDownload', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth/certificates/download', {
-        realm : '@realm',
-        oauth : '@oauth'
-    });
-});
-
-
-module.factory('OAuthClientRealmScopeMapping', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth/scope-mappings/realm', {
-        realm : '@realm',
-        oauth : '@oauth'
-    });
-});
-
-module.factory('OAuthClientCompositeRealmScopeMapping', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth/scope-mappings/realm/composite', {
-        realm : '@realm',
-        oauth : '@oauth'
-    });
-});
-
-module.factory('OAuthClientAvailableRealmScopeMapping', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth/scope-mappings/realm/available', {
-        realm : '@realm',
-        oauth : '@oauth'
-    });
-});
-
-module.factory('OAuthClientApplicationScopeMapping', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth/scope-mappings/applications-by-id/:targetApp', {
-        realm : '@realm',
-        oauth : '@oauth',
-        targetApp : '@targetApp'
-    });
-});
-
-module.factory('OAuthClientCompositeApplicationScopeMapping', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth/scope-mappings/applications-by-id/:targetApp/composite', {
-        realm : '@realm',
-        oauth : '@oauth',
-        targetApp : '@targetApp'
-    });
-});
-
-module.factory('OAuthClientAvailableApplicationScopeMapping', function($resource) {
-    return $resource(authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth/scope-mappings/applications-by-id/:targetApp/available', {
-        realm : '@realm',
-        oauth : '@oauth',
-        targetApp : '@targetApp'
-    });
-});
-
-
-
-module.factory('OAuthClientInstallation', function($resource) {
-    var url = authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth/installation';
-    var resource = $resource(authUrl + '/admin/realms/:realm/oauth-clients-by-id/:oauth/installation', {
-        realm : '@realm',
-        oauth : '@oauth'
-    },  {
-        update : {
-            method : 'PUT'
-        }
-    });
-    resource.url = function(parameters) {
-        return url.replace(':realm', parameters.realm).replace(':oauth', parameters.oauth);
-    }
-    return resource;
-});
-
-
 module.factory('Current', function(Realm, $route) {
     var current = {};
 
     current.realms = {};
     current.realm = null;
-    current.applications = {};
-    current.application = null;
+    current.clients = {};
+    current.client = null;
 
     current.refresh = function() {
         current.realm = null;
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/protocol-mapper-detail.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/protocol-mapper-detail.html
index aed7f50..03a52bb 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/protocol-mapper-detail.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/protocol-mapper-detail.html
@@ -1,18 +1,18 @@
 <div class="bs-sidebar col-sm-3 " data-ng-include data-src="resourceUrl + '/partials/realm-menu.html'"></div>
 <div id="content-area" class="col-sm-9" role="main">
-    <kc-navigation-application></kc-navigation-application>
+    <kc-navigation-client></kc-navigation-client>
     <div id="content">
         <ol class="breadcrumb" data-ng-show="create">
-            <li><a href="#/realms/{{realm.realm}}/applications">Applications</a></li>
-            <li><a href="#/realms/{{realm.realm}}/applications/{{application.id}}">{{application.name}}</a></li>
-            <li><a href="#/realms/{{realm.realm}}/applications/{{application.id}}/mappers">Protocol Mappers</a></li>
+            <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
+            <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></li>
+            <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/mappers">Protocol Mappers</a></li>
             <li class="active">Create Protocol Mapper</li>
         </ol>
 
         <ol class="breadcrumb" data-ng-hide="create">
-            <li><a href="#/realms/{{realm.realm}}/applications">Applications</a></li>
-            <li><a href="#/realms/{{realm.realm}}/applications/{{application.id}}">{{application.name}}</a></li>
-            <li><a href="#/realms/{{realm.realm}}/applications/{{application.id}}/mappers">Protocol Mappers</a></li>
+            <li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
+            <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></li>
+            <li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/mappers">Protocol Mappers</a></li>
             <li class="active">{{mapper.name}}</li>
         </ol>
         <h2 class="pull-left" data-ng-hide="create">{{mapper.name}} Protocol Mapper</h2>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-cache-settings.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-cache-settings.html
index 2567173..e4a134c 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-cache-settings.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-cache-settings.html
@@ -12,7 +12,7 @@
                         <div class="col-sm-4">
                             <input ng-model="realm.realmCacheEnabled" name="realmCacheEnabled" id="realmCacheEnabled" onoffswitch />
                         </div>
-                         <span tooltip-placement="right" tooltip="Enable/disable cache for realm, application, oauth client, and role data." class="fa fa-info-circle"></span>
+                         <span tooltip-placement="right" tooltip="Enable/disable cache for realm, client and role data." class="fa fa-info-circle"></span>
                      </div>
                     <div class="form-group">
                         <label class="col-sm-2 control-label" for="userCacheEnabled">User Cache Enabled</label>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-default-roles.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-default-roles.html
index d2207f7..f03349e 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-default-roles.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-default-roles.html
@@ -40,45 +40,45 @@
                 </div>
             </fieldset>
 
-            <fieldset ng-show="applications.length > 0">
-                <legend><span class="text">Application Default Roles</span> </legend>
+            <fieldset ng-show="clients.length > 0">
+                <legend><span class="text">Client Default Roles</span> </legend>
                 <div class="form-group input-select">
-                    <label class="col-sm-2 control-label" for="applications">Application <span tooltip-placement="top" tooltip="Select an application to view/modify assigned default roles." class="fa fa-info-circle"></span></label>
+                    <label class="col-sm-2 control-label" for="clients">Client <span tooltip-placement="top" tooltip="Select an client to view/modify assigned default roles." class="fa fa-info-circle"></span></label>
                     <div class="col-sm-4">
                         <div class="input-group">
                             <div class="select-kc">
-                                <select id="applications" name="applications" ng-change="changeApplication()" ng-model="application" ng-options="a.name for a in applications" ng-disabled="false">
-                                    <option value="" selected> Select an Application...</option>
+                                <select id="clients" name="clients" ng-change="changeClient()" ng-model="client" ng-options="a.clientId for a in clients" ng-disabled="false">
+                                    <option value="" selected> Select a Client...</option>
                                 </select>
                             </div>
                         </div>
                     </div>
 
                 </div>
-                <div class="form-group" ng-show="application">
+                <div class="form-group" ng-show="client">
                     <div class="controls changing-selectors col-sm-10">
                         <div class="select-title">
-                            <label class="control-label" for="available-app">Available Roles <span tooltip-placement="right" tooltip="Roles from this application that are assignable as a default." class="fa fa-info-circle"></span></label>
-                            <select id="available-app" class="form-control" multiple size="5"
+                            <label class="control-label" for="available-client">Available Roles <span tooltip-placement="right" tooltip="Roles from this client that are assignable as a default." class="fa fa-info-circle"></span></label>
+                            <select id="available-client" class="form-control" multiple size="5"
                                     ng-multiple="true"
-                                    ng-model="selectedAppRoles"
-                                    ng-options="r for r in availableAppRoles">
+                                    ng-model="selectedClientRoles"
+                                    ng-options="r for r in availableClientRoles">
                             </select>
                         </div>
                         <div class="middle-buttons">
-                            <button class="btn btn-default" type="submit" ng-click="addAppDefaultRole()" tooltip="Assign role" tooltip-placement="right">
+                            <button class="btn btn-default" type="submit" ng-click="addClientDefaultRole()" tooltip="Assign role" tooltip-placement="right">
                                 <span class="kc-icon-arrow-right"><span>Move right</span></span>
                             </button>
-                            <button class="btn btn-default" type="submit" ng-click="rmAppDefaultRole()" tooltip="Unassign role" tooltip-placement="left">
+                            <button class="btn btn-default" type="submit" ng-click="rmClientDefaultRole()" tooltip="Unassign role" tooltip-placement="left">
                                 <span class="kc-icon-arrow-left"><span>Move left</span></span>
                             </button>
                         </div>
                         <div class="select-title">
-                            <label class="control-label" for="assigned-app">Application Default Roles <span tooltip-placement="right" tooltip="Roles from this application assigned as a default role." class="fa fa-info-circle"></span></label>
-                            <select id="assigned-app" class="form-control" multiple size=5
+                            <label class="control-label" for="assigned-client">Client Default Roles <span tooltip-placement="right" tooltip="Roles from this client assigned as a default role." class="fa fa-info-circle"></span></label>
+                            <select id="assigned-client" class="form-control" multiple size=5
                                     ng-multiple="true"
-                                    ng-model="selectedAppDefRoles"
-                                    ng-options="r for r in application.defaultRoles">
+                                    ng-model="selectedClientDefRoles"
+                                    ng-options="r for r in client.defaultRoles">
                             </select>
                         </div>
                     </div>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-detail.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-detail.html
index 80f8e13..ae5b53a 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-detail.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-detail.html
@@ -17,7 +17,7 @@
                     </div>
                     <div class="form-group">
                         <label class="col-sm-2 control-label" for="enabled">Enabled</label>
-                        <span tooltip="Users and applications can only access a realm if it's enabled" class="fa fa-info-circle"></span>
+                        <span tooltip="Users and clients can only access a realm if it's enabled" class="fa fa-info-circle"></span>
                         <div class="col-sm-4">
                             <input ng-model="realm.enabled" name="enabled" id="enabled" onoffswitch />
                         </div>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider.html
index 1c0ed54..778bb2c 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider.html
@@ -12,7 +12,7 @@
                         <caption class="hidden">Table of identity providers</caption>
                         <thead>
                         <tr>
-                            <th colspan="5" class="kc-table-actions">
+                            <th colspan="3" class="kc-table-actions">
                                 <div class="pull-right">
                                     <div class="select-kc">
                                         <select ng-model="provider"
@@ -27,6 +27,7 @@
                         <tr ng-show="configuredProviders.length > 0">
                             <th>Name</th>
                             <th>Provider</th>
+                            <th width="15%">GUI order</th>
                         </tr>
                         </thead>
                         <tbody ng-show="configuredProviders.length > 0">
@@ -35,6 +36,7 @@
                                 <a href="#/realms/{{realm.realm}}/identity-provider-settings/provider/{{identityProvider.providerId}}/{{identityProvider.alias}}">{{identityProvider.alias}}</a>
                             </td>
                             <td>{{identityProvider.providerId}}</td>
+                            <td>{{identityProvider.config.guiOrder}}</td>
                         </tr>
                         </tbody>
                     </table>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html
index 7bf4035..67b0a68 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html
@@ -55,6 +55,13 @@
                         </div>
                         <span tooltip-placement="right" tooltip="Indicates if user must update his profile right after the first login." class="fa fa-info-circle"></span>
                     </div>
+                    <div class="form-group">
+                        <label class="col-sm-2 control-label" for="guiOrder">GUI order</label>
+                        <div class="col-sm-4">
+                            <input class="form-control" id="guiOrder" type="text" ng-model="identityProvider.config.guiOrder">
+                        </div>
+                        <span tooltip-placement="right" tooltip="Number defining order of the provider in GUI (eg. on Login page)." class="fa fa-info-circle"></span>
+                    </div>
                 </fieldset>
                 <fieldset>
                     <legend uncollapsed><span class="text">OpenID Connect Config</span> <span tooltip-placement="right" tooltip="OIDC SP and external IDP configuration." class="fa fa-info-circle"></span></legend>
@@ -91,7 +98,7 @@
                         <div class="col-sm-4">
                             <input class="form-control" id="clientId" type="text" ng-model="identityProvider.config.clientId" required>
                         </div>
-                        <span tooltip-placement="right" tooltip="The client or application identifier registered withing the identity provider." class="fa fa-info-circle"></span>
+                        <span tooltip-placement="right" tooltip="The client or client identifier registered withing the identity provider." class="fa fa-info-circle"></span>
                     </div>
                     <div class="form-group clearfix">
                         <label class="col-sm-2 control-label" for="clientSecret">Client Secret <span class="required">*</span></label>
@@ -101,7 +108,7 @@
                             <a href="" ng-click="showPassword(false)" class="link" ng-show="hidePassword">Show Secret</a>
                             <a href="" ng-click="showPassword(true);" ng-show="!hidePassword">Hide Secret</a>
                         </div>
-                        <span tooltip-placement="right" tooltip="The client or application secret registered withing the identity provider." class="fa fa-info-circle"></span>
+                        <span tooltip-placement="right" tooltip="The client or client secret registered withing the identity provider." class="fa fa-info-circle"></span>
                     </div>
                     <div class="form-group clearfix">
                         <label class="col-sm-2 control-label" for="issuer">Issuer </label>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html
index 10327e6..3e151fd 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html
@@ -55,6 +55,13 @@
                         </div>
                         <span tooltip-placement="right" tooltip="Indicates if user must update his profile right after the first login." class="fa fa-info-circle"></span>
                     </div>
+                    <div class="form-group">
+                        <label class="col-sm-2 control-label" for="guiOrder">GUI order</label>
+                        <div class="col-sm-4">
+                            <input class="form-control" id="guiOrder" type="text" ng-model="identityProvider.config.guiOrder">
+                        </div>
+                        <span tooltip-placement="right" tooltip="Number defining order of the provider in GUI (eg. on Login page)." class="fa fa-info-circle"></span>
+                    </div>
                 </fieldset>
                 <fieldset>
                     <legend uncollapsed><span class="text">SAML Config</span> <span tooltip-placement="right" tooltip="SAML SP and external IDP configuration." class="fa fa-info-circle"></span></legend>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html
index 0a8b56a..dd07093 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html
@@ -25,7 +25,7 @@
                         <div class="col-sm-4">
                             <input class="form-control" id="clientId" type="text" ng-model="identityProvider.config.clientId" required>
                         </div>
-                        <span tooltip-placement="right" tooltip="The client or application identifier registered withing the identity provider." class="fa fa-info-circle"></span>
+                        <span tooltip-placement="right" tooltip="The client identifier registered withing the identity provider." class="fa fa-info-circle"></span>
                     </div>
                     <div class="form-group clearfix">
                         <label class="col-sm-2 control-label" for="clientSecret">Client Secret <span class="required">*</span></label>
@@ -35,7 +35,7 @@
                             <a href="" ng-click="showPassword(false)" class="link" ng-show="hidePassword">Show Secret</a>
                             <a href="" ng-click="showPassword(true);" ng-show="!hidePassword">Hide Secret</a>
                         </div>
-                        <span tooltip-placement="right" tooltip="The client or application secret registered withing the identity provider." class="fa fa-info-circle"></span>
+                        <span tooltip-placement="right" tooltip="The client secret registered withing the identity provider." class="fa fa-info-circle"></span>
                     </div>
                     <div data-ng-include data-src="resourceUrl + '/partials/realm-identity-provider-' + identityProvider.providerId + '-ext.html'"></div>
                     <div class="form-group clearfix">
@@ -73,6 +73,13 @@
                         </div>
                         <span tooltip-placement="right" tooltip="Indicates if this provider should be tried by default for authentication even before displaying login screen" class="fa fa-info-circle"></span>
                     </div>
+                    <div class="form-group">
+                        <label class="col-sm-2 control-label" for="guiOrder">GUI order</label>
+                        <div class="col-sm-4">
+                            <input class="form-control" id="guiOrder" type="text" ng-model="identityProvider.config.guiOrder">
+                        </div>
+                        <span tooltip-placement="right" tooltip="Number defining order of the provider in GUI (eg. on Login page)." class="fa fa-info-circle"></span>
+                    </div>
                 </fieldset>
 
                 <div class="pull-right form-actions">
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-stackoverflow-ext.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-stackoverflow-ext.html
index 86516df..07a0e60 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-stackoverflow-ext.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-stackoverflow-ext.html
@@ -3,5 +3,5 @@
                         <div class="col-sm-4">
                             <input class="form-control" id="clientId" type="text" ng-model="identityProvider.config.key" required>
                         </div>
-                        <span tooltip-placement="right" tooltip="The Key obtained from Stack Overflow application registration." class="fa fa-info-circle"></span>
+                        <span tooltip-placement="right" tooltip="The Key obtained from Stack Overflow client registration." class="fa fa-info-circle"></span>
                     </div>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-menu.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-menu.html
index 098f317..4c60b02 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-menu.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-menu.html
@@ -4,15 +4,12 @@
     || path[2] == 'login-settings'
     || path[2] == 'theme-settings'
     || path[2] == 'cache-settings'
-    || path[2] == 'keys-settings' || path[2] == 'smtp-settings' || path[2] == 'ldap-settings' || path[2] == 'auth-settings') && path[3] != 'applications') && 'active'">
+    || path[2] == 'keys-settings' || path[2] == 'smtp-settings' || path[2] == 'ldap-settings' || path[2] == 'auth-settings') && path[3] != 'clients') && 'active'">
         <a href="#/realms/{{realm.realm}}">Settings</a>
     </li>
-    <li data-ng-show="access.viewUsers" data-ng-class="(path[2] == 'users' || path[1] == 'user') && 'active'"><a href="#/realms/{{realm.realm}}/users">Users</a>
-    </li>
-    <li data-ng-show="access.viewRealm" data-ng-class="(path[2] == 'roles' || (path[1] == 'role' && path[3] != 'applications')) && 'active'"><a href="#/realms/{{realm.realm}}/roles">Roles</a>
-    </li>
-    <li data-ng-show="access.viewApplications" data-ng-class="(path[2] == 'applications' || path[1] == 'application' || path[3] == 'applications') && 'active'"><a href="#/realms/{{realm.realm}}/applications">Applications</a></li>
-    <li data-ng-show="access.viewClients" data-ng-class="(path[2] == 'oauth-clients' || path[1] == 'oauth-client') && 'active'"><a href="#/realms/{{realm.realm}}/oauth-clients">OAuth Clients</a></li>
+    <li data-ng-show="access.viewUsers" data-ng-class="(path[2] == 'users' || path[1] == 'user') && 'active'"><a href="#/realms/{{realm.realm}}/users">Users</a></li>
+    <li data-ng-show="access.viewClients" data-ng-class="(path[2] == 'clients' || path[1] == 'client' || path[3] == 'clients') && 'active'"><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
+    <li data-ng-show="access.viewRealm" data-ng-class="(path[2] == 'roles' || (path[1] == 'role' && path[3] != 'clients')) && 'active'"><a href="#/realms/{{realm.realm}}/roles">Roles</a></li>
     <li data-ng-show="access.viewRealm" data-ng-class="(path[2] == 'sessions' || path[2] == 'token-settings') && 'active'"><a href="#/realms/{{realm.realm}}/sessions/realm">Sessions and Tokens</a></li>
     <li data-ng-show="access.viewRealm" data-ng-class="(path[2] == 'defense') && 'active'"><a href="#/realms/{{realm.realm}}/defense/headers">Security Defenses</a></li>
     <li data-ng-show="access.viewEvents" data-ng-class="(path[2] == 'events' || path[2] == 'events-settings') && 'active'"><a href="#/realms/{{realm.realm}}/events">Events</a></li>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-theme-settings.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-theme-settings.html
index 741b787..5701e48 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-theme-settings.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-theme-settings.html
@@ -18,7 +18,7 @@
                                 </select>
                             </div>
                         </div>
-                        <span tooltip-placement="right" tooltip="Select theme for login, totp, grant, registrationn, and forgot password pages." class="fa fa-info-circle"></span>
+                        <span tooltip-placement="right" tooltip="Select theme for login, TOTP, grant, registration, and forgot password pages." class="fa fa-info-circle"></span>
                     </div>
                     <div class="form-group">
                         <label class="col-sm-2 control-label" for="accountTheme">Account Theme</label>
@@ -98,4 +98,4 @@
         </div>
 
     </div>
-</div>
\ No newline at end of file
+</div>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-tokens.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-tokens.html
index 2f30127..eb519ee 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-tokens.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-tokens.html
@@ -90,8 +90,7 @@
                             </div>
                         </div>
                     </div>
-                    <span tooltip-placement="right" tooltip="Max time an application or oauth client has to finish the access token protocol.  This should normally be 1 minute." class="fa fa-info-circle"></span>
-                </div>
+                    <span tooltip-placement="right" tooltip="Max time an client has to finish the access token protocol.  This should normally be 1 minute." class="fa fa-info-circle"></span>                </div>
                 <div class="form-group input-select">
                     <label class="col-sm-2 control-label" for="accessCodeLifespanLogin" class="two-lines">Login lifespan</label>
                     <div class="col-sm-5">
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-detail.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-detail.html
index d5be190..412c8a0 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-detail.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-detail.html
@@ -74,45 +74,45 @@
                 </div>
             </fieldset>
 
-            <fieldset ng-show="applications.length > 0 && !create && (compositeSwitch || role.composite)">
-                <legend uncollapsed class="collapsible"><span class="text">Composite Application Roles</span> </legend>
+            <fieldset ng-show="clients.length > 0 && !create && (compositeSwitch || role.composite)">
+                <legend uncollapsed class="collapsible"><span class="text">Composite Client Roles</span> </legend>
                 <div class="form-group input-select">
-                    <label class="col-sm-2 control-label" for="applications">Application <span tooltip-placement="right" tooltip="Select an application to view/modify roles associated with this composite." class="fa fa-info-circle"></span>
+                    <label class="col-sm-2 control-label" for="clients">Client <span tooltip-placement="right" tooltip="Select a client to view/modify roles associated with this composite." class="fa fa-info-circle"></span>
                     </label>
                     <div class="col-sm-4">
                         <div class="input-group">
                             <div class="select-kc">
-                                <select id="applications" name="applications" ng-change="changeApplication()" ng-model="compositeApp" ng-options="a.name for a in applications" ng-disabled="false">
-                                    <option value="" selected> Select an Application...</option>
+                                <select id="clients" name="clients" ng-change="changeClient()" ng-model="compositeClient" ng-options="a.clientId for a in clients" ng-disabled="false">
+                                    <option value="" selected> Select a Client...</option>
                                 </select>
                             </div>
                         </div>
                      </div>
                 </div>
-                <div class="form-group" ng-show="compositeApp">
+                <div class="form-group" ng-show="compositeClient">
                     <div class="controls changing-selectors col-sm-10">
                         <div class="select-title">
-                            <label class="control-label" for="available-app">Available Roles <span tooltip-placement="right" tooltip="Roles from this application that you can associate to this composite role." class="fa fa-info-circle"></span></label>
-                            <select id="available-app" class="form-control" multiple size="5"
+                            <label class="control-label" for="available-client">Available Roles <span tooltip-placement="right" tooltip="Roles from this client that you can associate to this composite role." class="fa fa-info-circle"></span></label>
+                            <select id="available-client" class="form-control" multiple size="5"
                                     ng-multiple="true"
-                                    ng-model="selectedApplicationRoles"
-                                    ng-options="r.name for r in applicationRoles">
+                                    ng-model="selectedClientRoles"
+                                    ng-options="r.name for r in clientRoles">
                             </select>
                         </div>
                         <div class="middle-buttons kc-vertical">
-                            <button class="btn btn-default" type="submit" ng-click="addApplicationRole()" tooltip="Associate role" tooltip-placement="right">
+                            <button class="btn btn-default" type="submit" ng-click="addClientRole()" tooltip="Associate role" tooltip-placement="right">
                                 <span class="kc-icon-arrow-right">Move right</span>
                             </button>
-                            <button class="btn btn-default" type="submit" ng-click="deleteApplicationRole()" tooltip="Disassociate role" tooltip-placement="left">
+                            <button class="btn btn-default" type="submit" ng-click="deleteClientRole()" tooltip="Disassociate role" tooltip-placement="left">
                                 <span class="kc-icon-arrow-left">Move left</span>
                             </button>
                         </div>
                         <div class="select-title">
-                            <label class="control-label" for="assigned-app">Associated Roles <span tooltip-placement="right" tooltip="Application roles associated with this composite role." class="fa fa-info-circle"></span></label>
-                            <select id="assigned-app" class="form-control" multiple size=5
+                            <label class="control-label" for="assigned-client">Associated Roles <span tooltip-placement="right" tooltip="Client roles associated with this composite role." class="fa fa-info-circle"></span></label>
+                            <select id="assigned-client" class="form-control" multiple size=5
                                     ng-multiple="true"
-                                    ng-model="selectedApplicationMappings"
-                                    ng-options="r.name for r in applicationMappings">
+                                    ng-model="selectedClientMappings"
+                                    ng-options="r.name for r in clientMappings">
                             </select>
                         </div>
                     </div>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-mappings.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-mappings.html
index 0ae08be..314212b 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-mappings.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-mappings.html
@@ -63,56 +63,56 @@
                 </div>
             </fieldset>
 
-            <fieldset ng-show="applications.length > 0">
-                <legend><span class="text">Application Roles</span> </legend>
+            <fieldset ng-show="clients.length > 0">
+                <legend><span class="text">Client Roles</span> </legend>
                 <div class="form-group input-select">
-                    <label class="col-sm-2 control-label" for="applications">Application <span tooltip-placement="right" tooltip="Select an application to view or modify additional roles to map." class="fa fa-info-circle"></span></label>
+                    <label class="col-sm-2 control-label" for="clients">Client <span tooltip-placement="right" tooltip="Select a client to view or modify additional roles to map." class="fa fa-info-circle"></span></label>
                     <div class="col-sm-4">
                         <div class="input-group">
                             <div class="select-kc">
-                                <select id="applications" name="applications" ng-change="changeApplication()" ng-model="application" ng-options="a.name for a in applications" ng-disabled="false">
-                                    <option value="" selected> Select an Application...</option>
+                                <select id="clients" name="clients" ng-change="changeClient()" ng-model="client" ng-options="a.clientId for a in clients" ng-disabled="false">
+                                    <option value="" selected> Select a Client...</option>
                                 </select>
                             </div>
                         </div>
                     </div>
 
                 </div>
-                <div class="form-group" ng-show="application">
+                <div class="form-group" ng-show="client">
                     <div class="controls changing-selectors col-sm-10">
                         <div class="select-title">
-                            <label class="control-label" for="available-app">Available Roles <span tooltip-placement="right" tooltip="Assignable roles from this application." class="fa fa-info-circle"></span></label>
-                            <select id="available-app" class="form-control" multiple size="5"
+                            <label class="control-label" for="available-client">Available Roles <span tooltip-placement="right" tooltip="Assignable roles from this client." class="fa fa-info-circle"></span></label>
+                            <select id="available-client" class="form-control" multiple size="5"
                                     ng-multiple="true"
-                                    ng-model="selectedApplicationRoles"
-                                    ng-options="r.name for r in applicationRoles">
+                                    ng-model="selectedClientRoles"
+                                    ng-options="r.name for r in clientRoles">
                             </select>
                         </div>
                         <div class="middle-buttons">
-                            <button class="btn btn-default" type="submit" ng-click="addApplicationRole()" tooltip="Assign role" tooltip-placement="right">
+                            <button class="btn btn-default" type="submit" ng-click="addClientRole()" tooltip="Assign role" tooltip-placement="right">
                                 <span class="kc-icon-arrow-right">Move right</span>
                             </button>
-                            <button class="btn btn-default" type="submit" ng-click="deleteApplicationRole()" tooltip="Unassign role" tooltip-placement="left">
+                            <button class="btn btn-default" type="submit" ng-click="deleteClientRole()" tooltip="Unassign role" tooltip-placement="left">
                                 <span class="kc-icon-arrow-left">Move left</span>
                             </button>
                         </div>
                         <div class="select-title">
-                            <label class="control-label" for="assigned-app">Assigned Roles <span tooltip-placement="right" tooltip="Role mappings for this application." class="fa fa-info-circle"></span></label>
-                            <select id="assigned-app" class="form-control" multiple size=5
+                            <label class="control-label" for="assigned-client">Assigned Roles <span tooltip-placement="right" tooltip="Role mappings for this client." class="fa fa-info-circle"></span></label>
+                            <select id="assigned-client" class="form-control" multiple size=5
                                     ng-multiple="true"
-                                    ng-model="selectedApplicationMappings"
-                                    ng-options="r.name for r in applicationMappings">
+                                    ng-model="selectedClientMappings"
+                                    ng-options="r.name for r in clientMappings">
                             </select>
                         </div>
                         <div class="middle-buttons">
                             -
                         </div>
                         <div class="select-title">
-                            <label class="control-label" for="app-composite">Effective Roles <span tooltip-placement="right" tooltip="Role mappings for this application.  Some roles here might be inherited from a mapped composite role." class="fa fa-info-circle"></span></label>
-                            <select id="app-composite" class="form-control" multiple size=5
+                            <label class="control-label" for="client-composite">Effective Roles <span tooltip-placement="right" tooltip="Role mappings for this client.  Some roles here might be inherited from a mapped composite role." class="fa fa-info-circle"></span></label>
+                            <select id="client-composite" class="form-control" multiple size=5
                                     ng-disabled="true"
                                     ng-model="dummymodel"
-                                    ng-options="r.name for r in applicationComposite">
+                                    ng-options="r.name for r in clientComposite">
                             </select>
                         </div>
                     </div>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/session-realm.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/session-realm.html
index 1394703..2535b46 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/session-realm.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/session-realm.html
@@ -18,13 +18,13 @@
                 </th>
             </tr>
             <tr>
-                <th>Application</th>
+                <th>Client</th>
                 <th>Active Sessions</th>
             </tr>
             </thead>
             <tbody>
             <tr data-ng-repeat="data in stats">
-                <td><a href="#/realms/{{realm.realm}}/applications/{{data.id}}/sessions">{{data.name}}</a></td>
+                <td><a href="#/realms/{{realm.realm}}/clients/{{data.id}}/sessions">{{data.clientId}}</a></td>
                 <td>{{data.active}}</td>
             </tr>
             </tbody>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/session-revocation.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/session-revocation.html
index c87af7f..f84c5ae 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/session-revocation.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/session-revocation.html
@@ -18,12 +18,12 @@
                     <span tooltip-placement="right" tooltip="Revoke any tokens issued before this date." class="fa fa-info-circle"></span>
                 </div>
             </fieldset>
-            <div class="pull-right form-actions" data-ng-show="access.manageApplications">
+            <div class="pull-right form-actions" data-ng-show="access.manageClients">
                 <button type="submit" data-ng-click="clear()" class="btn btn-default btn-lg">Clear
                 </button>
                 <button type="submit" data-ng-click="setNotBeforeNow()" class="btn btn-primary btn-lg">Set To Now
                 </button>
-                <button type="submit" data-ng-click="pushRevocation()" class="btn btn-primary btn-lg" tooltip="For every application that has an admin URL, notify them of the new revocation policy." tooltip-placement="bottom">Push
+                <button type="submit" data-ng-click="pushRevocation()" class="btn btn-primary btn-lg" tooltip="For every client that has an admin URL, notify them of the new revocation policy." tooltip-placement="bottom">Push
                 </button>
             </div>
         </form>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-sessions.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-sessions.html
index f3de7e4..9db3f7d 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-sessions.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-sessions.html
@@ -27,8 +27,7 @@
                 <th>IP Address</th>
                 <th>Started</th>
                 <th>Last Access</th>
-                <th>Applications</th>
-                <th>OAuth Clients</th>
+                <th>Clients</th>
                 <th>Action</th>
             </tr>
             </thead>
@@ -38,16 +37,11 @@
                 <td>{{session.start | date:'medium'}}</td>
                 <td>{{session.lastAccess | date:'medium'}}</td>
                 <td>
-                    <div data-ng-repeat="(id, name) in session.applications">
-                        <a href="#/realms/{{realm.realm}}/applications/{{id}}">{{name}}</a>
+                    <div data-ng-repeat="(id, clientId) in session.clients">
+                        <a href="#/realms/{{realm.realm}}/clients/{{id}}">{{clientId}}</a>
                     </div>
                 </ul>
                 </td>
-                <td>
-                    <div data-ng-repeat="(clientId, clientName) in session.clients">
-                        <a href="#/realms/{{realm.realm}}/oauth-clients/{{clientId}}">{{clientName}}</a>
-                    </div>
-                </td>
                 <td><a href="" ng-click="logoutSession(session.id)">logout</a> </td>
             </tr>
             </tbody>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-navigation-client.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-navigation-client.html
new file mode 100755
index 0000000..9794e38
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-navigation-client.html
@@ -0,0 +1,13 @@
+<ul class="nav nav-tabs nav-tabs-pf"  data-ng-hide="create && !path[4]">
+    <li ng-class="{active: !path[4]}"><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">Settings</a></li>
+    <li ng-class="{active: path[4] == 'credentials'}" data-ng-show="!client.publicClient && client.protocol != 'saml'"><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/credentials">Credentials</a></li>
+    <li ng-class="{active: path[4] == 'saml'}" data-ng-show="client.protocol == 'saml' && (client.attributes['saml.client.signature'] == 'true' || client.attributes['saml.encrypt'] == 'true')"><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/saml/keys">SAML Keys</a></li>
+    <li ng-class="{active: path[4] == 'roles'}"><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/roles">Roles</a></li>
+    <li ng-class="{active: path[4] == 'mappers'}" data-ng-show="!client.bearerOnly"><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/mappers">Mappers</a></li>
+    <li ng-class="{active: path[4] == 'scope-mappings'}" data-ng-show="!client.bearerOnly"><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/scope-mappings">Scope</a></li>
+    <li ng-class="{active: path[4] == 'revocation'}"><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/revocation">Revocation</a></li>
+<!--    <li ng-class="{active: path[4] == 'identity-provider'}" data-ng-show="realm.identityFederationEnabled"><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/identity-provider">Identity Provider</a></li> -->
+    <li ng-class="{active: path[4] == 'sessions'}" data-ng-show="!client.bearerOnly"><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/sessions">Sessions</a></li>
+    <li ng-class="{active: path[4] == 'clustering'}" data-ng-show="!client.publicClient"><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/clustering">Clustering</a></li>
+    <li ng-class="{active: path[4] == 'installation'}" data-ng-show="client.protocol != 'saml'"><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/installation">Installation</a></li>
+</ul>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/login/login.ftl b/forms/common-themes/src/main/resources/theme/base/login/login.ftl
index 505e185..858e075 100755
--- a/forms/common-themes/src/main/resources/theme/base/login/login.ftl
+++ b/forms/common-themes/src/main/resources/theme/base/login/login.ftl
@@ -1,17 +1,9 @@
 <#import "template.ftl" as layout>
 <@layout.registrationLayout displayInfo=social.displayInfo; section>
     <#if section = "title">
-        <#if client.application>
-            ${msg("loginTitle",(realm.name!''))}
-        <#elseif client.oauthClient>
-            ${msg("loginOauthTitle",(realm.name!''))}
-        </#if>
+        ${msg("loginTitle",(realm.name!''))}
     <#elseif section = "header">
-        <#if client.application>
-            ${msg("loginTitleHtml",(realm.name!''))}
-        <#elseif client.oauthClient>
-            ${msg("loginOauthTitleHtml",(realm.name!''), (client.clientId!''))}
-        </#if>
+        ${msg("loginTitleHtml",(realm.name!''))}
     <#elseif section = "form">
         <#if realm.password>
             <form id="kc-form-login" class="${properties.kcFormClass!}" action="${url.loginAction}" method="post">
diff --git a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties
index 06abbb1..75ffd3e 100644
--- a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties
+++ b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties
@@ -11,7 +11,7 @@ registerWithTitle=Registrierung bei {0}
 registerWithTitleHtml=Registrierung bei <strong>{0}</strong>
 loginTitle=Anmeldung bei {0}
 loginTitleHtml=Anmeldung bei <strong>{0}</strong>
-loginOauthTitle=Tempor\u00E4rer zugriff auf {0}
+loginOauthTitle=
 loginOauthTitleHtml=Tempor\u00E4rer zugriff auf <strong>{0}</strong> angefordert von <strong>{1}</strong>.
 loginTotpTitle=Mobile Authentifizierung Einrichten
 loginProfileTitle=Benutzerkonto Informationen aktualisieren
diff --git a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties
index 4bb3a66..7c1347f 100755
--- a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties
+++ b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties
@@ -11,8 +11,6 @@ registerWithTitle=Register with {0}
 registerWithTitleHtml=Register with <strong>{0}</strong>
 loginTitle=Log in to {0}
 loginTitleHtml=Log in to <strong>{0}</strong>
-loginOauthTitle=Temporary access for {0}
-loginOauthTitleHtml=Temporary access for <strong>{0}</strong> requested by <strong>{1}</strong>.
 loginTotpTitle=Mobile Authenticator Setup
 loginProfileTitle=Update Account Information
 oauthGrantTitle=OAuth Grant
diff --git a/forms/login-freemarker/pom.xml b/forms/login-freemarker/pom.xml
index e83bc52..c5b7134 100755
--- a/forms/login-freemarker/pom.xml
+++ b/forms/login-freemarker/pom.xml
@@ -71,6 +71,12 @@
             <artifactId>jboss-logging</artifactId>
             <scope>provided</scope>
         </dependency>
+        
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
 	</dependencies>
 
 	<build>
diff --git a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/FreeMarkerLoginFormsProvider.java b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/FreeMarkerLoginFormsProvider.java
index 0dd6342..228a146 100755
--- a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/FreeMarkerLoginFormsProvider.java
+++ b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/FreeMarkerLoginFormsProvider.java
@@ -1,23 +1,5 @@
 package org.keycloak.login.freemarker;
 
-import java.io.IOException;
-import java.net.URI;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Properties;
-import java.util.concurrent.TimeUnit;
-
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.core.UriInfo;
-
 import org.jboss.logging.Logger;
 import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
 import org.keycloak.OAuth2Constants;
@@ -57,6 +39,23 @@ import org.keycloak.models.utils.FormMessage;
 import org.keycloak.services.messages.Messages;
 import org.keycloak.services.resources.flows.Urls;
 
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+import java.io.IOException;
+import java.net.URI;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.TimeUnit;
+
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
diff --git a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/ClientBean.java b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/ClientBean.java
index fcd9e11..53f7937 100755
--- a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/ClientBean.java
+++ b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/ClientBean.java
@@ -1,37 +1,25 @@
 package org.keycloak.login.freemarker.model;
 
-import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.ClientModel;
-import org.keycloak.models.OAuthClientModel;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
 public class ClientBean {
+
     protected ClientModel client;
 
     public ClientBean(ClientModel client) {
         this.client = client;
     }
 
-    public boolean isApplication() {
-        return client instanceof ApplicationModel;
-    }
-
-    public boolean isOauthClient() {
-        return client instanceof OAuthClientModel;
-    }
-
     public String getClientId() {
         return client.getClientId();
     }
 
     public String getBaseUrl() {
-        if (client instanceof ApplicationModel) {
-            return ((ApplicationModel) client).getBaseUrl();
-        }
-        return null;
+        return client.getBaseUrl();
     }
 
 }
diff --git a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/IdentityProviderBean.java b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/IdentityProviderBean.java
index 8da7f4d..65e0272 100755
--- a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/IdentityProviderBean.java
+++ b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/IdentityProviderBean.java
@@ -21,21 +21,21 @@
  */
 package org.keycloak.login.freemarker.model;
 
-import org.keycloak.OAuth2Constants;
-import org.keycloak.models.ApplicationModel;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.Constants;
 import org.keycloak.models.IdentityProviderModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.services.resources.flows.Urls;
 
 import javax.ws.rs.core.UriInfo;
 import java.net.URI;
+import java.util.Comparator;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ * @author Vlastimil Elias (velias at redhat dot com)
  */
 public class IdentityProviderBean {
 
@@ -49,23 +49,24 @@ public class IdentityProviderBean {
         List<IdentityProviderModel> identityProviders = realm.getIdentityProviders();
 
         if (!identityProviders.isEmpty()) {
-            providers = new LinkedList<IdentityProvider>();
-
+            Set<IdentityProvider> orderedSet = new TreeSet<>(IdentityProviderComparator.INSTANCE);
             for (IdentityProviderModel identityProvider : identityProviders) {
                 if (identityProvider.isEnabled()) {
-                    addIdentityProvider(realm, baseURI, identityProvider);
+                    addIdentityProvider(orderedSet, realm, baseURI, identityProvider);
                 }
             }
 
-            if (!providers.isEmpty()) {
+            if (!orderedSet.isEmpty()) {
+                providers = new LinkedList<IdentityProvider>(orderedSet);
                 displaySocial = true;
             }
         }
     }
 
-    private void addIdentityProvider(RealmModel realm, URI baseURI, IdentityProviderModel identityProvider) {
+    private void addIdentityProvider(Set<IdentityProvider> orderedSet, RealmModel realm, URI baseURI, IdentityProviderModel identityProvider) {
         String loginUrl = Urls.identityProviderAuthnRequest(baseURI, identityProvider.getAlias(), realm.getName()).toString();
-        providers.add(new IdentityProvider(identityProvider.getAlias(), identityProvider.getProviderId(), loginUrl));
+        orderedSet.add(new IdentityProvider(identityProvider.getAlias(), identityProvider.getProviderId(), loginUrl,
+                identityProvider.getConfig() != null ? identityProvider.getConfig().get("guiOrder") : null));
     }
 
     public List<IdentityProvider> getProviders() {
@@ -81,12 +82,13 @@ public class IdentityProviderBean {
         private final String alias;
         private final String providerId; // This refer to providerType (facebook, google, etc.)
         private final String loginUrl;
+        private final String guiOrder;
 
-        public IdentityProvider(String alias, String providerId,String loginUrl) {
+        public IdentityProvider(String alias, String providerId, String loginUrl, String guiOrder) {
             this.alias = alias;
             this.providerId = providerId;
-
             this.loginUrl = loginUrl;
+            this.guiOrder = guiOrder;
         }
 
         public String getAlias() {
@@ -100,5 +102,44 @@ public class IdentityProviderBean {
         public String getProviderId() {
             return providerId;
         }
+
+        public String getGuiOrder() {
+            return guiOrder;
+        }
+    }
+
+    public static class IdentityProviderComparator implements Comparator<IdentityProvider> {
+
+        public static IdentityProviderComparator INSTANCE = new IdentityProviderComparator();
+
+        private IdentityProviderComparator() {
+
+        }
+
+        @Override
+        public int compare(IdentityProvider o1, IdentityProvider o2) {
+            
+            int o1order = parseOrder(o1);
+            int o2order = parseOrder(o2);
+
+            if (o1order > o2order)
+                return 1;
+            else if (o1order < o2order)
+                return -1;
+            
+            return 1;
+        }
+
+        private int parseOrder(IdentityProvider ip) {
+            if (ip != null && ip.getGuiOrder() != null) {
+                try {
+                    return Integer.parseInt(ip.getGuiOrder());
+                } catch (NumberFormatException e) {
+                    // ignore it and use defaulr
+                }
+            }
+            return 10000;
+        }
+
     }
 }
diff --git a/forms/login-freemarker/src/test/java/org/keycloak/login/freemarker/model/IdentityProviderBeanTest.java b/forms/login-freemarker/src/test/java/org/keycloak/login/freemarker/model/IdentityProviderBeanTest.java
new file mode 100644
index 0000000..dda3316
--- /dev/null
+++ b/forms/login-freemarker/src/test/java/org/keycloak/login/freemarker/model/IdentityProviderBeanTest.java
@@ -0,0 +1,55 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @authors tag. All rights reserved.
+ */
+package org.keycloak.login.freemarker.model;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.keycloak.login.freemarker.model.IdentityProviderBean.IdentityProvider;
+import org.keycloak.login.freemarker.model.IdentityProviderBean.IdentityProviderComparator;
+
+/**
+ * Unit test for {@link IdentityProviderBean}
+ * 
+ * @author Vlastimil Elias (velias at redhat dot com)
+ */
+public class IdentityProviderBeanTest {
+
+
+    @Test
+    public void testIdentityProviderComparator() {
+
+        IdentityProvider o1 = new IdentityProvider("alias1", "id1", "ur1", null);
+        IdentityProvider o2 = new IdentityProvider("alias2", "id2", "ur2", null);
+
+        // guiOrder not defined at any object - first is always lower
+        Assert.assertEquals(1, IdentityProviderComparator.INSTANCE.compare(o1, o2));
+        Assert.assertEquals(1, IdentityProviderComparator.INSTANCE.compare(o2, o1));
+
+        // guiOrder is not a number so it is same as not defined - first is always lower
+        o1 = new IdentityProvider("alias1", "id1", "ur1", "not a number");
+        Assert.assertEquals(1, IdentityProviderComparator.INSTANCE.compare(o1, o2));
+        Assert.assertEquals(1, IdentityProviderComparator.INSTANCE.compare(o2, o1));
+
+        // guiOrder is defined for one only to it is always first
+        o1 = new IdentityProvider("alias1", "id1", "ur1", "0");
+        Assert.assertEquals(-1, IdentityProviderComparator.INSTANCE.compare(o1, o2));
+        Assert.assertEquals(1, IdentityProviderComparator.INSTANCE.compare(o2, o1));
+
+        // guiOrder is defined for both but is same - first is always lower
+        o1 = new IdentityProvider("alias1", "id1", "ur1", "0");
+        o2 = new IdentityProvider("alias2", "id2", "ur2", "0");
+        Assert.assertEquals(1, IdentityProviderComparator.INSTANCE.compare(o1, o2));
+        Assert.assertEquals(1, IdentityProviderComparator.INSTANCE.compare(o2, o1));
+
+        // guiOrder is reflected
+        o1 = new IdentityProvider("alias1", "id1", "ur1", "0");
+        o2 = new IdentityProvider("alias2", "id2", "ur2", "1");
+        Assert.assertEquals(-1, IdentityProviderComparator.INSTANCE.compare(o1, o2));
+        Assert.assertEquals(1, IdentityProviderComparator.INSTANCE.compare(o2, o1));
+
+    }
+
+}
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/ServerRequest.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/ServerRequest.java
index 27a2949..701dc09 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/ServerRequest.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/ServerRequest.java
@@ -102,8 +102,8 @@ public class ServerRequest {
         formparams.add(new BasicNameValuePair(OAuth2Constants.CODE, code));
         formparams.add(new BasicNameValuePair(OAuth2Constants.REDIRECT_URI, redirectUri));
         if (sessionId != null) {
-            formparams.add(new BasicNameValuePair(AdapterConstants.APPLICATION_SESSION_STATE, sessionId));
-            formparams.add(new BasicNameValuePair(AdapterConstants.APPLICATION_SESSION_HOST, HostUtils.getHostName()));
+            formparams.add(new BasicNameValuePair(AdapterConstants.CLIENT_SESSION_STATE, sessionId));
+            formparams.add(new BasicNameValuePair(AdapterConstants.CLIENT_SESSION_HOST, HostUtils.getHostName()));
         }
         HttpResponse response = null;
         HttpPost post = new HttpPost(tokenUrl);
@@ -237,7 +237,7 @@ public class ServerRequest {
         }
 
         List<NameValuePair> formparams = new ArrayList<NameValuePair>();
-        formparams.add(new BasicNameValuePair(AdapterConstants.APPLICATION_CLUSTER_HOST, host));
+        formparams.add(new BasicNameValuePair(AdapterConstants.CLIENT_CLUSTER_HOST, host));
 
         HttpPost post = new HttpPost(endpointUrl);
 
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/RealmResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/RealmResource.java
index 1ed0a80..4045ecf 100644
--- a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/RealmResource.java
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/RealmResource.java
@@ -23,15 +23,12 @@ public interface RealmResource {
     @Consumes(MediaType.APPLICATION_JSON)
     public void update(RealmRepresentation realmRepresentation);
 
-    @Path("applications")
-    public ApplicationsResource applications();
+    @Path("clients")
+    public ClientsResource clients();
 
     @Path("users")
     public UsersResource users();
 
-    @Path("oauth-clients")
-    public OAuthClientsResource oAuthClients();
-
     @Path("roles")
     public RolesResource roles();
 
diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerAddHandler.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerAddHandler.java
index 591718e..43d26ce 100755
--- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerAddHandler.java
+++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerAddHandler.java
@@ -69,7 +69,7 @@ public final class AuthServerAddHandler extends AbstractAddStepHandler {
 
         AuthServerUtil authServerUtil = new AuthServerUtil(operation);
         authServerUtil.addStepToUploadAuthServer(context, enabled);
-        KeycloakAdapterConfigService.INSTANCE.addServerDeployment(authServerUtil.getDeploymentName(), webContext);
+        KeycloakAdapterConfigService.getInstance().addServerDeployment(authServerUtil.getDeploymentName(), webContext);
     }
 
     @Override
diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerDefinition.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerDefinition.java
index 653d09a..648e35d 100755
--- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerDefinition.java
+++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerDefinition.java
@@ -116,7 +116,7 @@ public class AuthServerDefinition extends SimpleResourceDefinition {
         @Override
         public void validateParameter(String paramName, ModelNode value) throws OperationFailedException {
             String strValue = value.asString();
-            if (KeycloakAdapterConfigService.INSTANCE.isWebContextUsed(strValue)) {
+            if (KeycloakAdapterConfigService.getInstance().isWebContextUsed(strValue)) {
                 throw new OperationFailedException("Can not set web-context to '" + strValue + "'. web-context must be unique among all deployments.");
             }
         }
@@ -124,7 +124,7 @@ public class AuthServerDefinition extends SimpleResourceDefinition {
         @Override
         public void validateResolvedParameter(String paramName, ModelNode value) throws OperationFailedException {
             String strValue = value.asString();
-            if (KeycloakAdapterConfigService.INSTANCE.isWebContextUsed(strValue)) {
+            if (KeycloakAdapterConfigService.getInstance().isWebContextUsed(strValue)) {
                 throw new OperationFailedException("Can not set web-context to '" + strValue + "'. web-context must be unique among all deployments.");
             }
         }
diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerRemoveHandler.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerRemoveHandler.java
index f84e45f..e80fbc6 100644
--- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerRemoveHandler.java
+++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerRemoveHandler.java
@@ -45,7 +45,7 @@ public final class AuthServerRemoveHandler extends AbstractRemoveStepHandler {
     @Override
     protected void performRemove(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
         String deploymentName = AuthServerUtil.getDeploymentName(operation);
-        KeycloakAdapterConfigService.INSTANCE.removeServerDeployment(deploymentName);
+        KeycloakAdapterConfigService.getInstance().removeServerDeployment(deploymentName);
 
         if (requiresRuntime(context)) { // don't do this on a domain controller
             addStepToRemoveAuthServer(context, deploymentName);
diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerUtil.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerUtil.java
index 9ccef2c..bf8074b 100644
--- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerUtil.java
+++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerUtil.java
@@ -46,6 +46,7 @@ import org.jboss.dmr.ModelNode;
 import org.jboss.modules.Module;
 import org.jboss.modules.ModuleIdentifier;
 import org.jboss.modules.ModuleLoadException;
+import org.keycloak.subsystem.extension.KeycloakExtension;
 
 /**
  * Utility methods that help assemble and start an auth server.
@@ -105,6 +106,9 @@ public class AuthServerUtil {
         op.get(ENABLED).set(isEnabled);
         op.get(PERSISTENT).set(false); // prevents writing this deployment out to standalone.xml
 
+        // Owner attribute is valid starting with WidlFly 9.  Ignored in WildFly 8
+        op.get("owner").set(new ModelNode().add("subsystem", KeycloakExtension.SUBSYSTEM_NAME));
+
         if (authServerUri == null) {
             throw new OperationFailedException("Keycloak Auth Server WAR not found in keycloak-subsystem module");
         }
diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerWriteAttributeHandler.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerWriteAttributeHandler.java
index 48ffc32..6c5d6b3 100755
--- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerWriteAttributeHandler.java
+++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/AuthServerWriteAttributeHandler.java
@@ -55,8 +55,8 @@ public class AuthServerWriteAttributeHandler extends ModelOnlyWriteAttributeHand
 
         if (attributeName.equals(AuthServerDefinition.WEB_CONTEXT.getName())) {
 
-            KeycloakAdapterConfigService.INSTANCE.removeServerDeployment(deploymentName);
-            KeycloakAdapterConfigService.INSTANCE.addServerDeployment(deploymentName, newValue.asString());
+            KeycloakAdapterConfigService.getInstance().removeServerDeployment(deploymentName);
+            KeycloakAdapterConfigService.getInstance().addServerDeployment(deploymentName, newValue.asString());
             if (isEnabled) {
                 AuthServerUtil.addStepToRedeployAuthServer(context, deploymentName);
             }
diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/KeycloakServerDeploymentProcessor.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/KeycloakServerDeploymentProcessor.java
index dd66a01..565310d 100644
--- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/KeycloakServerDeploymentProcessor.java
+++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/authserver/KeycloakServerDeploymentProcessor.java
@@ -34,7 +34,7 @@ public class KeycloakServerDeploymentProcessor implements DeploymentUnitProcesso
     public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
         DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
         String deploymentName = deploymentUnit.getName();
-        KeycloakAdapterConfigService service = KeycloakAdapterConfigService.find(phaseContext.getServiceRegistry());
+        KeycloakAdapterConfigService service = KeycloakAdapterConfigService.getInstance();
         if (!service.isKeycloakServerDeployment(deploymentName)) {
             return;
         }
diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/CredentialAddHandler.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/CredentialAddHandler.java
index c3c37fa..17f7928 100755
--- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/CredentialAddHandler.java
+++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/CredentialAddHandler.java
@@ -40,7 +40,7 @@ public class CredentialAddHandler extends AbstractAddStepHandler {
 
     @Override
     protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model, ServiceVerificationHandler verificationHandler, List<ServiceController<?>> newControllers) throws OperationFailedException {
-        KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.find(context);
+        KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance();
         ckService.addCredential(operation, context.resolveExpressions(model));
     }
 
diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/CredentialReadWriteAttributeHandler.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/CredentialReadWriteAttributeHandler.java
index 6289ff4..75b334d 100644
--- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/CredentialReadWriteAttributeHandler.java
+++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/CredentialReadWriteAttributeHandler.java
@@ -33,7 +33,7 @@ public class CredentialReadWriteAttributeHandler extends AbstractWriteAttributeH
     protected boolean applyUpdateToRuntime(OperationContext context, ModelNode operation, String attributeName,
                                            ModelNode resolvedValue, ModelNode currentValue, AbstractWriteAttributeHandler.HandbackHolder<KeycloakAdapterConfigService> hh) throws OperationFailedException {
 
-        KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.find(context);
+        KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance();
         ckService.updateCredential(operation, attributeName, resolvedValue);
 
         hh.setHandback(ckService);
diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/CredentialRemoveHandler.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/CredentialRemoveHandler.java
index 1cad10b..0023d41 100644
--- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/CredentialRemoveHandler.java
+++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/CredentialRemoveHandler.java
@@ -35,7 +35,7 @@ public final class CredentialRemoveHandler extends AbstractRemoveStepHandler {
 
     @Override
     protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
-        KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.find(context);
+        KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance();
         ckService.removeCredential(operation);
     }
 
diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessor.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessor.java
index f96d1c2..bebf6db 100755
--- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessor.java
+++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessor.java
@@ -68,8 +68,7 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
         DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
 
         String deploymentName = deploymentUnit.getName();
-        KeycloakAdapterConfigService service = KeycloakAdapterConfigService.find(phaseContext.getServiceRegistry());
-        //log.info("********* CHECK KEYCLOAK DEPLOYMENT: " + deploymentName);
+        KeycloakAdapterConfigService service = KeycloakAdapterConfigService.getInstance();
         if (service.isSecureDeployment(deploymentName)) {
             addKeycloakAuthData(phaseContext, deploymentName, service);
         }
diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessorEAP6.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessorEAP6.java
index 77261ba..dc2d8e7 100755
--- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessorEAP6.java
+++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigDeploymentProcessorEAP6.java
@@ -50,7 +50,7 @@ public class KeycloakAdapterConfigDeploymentProcessorEAP6 implements DeploymentU
         DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
         String deploymentName = deploymentUnit.getName();
 
-        KeycloakAdapterConfigService service = KeycloakAdapterConfigService.find(phaseContext.getServiceRegistry());
+        KeycloakAdapterConfigService service = KeycloakAdapterConfigService.getInstance();
         //log.info("********* CHECK KEYCLOAK DEPLOYMENT: " + deploymentName);
         if (service.isSecureDeployment(deploymentName)) {
             addKeycloakAuthData(phaseContext, deploymentName, service);
diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigService.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigService.java
index d860cb6..81bb610 100755
--- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigService.java
+++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakAdapterConfigService.java
@@ -17,17 +17,9 @@
 
 package org.keycloak.subsystem.extension;
 
-import org.jboss.as.controller.OperationContext;
 import org.jboss.dmr.ModelNode;
 import org.jboss.dmr.Property;
 import org.jboss.logging.Logger;
-import org.jboss.msc.service.Service;
-import org.jboss.msc.service.ServiceController;
-import org.jboss.msc.service.ServiceName;
-import org.jboss.msc.service.ServiceRegistry;
-import org.jboss.msc.service.StartContext;
-import org.jboss.msc.service.StartException;
-import org.jboss.msc.service.StopContext;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -40,41 +32,27 @@ import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD
  *
  * @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
  */
-public final class KeycloakAdapterConfigService implements Service<KeycloakAdapterConfigService> {
+public final class KeycloakAdapterConfigService {
     protected Logger log = Logger.getLogger(KeycloakAdapterConfigService.class);
     private static final String CREDENTIALS_JSON_NAME = "credentials";
 
-    // Right now this is used as a service, but I'm not sure it really needs to be implemented that way.
-    // It's also a singleton serving the entire subsystem, but the INSTANCE variable is currently only
-    // used during initialization of the subsystem.
-    public static final ServiceName SERVICE_NAME = ServiceName.JBOSS.append("KeycloakAdapterConfigService");
-    public static final KeycloakAdapterConfigService INSTANCE = new KeycloakAdapterConfigService();
+    private static final KeycloakAdapterConfigService INSTANCE = new KeycloakAdapterConfigService();
 
-    private Map<String, ModelNode> realms = new HashMap<String, ModelNode>();
+    public static KeycloakAdapterConfigService getInstance() {
+        return INSTANCE;
+    }
+
+    private final Map<String, ModelNode> realms = new HashMap<String, ModelNode>();
 
     // keycloak-secured deployments
-    private Map<String, ModelNode> secureDeployments = new HashMap<String, ModelNode>();
+    private final Map<String, ModelNode> secureDeployments = new HashMap<String, ModelNode>();
 
     // key=auth-server deployment name; value=web-context
-    private Map<String, String> webContexts = new HashMap<String, String>();
+    private final Map<String, String> webContexts = new HashMap<String, String>();
 
-    private KeycloakAdapterConfigService() {
-
-    }
 
-    @Override
-    public void start(StartContext sc) throws StartException {
 
-    }
-
-    @Override
-    public void stop(StopContext sc) {
-
-    }
-
-    @Override
-    public KeycloakAdapterConfigService getValue() throws IllegalStateException, IllegalArgumentException {
-        return this;
+    private KeycloakAdapterConfigService() {
     }
 
     public void addServerDeployment(String deploymentName, String webContext) {
@@ -223,17 +201,4 @@ public final class KeycloakAdapterConfigService implements Service<KeycloakAdapt
     public boolean isKeycloakServerDeployment(String deploymentName) {
         return this.webContexts.containsKey(deploymentName);
     }
-
-    public static KeycloakAdapterConfigService find(ServiceRegistry registry) {
-        ServiceController<?> container = registry.getService(KeycloakAdapterConfigService.SERVICE_NAME);
-        if (container != null) {
-            KeycloakAdapterConfigService service = (KeycloakAdapterConfigService)container.getValue();
-            return service;
-        }
-        return null;
-    }
-
-    public static KeycloakAdapterConfigService find(OperationContext context) {
-        return find(context.getServiceRegistry(true));
-    }
 }
diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakSubsystemAdd.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakSubsystemAdd.java
index 0a49004..386f8c5 100755
--- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakSubsystemAdd.java
+++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakSubsystemAdd.java
@@ -83,18 +83,6 @@ class KeycloakSubsystemAdd extends AbstractBoottimeAddStepHandler {
     }
 
     @Override
-    protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model, ServiceVerificationHandler verificationHandler, List<ServiceController<?>> newControllers) throws OperationFailedException {
-        super.performRuntime(context, operation, model, verificationHandler, newControllers);
-
-        ServiceController<KeycloakAdapterConfigService> controller = context.getServiceTarget()
-                .addService(KeycloakAdapterConfigService.SERVICE_NAME, KeycloakAdapterConfigService.INSTANCE)
-                .addListener(verificationHandler)
-                .setInitialMode(ServiceController.Mode.ACTIVE)
-                .install();
-        newControllers.add(controller);
-    }
-
-    @Override
     protected boolean requiresRuntimeVerification() {
         return false;
     }
diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/RealmAddHandler.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/RealmAddHandler.java
index 0d4a5d8..62c76e6 100755
--- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/RealmAddHandler.java
+++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/RealmAddHandler.java
@@ -60,7 +60,7 @@ public final class RealmAddHandler extends AbstractAddStepHandler {
 
     @Override
     protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model, ServiceVerificationHandler verificationHandler, List<ServiceController<?>> newControllers) throws OperationFailedException {
-        KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.find(context);
+        KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance();
         ckService.addRealm(operation, context.resolveExpressions(model));
     }
 }
diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/RealmRemoveHandler.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/RealmRemoveHandler.java
index a5c5441..5cc319c 100644
--- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/RealmRemoveHandler.java
+++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/RealmRemoveHandler.java
@@ -35,7 +35,7 @@ public final class RealmRemoveHandler extends AbstractRemoveStepHandler {
 
     @Override
     protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
-        KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.find(context);
+        KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance();
         ckService.removeRealm(operation);
     }
 }
diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/RealmWriteAttributeHandler.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/RealmWriteAttributeHandler.java
index 1902b07..13e91c5 100755
--- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/RealmWriteAttributeHandler.java
+++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/RealmWriteAttributeHandler.java
@@ -43,7 +43,7 @@ public class RealmWriteAttributeHandler extends AbstractWriteAttributeHandler<Ke
     @Override
     protected boolean applyUpdateToRuntime(OperationContext context, ModelNode operation, String attributeName,
                                            ModelNode resolvedValue, ModelNode currentValue, HandbackHolder<KeycloakAdapterConfigService> hh) throws OperationFailedException {
-        KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.find(context);
+        KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance();
         ckService.updateRealm(operation, attributeName, resolvedValue);
 
         hh.setHandback(ckService);
diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentAddHandler.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentAddHandler.java
index 99267db..0c36146 100755
--- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentAddHandler.java
+++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentAddHandler.java
@@ -55,7 +55,7 @@ public final class SecureDeploymentAddHandler extends AbstractAddStepHandler {
 
     @Override
     protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model, ServiceVerificationHandler verificationHandler, List<ServiceController<?>> newControllers) throws OperationFailedException {
-        KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.find(context);
+        KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance();
         ckService.addSecureDeployment(operation, context.resolveExpressions(model));
     }
 }
diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentRemoveHandler.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentRemoveHandler.java
index da0ca7e..23196a5 100644
--- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentRemoveHandler.java
+++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentRemoveHandler.java
@@ -35,7 +35,7 @@ public final class SecureDeploymentRemoveHandler extends AbstractRemoveStepHandl
 
     @Override
     protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
-        KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.find(context);
+        KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance();
         ckService.removeSecureDeployment(operation);
     }
 }
diff --git a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentWriteAttributeHandler.java b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentWriteAttributeHandler.java
index 2caca6a..6c87ac8 100755
--- a/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentWriteAttributeHandler.java
+++ b/integration/keycloak-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentWriteAttributeHandler.java
@@ -44,7 +44,7 @@ public class SecureDeploymentWriteAttributeHandler extends AbstractWriteAttribut
     @Override
     protected boolean applyUpdateToRuntime(OperationContext context, ModelNode operation, String attributeName,
                                            ModelNode resolvedValue, ModelNode currentValue, HandbackHolder<KeycloakAdapterConfigService> hh) throws OperationFailedException {
-        KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.find(context);
+        KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance();
         hh.setHandback(ckService);
         ckService.updateSecureDeployment(operation, attributeName, resolvedValue);
         return false;
diff --git a/model/api/src/main/java/org/keycloak/models/AdminRoles.java b/model/api/src/main/java/org/keycloak/models/AdminRoles.java
index 8d46505..c067a1d 100755
--- a/model/api/src/main/java/org/keycloak/models/AdminRoles.java
+++ b/model/api/src/main/java/org/keycloak/models/AdminRoles.java
@@ -9,25 +9,23 @@ public class AdminRoles {
 
     public static String ADMIN = "admin";
 
-    // for admin application local to each realm
+    // for admin client local to each realm
     public static String REALM_ADMIN = "realm-admin";
 
     public static String CREATE_REALM = "create-realm";
 
     public static String VIEW_REALM = "view-realm";
     public static String VIEW_USERS = "view-users";
-    public static String VIEW_APPLICATIONS = "view-applications";
     public static String VIEW_CLIENTS = "view-clients";
     public static String VIEW_EVENTS = "view-events";
     public static String VIEW_IDENTITY_PROVIDERS = "view-identity-providers";
 
     public static String MANAGE_REALM = "manage-realm";
     public static String MANAGE_USERS = "manage-users";
-    public static String MANAGE_APPLICATIONS = "manage-applications";
     public static String MANAGE_IDENTITY_PROVIDERS = "manage-identity-providers";
     public static String MANAGE_CLIENTS = "manage-clients";
     public static String MANAGE_EVENTS = "manage-events";
 
-    public static String[] ALL_REALM_ROLES = {VIEW_REALM, VIEW_USERS, VIEW_APPLICATIONS, VIEW_CLIENTS, VIEW_EVENTS, VIEW_IDENTITY_PROVIDERS, MANAGE_REALM, MANAGE_USERS, MANAGE_APPLICATIONS, MANAGE_CLIENTS, MANAGE_EVENTS, MANAGE_IDENTITY_PROVIDERS};
+    public static String[] ALL_REALM_ROLES = {VIEW_REALM, VIEW_USERS, VIEW_CLIENTS, VIEW_EVENTS, VIEW_IDENTITY_PROVIDERS, MANAGE_REALM, MANAGE_USERS, MANAGE_CLIENTS, MANAGE_EVENTS, MANAGE_IDENTITY_PROVIDERS};
 
 }
diff --git a/model/api/src/main/java/org/keycloak/models/ClientModel.java b/model/api/src/main/java/org/keycloak/models/ClientModel.java
index e9de509..026e35e 100755
--- a/model/api/src/main/java/org/keycloak/models/ClientModel.java
+++ b/model/api/src/main/java/org/keycloak/models/ClientModel.java
@@ -8,7 +8,7 @@ import java.util.Set;
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public interface ClientModel {
+public interface ClientModel extends RoleContainerModel {
 
     // COMMON ATTRIBUTES
 
@@ -16,20 +16,22 @@ public interface ClientModel {
     String PUBLIC_KEY = "publicKey";
     String X509CERTIFICATE = "X509Certificate";
 
-    /**
-     * Internal database key
-     *
-     * @return
-     */
+    void updateClient();
+
     String getId();
 
-    /**
-     * String exposed to outside world
-     *
-     * @return
-     */
     String getClientId();
 
+    void setClientId(String clientId);
+
+    boolean isEnabled();
+
+    void setEnabled(boolean enabled);
+
+    boolean isSurrogateAuthRequired();
+
+    void setSurrogateAuthRequired(boolean surrogateAuthRequired);
+
     Set<String> getWebOrigins();
 
     void setWebOrigins(Set<String> webOrigins);
@@ -46,10 +48,28 @@ public interface ClientModel {
 
     void removeRedirectUri(String redirectUri);
 
+    String getManagementUrl();
 
-    boolean isEnabled();
+    void setManagementUrl(String url);
 
-    void setEnabled(boolean enabled);
+    String getBaseUrl();
+
+    void setBaseUrl(String url);
+
+    List<String> getDefaultRoles();
+
+    void addDefaultRole(String name);
+
+    void updateDefaultRoles(String[] defaultRoles);
+
+    Set<RoleModel> getClientScopeMappings(ClientModel client);
+
+    boolean isBearerOnly();
+    void setBearerOnly(boolean only);
+
+    int getNodeReRegistrationTimeout();
+
+    void setNodeReRegistrationTimeout(int timeout);
 
     boolean validateSecret(String secret);
     String getSecret();
@@ -76,13 +96,15 @@ public interface ClientModel {
     boolean isDirectGrantsOnly();
     void setDirectGrantsOnly(boolean flag);
 
+    boolean isConsentRequired();
+    void setConsentRequired(boolean consentRequired);
+
     Set<RoleModel> getScopeMappings();
     void addScopeMapping(RoleModel role);
     void deleteScopeMapping(RoleModel role);
     Set<RoleModel> getRealmScopeMappings();
     boolean hasScope(RoleModel role);
 
-
     RealmModel getRealm();
 
     /**
@@ -104,4 +126,16 @@ public interface ClientModel {
     void updateProtocolMapper(ProtocolMapperModel mapping);
     public ProtocolMapperModel getProtocolMapperById(String id);
     public ProtocolMapperModel getProtocolMapperByName(String protocol, String name);
+
+    Map<String, Integer> getRegisteredNodes();
+
+    /**
+     * Register node or just update the 'lastReRegistration' time if this node is already registered
+     *
+     * @param nodeHost
+     * @param registrationTime
+     */
+    void registerNode(String nodeHost, int registrationTime);
+
+    void unregisterNode(String nodeHost);
 }
diff --git a/model/api/src/main/java/org/keycloak/models/Constants.java b/model/api/src/main/java/org/keycloak/models/Constants.java
index 7374d7b..edba3e3 100755
--- a/model/api/src/main/java/org/keycloak/models/Constants.java
+++ b/model/api/src/main/java/org/keycloak/models/Constants.java
@@ -5,9 +5,9 @@ package org.keycloak.models;
  * @version $Revision: 1 $
  */
 public interface Constants {
-    String ADMIN_CONSOLE_APPLICATION = "security-admin-console";
+    String ADMIN_CONSOLE_CLIENT_ID = "security-admin-console";
 
-    String ACCOUNT_MANAGEMENT_APP = "account";
+    String ACCOUNT_MANAGEMENT_CLIENT_ID = "account";
 
     String INSTALLED_APP_URN = "urn:ietf:wg:oauth:2.0:oob";
     String INSTALLED_APP_URL = "http://localhost";
diff --git a/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java b/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java
old mode 100755
new mode 100644
index 9c24072..699c6d6
--- a/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java
+++ b/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java
@@ -1,154 +1,236 @@
-package org.keycloak.models.entities;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-public class ClientEntity extends AbstractIdentifiableEntity {
-
-    private String name;
-    private boolean enabled;
-    private String secret;
-    private String protocol;
-    private long allowedClaimsMask;
-    private int notBefore;
-    private boolean publicClient;
-    private boolean fullScopeAllowed;
-    private boolean frontchannelLogout;
-
-    private String realmId;
-    private Map<String, String> attributes = new HashMap<String, String>();
-
-
-    private List<String> webOrigins = new ArrayList<String>();
-    private List<String> redirectUris = new ArrayList<String>();
-    private List<String> scopeIds = new ArrayList<String>();
-    private List<ClientIdentityProviderMappingEntity> identityProviders = new ArrayList<ClientIdentityProviderMappingEntity>();
-    private List<ProtocolMapperEntity> protocolMappers = new ArrayList<ProtocolMapperEntity>();
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-    public void setEnabled(boolean enabled) {
-        this.enabled = enabled;
-    }
-
-    public String getSecret() {
-        return secret;
-    }
-
-    public void setSecret(String secret) {
-        this.secret = secret;
-    }
-
-    public int getNotBefore() {
-        return notBefore;
-    }
-
-    public void setNotBefore(int notBefore) {
-        this.notBefore = notBefore;
-    }
-
-    public boolean isPublicClient() {
-        return publicClient;
-    }
-
-    public void setPublicClient(boolean publicClient) {
-        this.publicClient = publicClient;
-    }
-
-    public String getRealmId() {
-        return realmId;
-    }
-
-    public void setRealmId(String realmId) {
-        this.realmId = realmId;
-    }
-
-    public List<String> getWebOrigins() {
-        return webOrigins;
-    }
-
-    public void setWebOrigins(List<String> webOrigins) {
-        this.webOrigins = webOrigins;
-    }
-
-    public List<String> getRedirectUris() {
-        return redirectUris;
-    }
-
-    public void setRedirectUris(List<String> redirectUris) {
-        this.redirectUris = redirectUris;
-    }
-
-    public List<String> getScopeIds() {
-        return scopeIds;
-    }
-
-    public void setScopeIds(List<String> scopeIds) {
-        this.scopeIds = scopeIds;
-    }
-
-    public boolean isFullScopeAllowed() {
-        return fullScopeAllowed;
-    }
-
-    public void setFullScopeAllowed(boolean fullScopeAllowed) {
-        this.fullScopeAllowed = fullScopeAllowed;
-    }
-
-    public String getProtocol() {
-        return protocol;
-    }
-
-    public void setProtocol(String protocol) {
-        this.protocol = protocol;
-    }
-
-    public Map<String, String> getAttributes() {
-        return attributes;
-    }
-
-    public void setAttributes(Map<String, String> attributes) {
-        this.attributes = attributes;
-    }
-
-    public boolean isFrontchannelLogout() {
-        return frontchannelLogout;
-    }
-
-    public void setFrontchannelLogout(boolean frontchannelLogout) {
-        this.frontchannelLogout = frontchannelLogout;
-    }
-
-    public List<ClientIdentityProviderMappingEntity> getIdentityProviders() {
-        return this.identityProviders;
-    }
-
-    public void setIdentityProviders(List<ClientIdentityProviderMappingEntity> identityProviders) {
-        this.identityProviders = identityProviders;
-    }
-
-    public List<ProtocolMapperEntity> getProtocolMappers() {
-        return protocolMappers;
-    }
-
-    public void setProtocolMappers(List<ProtocolMapperEntity> protocolMappers) {
-        this.protocolMappers = protocolMappers;
-    }
-}
+package org.keycloak.models.entities;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class ClientEntity extends AbstractIdentifiableEntity {
+
+    private String clientId;
+    private String realmId;
+    private boolean enabled;
+    private String secret;
+    private String protocol;
+    private int notBefore;
+    private boolean publicClient;
+    private boolean fullScopeAllowed;
+    private boolean frontchannelLogout;
+
+    private boolean surrogateAuthRequired;
+    private String managementUrl;
+    private String baseUrl;
+    private boolean bearerOnly;
+    private boolean consentRequired;
+    private boolean directGrantsOnly;
+    private int nodeReRegistrationTimeout;
+
+    // We are using names of defaultRoles (not ids)
+    private List<String> defaultRoles = new ArrayList<String>();
+
+    private Map<String, Integer> registeredNodes;
+
+    private Map<String, String> attributes = new HashMap<String, String>();
+
+    private List<String> webOrigins = new ArrayList<String>();
+    private List<String> redirectUris = new ArrayList<String>();
+    private List<String> scopeIds = new ArrayList<String>();
+    private List<ClientIdentityProviderMappingEntity> identityProviders = new ArrayList<ClientIdentityProviderMappingEntity>();
+    private List<ProtocolMapperEntity> protocolMappers = new ArrayList<ProtocolMapperEntity>();
+
+    public String getClientId() {
+        return clientId;
+    }
+
+    public void setClientId(String clientId) {
+        this.clientId = clientId;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    public String getSecret() {
+        return secret;
+    }
+
+    public void setSecret(String secret) {
+        this.secret = secret;
+    }
+
+    public int getNotBefore() {
+        return notBefore;
+    }
+
+    public void setNotBefore(int notBefore) {
+        this.notBefore = notBefore;
+    }
+
+    public boolean isPublicClient() {
+        return publicClient;
+    }
+
+    public void setPublicClient(boolean publicClient) {
+        this.publicClient = publicClient;
+    }
+
+    public String getRealmId() {
+        return realmId;
+    }
+
+    public void setRealmId(String realmId) {
+        this.realmId = realmId;
+    }
+
+    public List<String> getWebOrigins() {
+        return webOrigins;
+    }
+
+    public void setWebOrigins(List<String> webOrigins) {
+        this.webOrigins = webOrigins;
+    }
+
+    public List<String> getRedirectUris() {
+        return redirectUris;
+    }
+
+    public void setRedirectUris(List<String> redirectUris) {
+        this.redirectUris = redirectUris;
+    }
+
+    public List<String> getScopeIds() {
+        return scopeIds;
+    }
+
+    public void setScopeIds(List<String> scopeIds) {
+        this.scopeIds = scopeIds;
+    }
+
+    public boolean isFullScopeAllowed() {
+        return fullScopeAllowed;
+    }
+
+    public void setFullScopeAllowed(boolean fullScopeAllowed) {
+        this.fullScopeAllowed = fullScopeAllowed;
+    }
+
+    public String getProtocol() {
+        return protocol;
+    }
+
+    public void setProtocol(String protocol) {
+        this.protocol = protocol;
+    }
+
+    public Map<String, String> getAttributes() {
+        return attributes;
+    }
+
+    public void setAttributes(Map<String, String> attributes) {
+        this.attributes = attributes;
+    }
+
+    public boolean isFrontchannelLogout() {
+        return frontchannelLogout;
+    }
+
+    public void setFrontchannelLogout(boolean frontchannelLogout) {
+        this.frontchannelLogout = frontchannelLogout;
+    }
+
+    public List<ClientIdentityProviderMappingEntity> getIdentityProviders() {
+        return this.identityProviders;
+    }
+
+    public void setIdentityProviders(List<ClientIdentityProviderMappingEntity> identityProviders) {
+        this.identityProviders = identityProviders;
+    }
+
+    public List<ProtocolMapperEntity> getProtocolMappers() {
+        return protocolMappers;
+    }
+
+    public void setProtocolMappers(List<ProtocolMapperEntity> protocolMappers) {
+        this.protocolMappers = protocolMappers;
+    }
+
+    public boolean isSurrogateAuthRequired() {
+        return surrogateAuthRequired;
+    }
+
+    public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
+        this.surrogateAuthRequired = surrogateAuthRequired;
+    }
+
+    public String getManagementUrl() {
+        return managementUrl;
+    }
+
+    public void setManagementUrl(String managementUrl) {
+        this.managementUrl = managementUrl;
+    }
+
+    public String getBaseUrl() {
+        return baseUrl;
+    }
+
+    public void setBaseUrl(String baseUrl) {
+        this.baseUrl = baseUrl;
+    }
+
+    public boolean isBearerOnly() {
+        return bearerOnly;
+    }
+
+    public void setBearerOnly(boolean bearerOnly) {
+        this.bearerOnly = bearerOnly;
+    }
+
+    public boolean isConsentRequired() {
+        return consentRequired;
+    }
+
+    public void setConsentRequired(boolean consentRequired) {
+        this.consentRequired = consentRequired;
+    }
+
+    public boolean isDirectGrantsOnly() {
+        return directGrantsOnly;
+    }
+
+    public void setDirectGrantsOnly(boolean directGrantsOnly) {
+        this.directGrantsOnly = directGrantsOnly;
+    }
+
+    public List<String> getDefaultRoles() {
+        return defaultRoles;
+    }
+
+    public void setDefaultRoles(List<String> defaultRoles) {
+        this.defaultRoles = defaultRoles;
+    }
+
+    public int getNodeReRegistrationTimeout() {
+        return nodeReRegistrationTimeout;
+    }
+
+    public void setNodeReRegistrationTimeout(int nodeReRegistrationTimeout) {
+        this.nodeReRegistrationTimeout = nodeReRegistrationTimeout;
+    }
+
+    public Map<String, Integer> getRegisteredNodes() {
+        return registeredNodes;
+    }
+
+    public void setRegisteredNodes(Map<String, Integer> registeredNodes) {
+        this.registeredNodes = registeredNodes;
+    }
+}
+
diff --git a/model/api/src/main/java/org/keycloak/models/entities/RoleEntity.java b/model/api/src/main/java/org/keycloak/models/entities/RoleEntity.java
index a961c70..a610d39 100644
--- a/model/api/src/main/java/org/keycloak/models/entities/RoleEntity.java
+++ b/model/api/src/main/java/org/keycloak/models/entities/RoleEntity.java
@@ -13,7 +13,7 @@ public class RoleEntity extends AbstractIdentifiableEntity {
     private List<String> compositeRoleIds;
 
     private String realmId;
-    private String applicationId;
+    private String clientId;
 
     public String getName() {
         return name;
@@ -47,11 +47,12 @@ public class RoleEntity extends AbstractIdentifiableEntity {
         this.realmId = realmId;
     }
 
-    public String getApplicationId() {
-        return applicationId;
+    public String getClientId() {
+        return clientId;
     }
 
-    public void setApplicationId(String applicationId) {
-        this.applicationId = applicationId;
+    public void setClientId(String clientId) {
+        this.clientId = clientId;
     }
+
 }
diff --git a/model/api/src/main/java/org/keycloak/models/LDAPConstants.java b/model/api/src/main/java/org/keycloak/models/LDAPConstants.java
index bf76be7..acab3e0 100644
--- a/model/api/src/main/java/org/keycloak/models/LDAPConstants.java
+++ b/model/api/src/main/java/org/keycloak/models/LDAPConstants.java
@@ -29,5 +29,40 @@ public class LDAPConstants {
     public static final String BATCH_SIZE_FOR_SYNC = "batchSizeForSync";
     public static final int DEFAULT_BATCH_SIZE_FOR_SYNC = 1000;
 
+    // Config option to specify if registrations will be synced or not
+    public static final String SYNC_REGISTRATIONS = "syncRegistrations";
+
+    // Applicable just for active directory
     public static final String USER_ACCOUNT_CONTROLS_AFTER_PASSWORD_UPDATE = "userAccountControlsAfterPasswordUpdate";
+
+    // Custom attributes on UserModel, which is mapped to LDAP
+    public static final String LDAP_ID = "LDAP_ID";
+    public static final String LDAP_ENTRY_DN = "LDAP_ENTRY_DN";
+
+
+    // Those are forked from Picketlink
+    public static final String GIVENNAME = "givenname";
+    public static final String CN = "cn";
+    public static final String SN = "sn";
+    public static final String EMAIL = "mail";
+    public static final String MEMBER = "member";
+    public static final String MEMBER_OF = "memberOf";
+    public static final String OBJECT_CLASS = "objectclass";
+    public static final String UID = "uid";
+    public static final String USER_PASSWORD_ATTRIBUTE = "userpassword";
+    public static final String GROUP_OF_NAMES = "groupOfNames";
+    public static final String GROUP_OF_ENTRIES = "groupOfEntries";
+    public static final String GROUP_OF_UNIQUE_NAMES = "groupOfUniqueNames";
+
+    public static final String COMMA = ",";
+    public static final String EQUAL = "=";
+    public static final String SPACE_STRING = " ";
+
+    public static final String CUSTOM_ATTRIBUTE_ENABLED = "enabled";
+    public static final String CUSTOM_ATTRIBUTE_CREATE_DATE = "createDate";
+    public static final String CUSTOM_ATTRIBUTE_EXPIRY_DATE = "expiryDate";
+    public static final String ENTRY_UUID = "entryUUID";
+    public static final String OBJECT_GUID = "objectGUID";
+    public static final String CREATE_TIMESTAMP = "createTimeStamp";
+    public static final String MODIFY_TIMESTAMP = "modifyTimeStamp";
 }
diff --git a/model/api/src/main/java/org/keycloak/models/RealmModel.java b/model/api/src/main/java/org/keycloak/models/RealmModel.java
index 81d53a6..17c88ea 100755
--- a/model/api/src/main/java/org/keycloak/models/RealmModel.java
+++ b/model/api/src/main/java/org/keycloak/models/RealmModel.java
@@ -19,15 +19,10 @@ public interface RealmModel extends RoleContainerModel {
     interface RealmCreationEvent extends ProviderEvent {
         RealmModel getCreatedRealm();
     }
+
     interface ClientCreationEvent extends ProviderEvent {
         ClientModel getCreatedClient();
     }
-    interface ApplicationCreationEvent extends ClientCreationEvent {
-        ApplicationModel getCreatedApplication();
-    }
-    interface OAuthClientCreationEvent extends ClientCreationEvent {
-        OAuthClientModel getCreatedOAuthClient();
-    }
 
     String getId();
 
@@ -150,33 +145,21 @@ public interface RealmModel extends RoleContainerModel {
 
     void updateDefaultRoles(String[] defaultRoles);
 
-    ClientModel findClient(String clientId);
+    Map<String, ClientModel> getClientNameMap();
 
-    Map<String, ApplicationModel> getApplicationNameMap();
+    List<ClientModel> getClients();
 
-    List<ApplicationModel> getApplications();
+    ClientModel addClient(String name);
 
-    ApplicationModel addApplication(String name);
+    ClientModel addClient(String id, String clientId);
 
-    ApplicationModel addApplication(String id, String name);
+    boolean removeClient(String id);
 
-    boolean removeApplication(String id);
-
-    ApplicationModel getApplicationById(String id);
-    ApplicationModel getApplicationByName(String name);
+    ClientModel getClientById(String id);
+    ClientModel getClientByClientId(String clientId);
 
     void updateRequiredCredentials(Set<String> creds);
 
-    OAuthClientModel addOAuthClient(String name);
-
-    OAuthClientModel addOAuthClient(String id, String name);
-
-    OAuthClientModel getOAuthClient(String name);
-    OAuthClientModel getOAuthClientById(String id);
-    boolean removeOAuthClient(String id);
-
-    List<OAuthClientModel> getOAuthClients();
-
     Map<String, String> getBrowserSecurityHeaders();
     void setBrowserSecurityHeaders(Map<String, String> headers);
 
@@ -249,11 +232,9 @@ public interface RealmModel extends RoleContainerModel {
 
     void setEnabledEventTypes(Set<String> enabledEventTypes);
 
-    ApplicationModel getMasterAdminApp();
-
-    void setMasterAdminApp(ApplicationModel app);
+    ClientModel getMasterAdminClient();
 
-    ClientModel findClientById(String id);
+    void setMasterAdminClient(ClientModel client);
 
     boolean isIdentityFederationEnabled();
 
diff --git a/model/api/src/main/java/org/keycloak/models/RealmProvider.java b/model/api/src/main/java/org/keycloak/models/RealmProvider.java
index 58328b2..17de99d 100755
--- a/model/api/src/main/java/org/keycloak/models/RealmProvider.java
+++ b/model/api/src/main/java/org/keycloak/models/RealmProvider.java
@@ -1,7 +1,6 @@
 package org.keycloak.models;
 
 import org.keycloak.provider.Provider;
-import org.keycloak.provider.ProviderEvent;
 
 import java.util.List;
 
@@ -19,8 +18,7 @@ public interface RealmProvider extends Provider {
     RealmModel getRealmByName(String name);
 
     RoleModel getRoleById(String id, RealmModel realm);
-    ApplicationModel getApplicationById(String id, RealmModel realm);
-    OAuthClientModel getOAuthClientById(String id, RealmModel realm);
+    ClientModel getClientById(String id, RealmModel realm);
     List<RealmModel> getRealms();
     boolean removeRealm(String id);
 
diff --git a/model/api/src/main/java/org/keycloak/models/UserModel.java b/model/api/src/main/java/org/keycloak/models/UserModel.java
index ee8ce80..770cf03 100755
--- a/model/api/src/main/java/org/keycloak/models/UserModel.java
+++ b/model/api/src/main/java/org/keycloak/models/UserModel.java
@@ -66,7 +66,7 @@ public interface UserModel {
     void updateCredentialDirectly(UserCredentialValueModel cred);
 
     Set<RoleModel> getRealmRoleMappings();
-    Set<RoleModel> getApplicationRoleMappings(ApplicationModel app);
+    Set<RoleModel> getClientRoleMappings(ClientModel app);
     boolean hasRole(RoleModel role);
     void grantRole(RoleModel role);
     Set<RoleModel> getRoleMappings();
diff --git a/model/api/src/main/java/org/keycloak/models/UserSessionProvider.java b/model/api/src/main/java/org/keycloak/models/UserSessionProvider.java
index b7421de..3a64206 100755
--- a/model/api/src/main/java/org/keycloak/models/UserSessionProvider.java
+++ b/model/api/src/main/java/org/keycloak/models/UserSessionProvider.java
@@ -3,7 +3,6 @@ package org.keycloak.models;
 import org.keycloak.provider.Provider;
 
 import java.util.List;
-import java.util.Map;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
diff --git a/model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java b/model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java
index af0b92d..8ee918b 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java
@@ -1,8 +1,6 @@
 package org.keycloak.models.utils;
 
 import org.bouncycastle.openssl.PEMWriter;
-import org.keycloak.models.ApplicationModel;
-import org.keycloak.models.ClaimMask;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
@@ -174,8 +172,8 @@ public final class KeycloakModelUtils {
         return UUID.randomUUID().toString();
     }
 
-    public static ApplicationModel createApplication(RealmModel realm, String name) {
-        ApplicationModel app = realm.addApplication(name);
+    public static ClientModel createClient(RealmModel realm, String name) {
+        ClientModel app = realm.addClient(name);
         generateSecret(app);
         app.setFullScopeAllowed(true);
 
@@ -247,7 +245,7 @@ public final class KeycloakModelUtils {
         }
     }
 
-    public static String getMasterRealmAdminApplicationName(RealmModel realm) {
+    public static String getMasterRealmAdminApplicationClientId(RealmModel realm) {
         return realm.getName() + "-realm";
     }
 }
diff --git a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
index 78a64ca..dc1124a 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
@@ -1,13 +1,10 @@
 package org.keycloak.models.utils;
 
-import org.keycloak.models.ApplicationModel;
-import org.keycloak.models.ClaimMask;
-import org.keycloak.models.ClientIdentityProviderMappingModel;
 import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientIdentityProviderMappingModel;
 import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.FederatedIdentityModel;
 import org.keycloak.models.IdentityProviderModel;
-import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.ProtocolMapperModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RequiredCredentialModel;
@@ -17,12 +14,11 @@ import org.keycloak.models.UserFederationProviderModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.UserSessionModel;
 import org.keycloak.representations.idm.ApplicationRepresentation;
-import org.keycloak.representations.idm.ClaimRepresentation;
 import org.keycloak.representations.idm.ClientIdentityProviderMappingRepresentation;
+import org.keycloak.representations.idm.ClientRepresentation;
 import org.keycloak.representations.idm.CredentialRepresentation;
 import org.keycloak.representations.idm.FederatedIdentityRepresentation;
 import org.keycloak.representations.idm.IdentityProviderRepresentation;
-import org.keycloak.representations.idm.OAuthClientRepresentation;
 import org.keycloak.representations.idm.ProtocolMapperRepresentation;
 import org.keycloak.representations.idm.RealmEventsConfigRepresentation;
 import org.keycloak.representations.idm.RealmRepresentation;
@@ -30,6 +26,7 @@ import org.keycloak.representations.idm.RoleRepresentation;
 import org.keycloak.representations.idm.UserFederationProviderRepresentation;
 import org.keycloak.representations.idm.UserRepresentation;
 import org.keycloak.representations.idm.UserSessionRepresentation;
+import org.keycloak.util.Time;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -211,63 +208,60 @@ public class ModelToRepresentation {
     public static UserSessionRepresentation toRepresentation(UserSessionModel session) {
         UserSessionRepresentation rep = new UserSessionRepresentation();
         rep.setId(session.getId());
-        rep.setStart(((long)session.getStarted()) * 1000L);
-        rep.setLastAccess(((long)session.getLastSessionRefresh())* 1000L);
+        rep.setStart(Time.toMillis(session.getStarted()));
+        rep.setLastAccess(Time.toMillis(session.getLastSessionRefresh()));
         rep.setUser(session.getUser().getUsername());
         rep.setIpAddress(session.getIpAddress());
         for (ClientSessionModel clientSession : session.getClientSessions()) {
             ClientModel client = clientSession.getClient();
-            if (client instanceof ApplicationModel) {
-                rep.getApplications().put(client.getId(), client.getClientId());
-            } else if (client instanceof OAuthClientModel) {
-                rep.getClients().put(client.getId(), client.getClientId());
-            }
+            rep.getClients().put(client.getId(), client.getClientId());
         }
         return rep;
     }
 
-    public static ApplicationRepresentation toRepresentation(ApplicationModel applicationModel) {
-        ApplicationRepresentation rep = new ApplicationRepresentation();
-        rep.setId(applicationModel.getId());
-        rep.setName(applicationModel.getName());
-        rep.setEnabled(applicationModel.isEnabled());
-        rep.setAdminUrl(applicationModel.getManagementUrl());
-        rep.setPublicClient(applicationModel.isPublicClient());
-        rep.setFrontchannelLogout(applicationModel.isFrontchannelLogout());
-        rep.setProtocol(applicationModel.getProtocol());
-        rep.setAttributes(applicationModel.getAttributes());
-        rep.setFullScopeAllowed(applicationModel.isFullScopeAllowed());
-        rep.setBearerOnly(applicationModel.isBearerOnly());
-        rep.setSurrogateAuthRequired(applicationModel.isSurrogateAuthRequired());
-        rep.setBaseUrl(applicationModel.getBaseUrl());
-        rep.setNotBefore(applicationModel.getNotBefore());
-        rep.setNodeReRegistrationTimeout(applicationModel.getNodeReRegistrationTimeout());
-
-        Set<String> redirectUris = applicationModel.getRedirectUris();
+    public static ClientRepresentation toRepresentation(ClientModel clientModel) {
+        ClientRepresentation rep = new ClientRepresentation();
+        rep.setId(clientModel.getId());
+        rep.setClientId(clientModel.getClientId());
+        rep.setEnabled(clientModel.isEnabled());
+        rep.setAdminUrl(clientModel.getManagementUrl());
+        rep.setPublicClient(clientModel.isPublicClient());
+        rep.setFrontchannelLogout(clientModel.isFrontchannelLogout());
+        rep.setProtocol(clientModel.getProtocol());
+        rep.setAttributes(clientModel.getAttributes());
+        rep.setFullScopeAllowed(clientModel.isFullScopeAllowed());
+        rep.setBearerOnly(clientModel.isBearerOnly());
+        rep.setConsentRequired(clientModel.isConsentRequired());
+        rep.setSurrogateAuthRequired(clientModel.isSurrogateAuthRequired());
+        rep.setBaseUrl(clientModel.getBaseUrl());
+        rep.setNotBefore(clientModel.getNotBefore());
+        rep.setNodeReRegistrationTimeout(clientModel.getNodeReRegistrationTimeout());
+
+        Set<String> redirectUris = clientModel.getRedirectUris();
         if (redirectUris != null) {
-            rep.setRedirectUris(new LinkedList<String>(redirectUris));
+            rep.setRedirectUris(new LinkedList<>(redirectUris));
         }
 
-        Set<String> webOrigins = applicationModel.getWebOrigins();
+        Set<String> webOrigins = clientModel.getWebOrigins();
         if (webOrigins != null) {
-            rep.setWebOrigins(new LinkedList<String>(webOrigins));
+            rep.setWebOrigins(new LinkedList<>(webOrigins));
         }
 
-        if (!applicationModel.getDefaultRoles().isEmpty()) {
-            rep.setDefaultRoles(applicationModel.getDefaultRoles().toArray(new String[0]));
+        if (!clientModel.getDefaultRoles().isEmpty()) {
+            rep.setDefaultRoles(clientModel.getDefaultRoles().toArray(new String[0]));
         }
 
-        if (!applicationModel.getRegisteredNodes().isEmpty()) {
-            rep.setRegisteredNodes(new HashMap<String, Integer>(applicationModel.getRegisteredNodes()));
+        if (!clientModel.getRegisteredNodes().isEmpty()) {
+            rep.setRegisteredNodes(new HashMap<>(clientModel.getRegisteredNodes()));
         }
 
-        if (!applicationModel.getIdentityProviders().isEmpty()) {
-            rep.setIdentityProviders(toRepresentation(applicationModel.getIdentityProviders()));
+        if (!clientModel.getIdentityProviders().isEmpty()) {
+            rep.setIdentityProviders(toRepresentation(clientModel.getIdentityProviders()));
         }
 
-        if (!applicationModel.getProtocolMappers().isEmpty()) {
-            List<ProtocolMapperRepresentation> mappings = new LinkedList<ProtocolMapperRepresentation>();
-            for (ProtocolMapperModel model : applicationModel.getProtocolMappers()) {
+        if (!clientModel.getProtocolMappers().isEmpty()) {
+            List<ProtocolMapperRepresentation> mappings = new LinkedList<>();
+            for (ProtocolMapperModel model : clientModel.getProtocolMappers()) {
                 mappings.add(toRepresentation(model));
             }
             rep.setProtocolMappers(mappings);
@@ -291,43 +285,6 @@ public class ModelToRepresentation {
         return representations;
     }
 
-    public static OAuthClientRepresentation toRepresentation(OAuthClientModel model) {
-        OAuthClientRepresentation rep = new OAuthClientRepresentation();
-        rep.setId(model.getId());
-        rep.setName(model.getClientId());
-        rep.setEnabled(model.isEnabled());
-        rep.setPublicClient(model.isPublicClient());
-        rep.setFrontchannelLogout(model.isFrontchannelLogout());
-        rep.setProtocol(model.getProtocol());
-        rep.setAttributes(model.getAttributes());
-        rep.setFullScopeAllowed(model.isFullScopeAllowed());
-        rep.setDirectGrantsOnly(model.isDirectGrantsOnly());
-        Set<String> redirectUris = model.getRedirectUris();
-        if (redirectUris != null) {
-            rep.setRedirectUris(new LinkedList<String>(redirectUris));
-        }
-
-        Set<String> webOrigins = model.getWebOrigins();
-        if (webOrigins != null) {
-            rep.setWebOrigins(new LinkedList<String>(webOrigins));
-        }
-        rep.setNotBefore(model.getNotBefore());
-
-        if (!model.getIdentityProviders().isEmpty()) {
-            rep.setIdentityProviders(toRepresentation(model.getIdentityProviders()));
-        }
-
-        if (!model.getProtocolMappers().isEmpty()) {
-                List<ProtocolMapperRepresentation> mappings = new LinkedList<ProtocolMapperRepresentation>();
-                for (ProtocolMapperModel mapper : model.getProtocolMappers()) {
-                    mappings.add(toRepresentation(mapper));
-                }
-                rep.setProtocolMappers(mappings);
-        }
-
-        return rep;
-    }
-
     public static UserFederationProviderRepresentation toRepresentation(UserFederationProviderModel model) {
         UserFederationProviderRepresentation rep = new UserFederationProviderRepresentation();
         rep.setId(model.getId());
diff --git a/model/api/src/main/java/org/keycloak/models/utils/reflection/NamedPropertyCriteria.java b/model/api/src/main/java/org/keycloak/models/utils/reflection/NamedPropertyCriteria.java
new file mode 100644
index 0000000..fc3b538
--- /dev/null
+++ b/model/api/src/main/java/org/keycloak/models/utils/reflection/NamedPropertyCriteria.java
@@ -0,0 +1,40 @@
+package org.keycloak.models.utils.reflection;
+
+import java.beans.Introspector;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+/**
+ * A criteria that matches a property based on name
+ *
+ * @see PropertyCriteria
+ */
+public class NamedPropertyCriteria implements PropertyCriteria {
+    private final String[] propertyNames;
+
+    public NamedPropertyCriteria(String... propertyNames) {
+        this.propertyNames = propertyNames;
+    }
+
+    public boolean fieldMatches(Field f) {
+        for (String propertyName : propertyNames) {
+            if (propertyName.equals(f.getName())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean methodMatches(Method m) {
+        String[] validPrefix = {"get", "is"};
+        for (String propertyName : propertyNames) {
+            for (String prefix : validPrefix) {
+                if (m.getName().startsWith(prefix) &&
+                        Introspector.decapitalize(m.getName().substring(prefix.length())).equals(propertyName)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+}
diff --git a/model/api/src/main/java/org/keycloak/models/utils/reflection/TypedPropertyCriteria.java b/model/api/src/main/java/org/keycloak/models/utils/reflection/TypedPropertyCriteria.java
new file mode 100644
index 0000000..93688a4
--- /dev/null
+++ b/model/api/src/main/java/org/keycloak/models/utils/reflection/TypedPropertyCriteria.java
@@ -0,0 +1,71 @@
+package org.keycloak.models.utils.reflection;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+/**
+ * A criteria that matches a property based on its type
+ *
+ * @see PropertyCriteria
+ */
+public class TypedPropertyCriteria implements PropertyCriteria {
+
+    /**
+     * <p> Different options can be used to match a specific property based on its type. Regardless of the option
+     * chosen, if the property type equals the <code>propertyClass</code> it will be selected. <p/> <ul> <li>SUB_TYPE:
+     * Also consider properties where its type is a subtype of <code>propertyClass</code>. .</li> <li>SUPER_TYPE: Also
+     * consider properties where its type is a superclass or superinterface of <code>propertyClass</code>. .</li> </ul>
+     * </p>
+     */
+    public static enum MatchOption {
+        SUB_TYPE, SUPER_TYPE, ALL
+    }
+
+    private final Class<?> propertyClass;
+    private final MatchOption matchOption;
+
+    public TypedPropertyCriteria(Class<?> propertyClass) {
+        this(propertyClass, null);
+    }
+
+    public TypedPropertyCriteria(Class<?> propertyClass, MatchOption matchOption) {
+        if (propertyClass == null) {
+            throw new IllegalArgumentException("Property class can not be null.");
+        }
+        this.propertyClass = propertyClass;
+        this.matchOption = matchOption;
+    }
+
+    public boolean fieldMatches(Field f) {
+        return match(f.getType());
+    }
+
+    public boolean methodMatches(Method m) {
+        return match(m.getReturnType());
+    }
+
+    private boolean match(Class<?> type) {
+        if (propertyClass.equals(type)) {
+            return true;
+        } else {
+            boolean matchSubType = propertyClass.isAssignableFrom(type);
+
+            if (MatchOption.SUB_TYPE == this.matchOption) {
+                return matchSubType;
+            }
+
+            boolean matchSuperType = type.isAssignableFrom(propertyClass);
+
+            if (MatchOption.SUPER_TYPE == this.matchOption) {
+                return matchSuperType;
+            }
+
+            if (MatchOption.ALL == this.matchOption) {
+                return matchSubType || matchSuperType;
+            }
+        }
+
+        return false;
+    }
+}
+
diff --git a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index 4ebc2d0..f830ac1 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -4,7 +4,6 @@ import net.iharder.Base64;
 import org.jboss.logging.Logger;
 import org.keycloak.enums.SslRequired;
 import org.keycloak.migration.MigrationProvider;
-import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.BrowserSecurityHeaders;
 import org.keycloak.models.ClaimMask;
 import org.keycloak.models.ClientIdentityProviderMappingModel;
@@ -12,7 +11,6 @@ import org.keycloak.models.ClientModel;
 import org.keycloak.models.FederatedIdentityModel;
 import org.keycloak.models.IdentityProviderModel;
 import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.PasswordPolicy;
 import org.keycloak.models.ProtocolMapperModel;
 import org.keycloak.models.RealmModel;
@@ -24,6 +22,7 @@ import org.keycloak.models.UserModel;
 import org.keycloak.representations.idm.ApplicationRepresentation;
 import org.keycloak.representations.idm.ClaimRepresentation;
 import org.keycloak.representations.idm.ClientIdentityProviderMappingRepresentation;
+import org.keycloak.representations.idm.ClientRepresentation;
 import org.keycloak.representations.idm.CredentialRepresentation;
 import org.keycloak.representations.idm.FederatedIdentityRepresentation;
 import org.keycloak.representations.idm.IdentityProviderRepresentation;
@@ -52,6 +51,7 @@ public class RepresentationToModel {
 
     public static void importRealm(KeycloakSession session, RealmRepresentation rep, RealmModel newRealm) {
         convertDeprecatedSocialProviders(rep);
+        convertDeprecatedApplications(session, rep);
 
         newRealm.setName(rep.getRealm());
         if (rep.isEnabled() != null) newRealm.setEnabled(rep.isEnabled());
@@ -129,8 +129,8 @@ public class RepresentationToModel {
 
         importIdentityProviders(rep, newRealm);
 
-        if (rep.getApplications() != null) {
-            Map<String, ApplicationModel> appMap = createApplications(session, rep, newRealm);
+        if (rep.getClients() != null) {
+            createClients(session, rep, newRealm);
         }
 
         if (rep.getRoles() != null) {
@@ -139,15 +139,15 @@ public class RepresentationToModel {
                     createRole(newRealm, roleRep);
                 }
             }
-            if (rep.getRoles().getApplication() != null) {
-                for (Map.Entry<String, List<RoleRepresentation>> entry : rep.getRoles().getApplication().entrySet()) {
-                    ApplicationModel app = newRealm.getApplicationByName(entry.getKey());
-                    if (app == null) {
+            if (rep.getRoles().getClient() != null) {
+                for (Map.Entry<String, List<RoleRepresentation>> entry : rep.getRoles().getClient().entrySet()) {
+                    ClientModel client = newRealm.getClientByClientId(entry.getKey());
+                    if (client == null) {
                         throw new RuntimeException("App doesn't exist in role definitions: " + entry.getKey());
                     }
                     for (RoleRepresentation roleRep : entry.getValue()) {
                         // Application role may already exists (for example if it is defaultRole)
-                        RoleModel role = roleRep.getId()!=null ? app.addRole(roleRep.getId(), roleRep.getName()) : app.addRole(roleRep.getName());
+                        RoleModel role = roleRep.getId()!=null ? client.addRole(roleRep.getId(), roleRep.getName()) : client.addRole(roleRep.getName());
                         role.setDescription(roleRep.getDescription());
                     }
                 }
@@ -159,14 +159,14 @@ public class RepresentationToModel {
                     addComposites(role, roleRep, newRealm);
                 }
             }
-            if (rep.getRoles().getApplication() != null) {
-                for (Map.Entry<String, List<RoleRepresentation>> entry : rep.getRoles().getApplication().entrySet()) {
-                    ApplicationModel app = newRealm.getApplicationByName(entry.getKey());
-                    if (app == null) {
+            if (rep.getRoles().getClient() != null) {
+                for (Map.Entry<String, List<RoleRepresentation>> entry : rep.getRoles().getClient().entrySet()) {
+                    ClientModel client = newRealm.getClientByClientId(entry.getKey());
+                    if (client == null) {
                         throw new RuntimeException("App doesn't exist in role definitions: " + entry.getKey());
                     }
                     for (RoleRepresentation roleRep : entry.getValue()) {
-                        RoleModel role = app.getRole(roleRep.getName());
+                        RoleModel role = client.getRole(roleRep.getName());
                         addComposites(role, roleRep, newRealm);
                     }
                 }
@@ -179,39 +179,34 @@ public class RepresentationToModel {
                 newRealm.addDefaultRole(roleString.trim());
             }
         }
-        // Setup application default roles
-        if (rep.getApplications() != null) {
-            for (ApplicationRepresentation resourceRep : rep.getApplications()) {
+        // Setup client default roles
+        if (rep.getClients() != null) {
+            for (ClientRepresentation resourceRep : rep.getClients()) {
                 if (resourceRep.getDefaultRoles() != null) {
-                    ApplicationModel appModel = newRealm.getApplicationByName(resourceRep.getName());
-                    appModel.updateDefaultRoles(resourceRep.getDefaultRoles());
+                    ClientModel clientModel = newRealm.getClientByClientId(resourceRep.getClientId());
+                    clientModel.updateDefaultRoles(resourceRep.getDefaultRoles());
                 }
             }
         }
 
-        if (rep.getOauthClients() != null) {
-            createOAuthClients(session, rep, newRealm);
-        }
-
-
-        // Now that all possible roles and applications are created, create scope mappings
+        // Now that all possible roles and clients are created, create scope mappings
 
-        Map<String, ApplicationModel> appMap = newRealm.getApplicationNameMap();
+        Map<String, ClientModel> appMap = newRealm.getClientNameMap();
 
-        if (rep.getApplicationScopeMappings() != null) {
+        if (rep.getClientScopeMappings() != null) {
 
-            for (Map.Entry<String, List<ScopeMappingRepresentation>> entry : rep.getApplicationScopeMappings().entrySet()) {
-                ApplicationModel app = appMap.get(entry.getKey());
+            for (Map.Entry<String, List<ScopeMappingRepresentation>> entry : rep.getClientScopeMappings().entrySet()) {
+                ClientModel app = appMap.get(entry.getKey());
                 if (app == null) {
-                    throw new RuntimeException("Unable to find application role mappings for app: " + entry.getKey());
+                    throw new RuntimeException("Unable to find client role mappings for client: " + entry.getKey());
                 }
-                createApplicationScopeMappings(newRealm, app, entry.getValue());
+                createClientScopeMappings(newRealm, app, entry.getValue());
             }
         }
 
         if (rep.getScopeMappings() != null) {
             for (ScopeMappingRepresentation scope : rep.getScopeMappings()) {
-                ClientModel client = newRealm.findClient(scope.getClient());
+                ClientModel client = newRealm.getClientByClientId(scope.getClient());
                 if (client == null) {
                     throw new RuntimeException("Unknown client specification in realm scope mappings");
                 }
@@ -290,10 +285,6 @@ public class RepresentationToModel {
                 rep.setIdentityProviders(identityProviders);
             }
         }
-
-        rep.setSocial(null);
-        rep.setSocialProviders(null);
-        rep.setUpdateProfileOnInitialSocialLogin(false);
     }
 
     private static void convertDeprecatedSocialProviders(UserRepresentation user) {
@@ -314,15 +305,73 @@ public class RepresentationToModel {
         user.setSocialLinks(null);
     }
 
-    private static List<ProtocolMapperRepresentation> convertDeprecatedClaimsMask(KeycloakSession session, ClaimRepresentation claimRep) {
-        if (claimRep == null) {
-            return null;
+    private static void convertDeprecatedApplications(KeycloakSession session, RealmRepresentation realm) {
+        if (realm.getApplications() != null || realm.getOauthClients() != null) {
+            if (realm.getClients() == null) {
+                realm.setClients(new LinkedList<ClientRepresentation>());
+            }
+
+            List<ApplicationRepresentation> clients = new LinkedList<>();
+            if (realm.getApplications() != null) {
+                clients.addAll(realm.getApplications());
+            }
+            if (realm.getOauthClients() != null) {
+                clients.addAll(realm.getOauthClients());
+            }
+
+            for (ApplicationRepresentation app : clients) {
+                app.setClientId(app.getName());
+                app.setName(null);
+
+                if (app instanceof OAuthClientRepresentation) {
+                    app.setConsentRequired(true);
+                    app.setFullScopeAllowed(false);
+                }
+
+                if (app.getProtocolMappers() == null && app.getClaims() != null) {
+                    long mask = getClaimsMask(app.getClaims());
+                    List<ProtocolMapperRepresentation> convertedProtocolMappers = session.getProvider(MigrationProvider.class).getMappersForClaimMask(mask);
+                    app.setProtocolMappers(convertedProtocolMappers);
+                    app.setClaims(null);
+                }
+
+                realm.getClients().add(app);
+            }
+        }
+
+        if (realm.getApplicationScopeMappings() != null && realm.getClientScopeMappings() == null) {
+            realm.setClientScopeMappings(realm.getApplicationScopeMappings());
+        }
+
+        if (realm.getRoles() != null && realm.getRoles().getApplication() != null && realm.getRoles().getClient() == null) {
+            realm.getRoles().setClient(realm.getRoles().getApplication());
+        }
+
+        if (realm.getUsers() != null) {
+            for (UserRepresentation user : realm.getUsers()) {
+                if (user.getApplicationRoles() != null && user.getClientRoles() == null) {
+                    user.setClientRoles(user.getApplicationRoles());
+                }
+            }
+        }
+
+        if (realm.getRoles() != null && realm.getRoles().getRealm() != null) {
+            for (RoleRepresentation role : realm.getRoles().getRealm()) {
+                if (role.getComposites() != null && role.getComposites().getApplication() != null && role.getComposites().getClient() == null) {
+                    role.getComposites().setClient(role.getComposites().getApplication());
+                }
+            }
         }
 
-        logger.warn("Using deprecated 'claims' configuration in JSON representation. It will be removed in future versions");
-        long mask = getClaimsMask(claimRep);
-        MigrationProvider migrationProvider = session.getProvider(MigrationProvider.class);
-        return migrationProvider.getMappersForClaimMask(mask);
+        if (realm.getRoles() != null && realm.getRoles().getClient() != null) {
+            for (Map.Entry<String, List<RoleRepresentation>> clientRoles : realm.getRoles().getClient().entrySet()) {
+                for (RoleRepresentation role : clientRoles.getValue()) {
+                    if (role.getComposites() != null && role.getComposites().getApplication() != null && role.getComposites().getClient() == null) {
+                        role.getComposites().setClient(role.getComposites().getApplication());
+                    }
+                }
+            }
+        }
     }
 
     public static void updateRealm(RealmRepresentation rep, RealmModel realm) {
@@ -432,31 +481,30 @@ public class RepresentationToModel {
                 role.addCompositeRole(realmRole);
             }
         }
-        if (roleRep.getComposites().getApplication() != null) {
-            for (Map.Entry<String, List<String>> entry : roleRep.getComposites().getApplication().entrySet()) {
-                ApplicationModel app = realm.getApplicationByName(entry.getKey());
-                if (app == null) {
+        if (roleRep.getComposites().getClient() != null) {
+            for (Map.Entry<String, List<String>> entry : roleRep.getComposites().getClient().entrySet()) {
+                ClientModel client = realm.getClientByClientId(entry.getKey());
+                if (client == null) {
                     throw new RuntimeException("App doesn't exist in role definitions: " + roleRep.getName());
                 }
                 for (String roleStr : entry.getValue()) {
-                    RoleModel appRole = app.getRole(roleStr);
-                    if (appRole == null) throw new RuntimeException("Unable to find composite app role: " + roleStr);
-                    role.addCompositeRole(appRole);
+                    RoleModel clientRole = client.getRole(roleStr);
+                    if (clientRole == null) throw new RuntimeException("Unable to find composite client role: " + roleStr);
+                    role.addCompositeRole(clientRole);
                 }
-
             }
 
         }
 
     }
 
-    // APPLICATIONS
+    // CLIENTS
 
-    private static Map<String, ApplicationModel> createApplications(KeycloakSession session, RealmRepresentation rep, RealmModel realm) {
-        Map<String, ApplicationModel> appMap = new HashMap<String, ApplicationModel>();
-        for (ApplicationRepresentation resourceRep : rep.getApplications()) {
-            ApplicationModel app = createApplication(session, realm, resourceRep, false);
-            appMap.put(app.getName(), app);
+    private static Map<String, ClientModel> createClients(KeycloakSession session, RealmRepresentation rep, RealmModel realm) {
+        Map<String, ClientModel> appMap = new HashMap<String, ClientModel>();
+        for (ClientRepresentation resourceRep : rep.getClients()) {
+            ClientModel app = createClient(session, realm, resourceRep, false);
+            appMap.put(app.getClientId(), app);
         }
         return appMap;
     }
@@ -468,63 +516,57 @@ public class RepresentationToModel {
      * @param resourceRep
      * @return
      */
-    public static ApplicationModel createApplication(KeycloakSession session, RealmModel realm, ApplicationRepresentation resourceRep, boolean addDefaultRoles) {
-        logger.debug("************ CREATE APPLICATION: {0}" + resourceRep.getName());
-
-        if (resourceRep.getProtocolMappers() == null) {
-            List<ProtocolMapperRepresentation> convertedProtocolMappers = convertDeprecatedClaimsMask(session, resourceRep.getClaims());
-            if (convertedProtocolMappers != null) {
-                resourceRep.setProtocolMappers(convertedProtocolMappers);
-            }
-        }
+    public static ClientModel createClient(KeycloakSession session, RealmModel realm, ClientRepresentation resourceRep, boolean addDefaultRoles) {
+        logger.debug("Create client: {0}" + resourceRep.getClientId());
 
-        ApplicationModel applicationModel = resourceRep.getId()!=null ? realm.addApplication(resourceRep.getId(), resourceRep.getName()) : realm.addApplication(resourceRep.getName());
-        if (resourceRep.isEnabled() != null) applicationModel.setEnabled(resourceRep.isEnabled());
-        applicationModel.setManagementUrl(resourceRep.getAdminUrl());
+        ClientModel client = resourceRep.getId()!=null ? realm.addClient(resourceRep.getId(), resourceRep.getClientId()) : realm.addClient(resourceRep.getClientId());
+        if (resourceRep.isEnabled() != null) client.setEnabled(resourceRep.isEnabled());
+        client.setManagementUrl(resourceRep.getAdminUrl());
         if (resourceRep.isSurrogateAuthRequired() != null)
-            applicationModel.setSurrogateAuthRequired(resourceRep.isSurrogateAuthRequired());
-        applicationModel.setBaseUrl(resourceRep.getBaseUrl());
-        if (resourceRep.isBearerOnly() != null) applicationModel.setBearerOnly(resourceRep.isBearerOnly());
-        if (resourceRep.isPublicClient() != null) applicationModel.setPublicClient(resourceRep.isPublicClient());
-        if (resourceRep.isFrontchannelLogout() != null) applicationModel.setFrontchannelLogout(resourceRep.isFrontchannelLogout());
-        if (resourceRep.getProtocol() != null) applicationModel.setProtocol(resourceRep.getProtocol());
+            client.setSurrogateAuthRequired(resourceRep.isSurrogateAuthRequired());
+        client.setBaseUrl(resourceRep.getBaseUrl());
+        if (resourceRep.isBearerOnly() != null) client.setBearerOnly(resourceRep.isBearerOnly());
+        if (resourceRep.isConsentRequired() != null) client.setConsentRequired(resourceRep.isConsentRequired());
+        if (resourceRep.isPublicClient() != null) client.setPublicClient(resourceRep.isPublicClient());
+        if (resourceRep.isFrontchannelLogout() != null) client.setFrontchannelLogout(resourceRep.isFrontchannelLogout());
+        if (resourceRep.getProtocol() != null) client.setProtocol(resourceRep.getProtocol());
         if (resourceRep.isFullScopeAllowed() != null) {
-            applicationModel.setFullScopeAllowed(resourceRep.isFullScopeAllowed());
+            client.setFullScopeAllowed(resourceRep.isFullScopeAllowed());
         } else {
-            applicationModel.setFullScopeAllowed(true);
+            client.setFullScopeAllowed(!client.isConsentRequired());
         }
         if (resourceRep.getNodeReRegistrationTimeout() != null) {
-            applicationModel.setNodeReRegistrationTimeout(resourceRep.getNodeReRegistrationTimeout());
+            client.setNodeReRegistrationTimeout(resourceRep.getNodeReRegistrationTimeout());
         } else {
-            applicationModel.setNodeReRegistrationTimeout(-1);
+            client.setNodeReRegistrationTimeout(-1);
         }
-        applicationModel.updateApplication();
+        client.updateClient();
 
         if (resourceRep.getNotBefore() != null) {
-            applicationModel.setNotBefore(resourceRep.getNotBefore());
+            client.setNotBefore(resourceRep.getNotBefore());
         }
 
-        applicationModel.setSecret(resourceRep.getSecret());
-        if (applicationModel.getSecret() == null) {
-            KeycloakModelUtils.generateSecret(applicationModel);
+        client.setSecret(resourceRep.getSecret());
+        if (client.getSecret() == null) {
+            KeycloakModelUtils.generateSecret(client);
         }
 
         if (resourceRep.getAttributes() != null) {
             for (Map.Entry<String, String> entry : resourceRep.getAttributes().entrySet()) {
-                applicationModel.setAttribute(entry.getKey(), entry.getValue());
+                client.setAttribute(entry.getKey(), entry.getValue());
             }
         }
 
 
         if (resourceRep.getRedirectUris() != null) {
             for (String redirectUri : resourceRep.getRedirectUris()) {
-                applicationModel.addRedirectUri(redirectUri);
+                client.addRedirectUri(redirectUri);
             }
         }
         if (resourceRep.getWebOrigins() != null) {
             for (String webOrigin : resourceRep.getWebOrigins()) {
-                logger.debugv("Application: {0} webOrigin: {1}", resourceRep.getName(), webOrigin);
-                applicationModel.addWebOrigin(webOrigin);
+                logger.debugv("Client: {0} webOrigin: {1}", resourceRep.getClientId(), webOrigin);
+                client.addWebOrigin(webOrigin);
             }
         } else {
             // add origins from redirect uris
@@ -538,45 +580,46 @@ public class RepresentationToModel {
                         if (uri.getPort() != -1) {
                             origin += ":" + uri.getPort();
                         }
-                        logger.debugv("adding default application origin: {0}" , origin);
+                        logger.debugv("adding default client origin: {0}" , origin);
                         origins.add(origin);
                     }
                 }
                 if (origins.size() > 0) {
-                    applicationModel.setWebOrigins(origins);
+                    client.setWebOrigins(origins);
                 }
             }
         }
 
         if (resourceRep.getRegisteredNodes() != null) {
             for (Map.Entry<String, Integer> entry : resourceRep.getRegisteredNodes().entrySet()) {
-                applicationModel.registerNode(entry.getKey(), entry.getValue());
+                client.registerNode(entry.getKey(), entry.getValue());
             }
         }
 
         if (addDefaultRoles && resourceRep.getDefaultRoles() != null) {
-            applicationModel.updateDefaultRoles(resourceRep.getDefaultRoles());
+            client.updateDefaultRoles(resourceRep.getDefaultRoles());
         }
 
         if (resourceRep.getProtocolMappers() != null) {
             // first, remove all default/built in mappers
-            Set<ProtocolMapperModel> mappers = applicationModel.getProtocolMappers();
-            for (ProtocolMapperModel mapper : mappers) applicationModel.removeProtocolMapper(mapper);
+            Set<ProtocolMapperModel> mappers = client.getProtocolMappers();
+            for (ProtocolMapperModel mapper : mappers) client.removeProtocolMapper(mapper);
 
             for (ProtocolMapperRepresentation mapper : resourceRep.getProtocolMappers()) {
-                applicationModel.addProtocolMapper(toModel(mapper));
+                client.addProtocolMapper(toModel(mapper));
             }
         }
 
-        applicationModel.updateIdentityProviders(toModel(resourceRep.getIdentityProviders(), realm));
+        client.updateIdentityProviders(toModel(resourceRep.getIdentityProviders(), realm));
 
-        return applicationModel;
+        return client;
     }
 
-    public static void updateApplication(ApplicationRepresentation rep, ApplicationModel resource) {
-        if (rep.getName() != null) resource.setName(rep.getName());
+    public static void updateClient(ClientRepresentation rep, ClientModel resource) {
+        if (rep.getClientId() != null) resource.setClientId(rep.getClientId());
         if (rep.isEnabled() != null) resource.setEnabled(rep.isEnabled());
         if (rep.isBearerOnly() != null) resource.setBearerOnly(rep.isBearerOnly());
+        if (rep.isConsentRequired() != null) resource.setConsentRequired(rep.isConsentRequired());
         if (rep.isPublicClient() != null) resource.setPublicClient(rep.isPublicClient());
         if (rep.isFullScopeAllowed() != null) resource.setFullScopeAllowed(rep.isFullScopeAllowed());
         if (rep.isFrontchannelLogout() != null) resource.setFrontchannelLogout(rep.isFrontchannelLogout());
@@ -584,7 +627,7 @@ public class RepresentationToModel {
         if (rep.getBaseUrl() != null) resource.setBaseUrl(rep.getBaseUrl());
         if (rep.isSurrogateAuthRequired() != null) resource.setSurrogateAuthRequired(rep.isSurrogateAuthRequired());
         if (rep.getNodeReRegistrationTimeout() != null) resource.setNodeReRegistrationTimeout(rep.getNodeReRegistrationTimeout());
-        resource.updateApplication();
+        resource.updateClient();
 
         if (rep.getProtocol() != null) resource.setProtocol(rep.getProtocol());
         if (rep.getAttributes() != null) {
@@ -676,93 +719,18 @@ public class RepresentationToModel {
         return mask;
     }
 
-    // OAuth clients
-
-    private static void createOAuthClients(KeycloakSession session, RealmRepresentation realmRep, RealmModel realm) {
-        for (OAuthClientRepresentation rep : realmRep.getOauthClients()) {
-            createOAuthClient(session, rep, realm);
-        }
-    }
-
-    public static OAuthClientModel createOAuthClient(String id, String name, RealmModel realm) {
-        OAuthClientModel model = id!=null ? realm.addOAuthClient(id, name) : realm.addOAuthClient(name);
-        KeycloakModelUtils.generateSecret(model);
-        return model;
-    }
-
-    public static OAuthClientModel createOAuthClient(KeycloakSession session, OAuthClientRepresentation rep, RealmModel realm) {
-        OAuthClientModel model = createOAuthClient(rep.getId(), rep.getName(), realm);
-
-        model.updateIdentityProviders(toModel(rep.getIdentityProviders(), realm));
-
-        updateOAuthClient(session, rep, model);
-        return model;
-    }
-
-    public static void updateOAuthClient(KeycloakSession session, OAuthClientRepresentation rep, OAuthClientModel model) {
-        if (rep.getProtocolMappers() == null) {
-            List<ProtocolMapperRepresentation> convertedProtocolMappers = convertDeprecatedClaimsMask(session, rep.getClaims());
-            if (convertedProtocolMappers != null) {
-                rep.setProtocolMappers(convertedProtocolMappers);
-            }
-        }
-
-        if (rep.getName() != null) model.setClientId(rep.getName());
-        if (rep.isEnabled() != null) model.setEnabled(rep.isEnabled());
-        if (rep.isPublicClient() != null) model.setPublicClient(rep.isPublicClient());
-        if (rep.isFrontchannelLogout() != null) model.setFrontchannelLogout(rep.isFrontchannelLogout());
-        if (rep.isFullScopeAllowed() != null) model.setFullScopeAllowed(rep.isFullScopeAllowed());
-        if (rep.isDirectGrantsOnly() != null) model.setDirectGrantsOnly(rep.isDirectGrantsOnly());
-        if (rep.getNotBefore() != null) {
-            model.setNotBefore(rep.getNotBefore());
-        }
-        if (rep.getSecret() != null) model.setSecret(rep.getSecret());
-        List<String> redirectUris = rep.getRedirectUris();
-        if (redirectUris != null) {
-            model.setRedirectUris(new HashSet<String>(redirectUris));
-        }
-
-        List<String> webOrigins = rep.getWebOrigins();
-        if (webOrigins != null) {
-            model.setWebOrigins(new HashSet<String>(webOrigins));
-        }
-
-        if (rep.getNotBefore() != null) {
-            model.setNotBefore(rep.getNotBefore());
-        }
-        if (rep.getProtocol() != null) model.setProtocol(rep.getProtocol());
-        if (rep.getAttributes() != null) {
-            for (Map.Entry<String, String> entry : rep.getAttributes().entrySet()) {
-                model.setAttribute(entry.getKey(), entry.getValue());
-            }
-        }
-
-        updateClientIdentityProviders(rep.getIdentityProviders(), model);
-
-        if (rep.getProtocolMappers() != null) {
-            // first, remove all default/built in mappers
-            Set<ProtocolMapperModel> mappers = model.getProtocolMappers();
-            for (ProtocolMapperModel mapper : mappers) model.removeProtocolMapper(mapper);
-
-            for (ProtocolMapperRepresentation mapper : rep.getProtocolMappers()) {
-                model.addProtocolMapper(toModel(mapper));
-            }
-        }
-
-    }
-
     // Scope mappings
 
-    public static void createApplicationScopeMappings(RealmModel realm, ApplicationModel applicationModel, List<ScopeMappingRepresentation> mappings) {
+    public static void createClientScopeMappings(RealmModel realm, ClientModel clientModel, List<ScopeMappingRepresentation> mappings) {
         for (ScopeMappingRepresentation mapping : mappings) {
-            ClientModel client = realm.findClient(mapping.getClient());
+            ClientModel client = realm.getClientByClientId(mapping.getClient());
             if (client == null) {
-                throw new RuntimeException("Unknown client specified in application scope mappings");
+                throw new RuntimeException("Unknown client specified in client scope mappings");
             }
             for (String roleString : mapping.getRoles()) {
-                RoleModel role = applicationModel.getRole(roleString.trim());
+                RoleModel role = clientModel.getRole(roleString.trim());
                 if (role == null) {
-                    role = applicationModel.addRole(roleString.trim());
+                    role = clientModel.addRole(roleString.trim());
                 }
                 client.addScopeMapping(role);
             }
@@ -771,7 +739,7 @@ public class RepresentationToModel {
 
     // Users
 
-    public static UserModel createUser(KeycloakSession session, RealmModel newRealm, UserRepresentation userRep, Map<String, ApplicationModel> appMap) {
+    public static UserModel createUser(KeycloakSession session, RealmModel newRealm, UserRepresentation userRep, Map<String, ClientModel> clientMap) {
         convertDeprecatedSocialProviders(userRep);
 
         // Import users just to user storage. Don't federate
@@ -812,13 +780,13 @@ public class RepresentationToModel {
                 user.grantRole(role);
             }
         }
-        if (userRep.getApplicationRoles() != null) {
-            for (Map.Entry<String, List<String>> entry : userRep.getApplicationRoles().entrySet()) {
-                ApplicationModel app = appMap.get(entry.getKey());
-                if (app == null) {
-                    throw new RuntimeException("Unable to find application role mappings for app: " + entry.getKey());
+        if (userRep.getClientRoles() != null) {
+            for (Map.Entry<String, List<String>> entry : userRep.getClientRoles().entrySet()) {
+                ClientModel client = clientMap.get(entry.getKey());
+                if (client == null) {
+                    throw new RuntimeException("Unable to find client role mappings for client: " + entry.getKey());
                 }
-                createApplicationRoleMappings(app, user, entry.getValue());
+                createClientRoleMappings(client, user, entry.getValue());
             }
         }
         return user;
@@ -853,15 +821,15 @@ public class RepresentationToModel {
 
     // Role mappings
 
-    public static void createApplicationRoleMappings(ApplicationModel applicationModel, UserModel user, List<String> roleNames) {
+    public static void createClientRoleMappings(ClientModel clientModel, UserModel user, List<String> roleNames) {
         if (user == null) {
             throw new RuntimeException("User not found");
         }
 
         for (String roleName : roleNames) {
-            RoleModel role = applicationModel.getRole(roleName.trim());
+            RoleModel role = clientModel.getRole(roleName.trim());
             if (role == null) {
-                role = applicationModel.addRole(roleName.trim());
+                role = clientModel.addRole(roleName.trim());
             }
             user.grantRole(role);
 
diff --git a/model/api/src/main/java/org/keycloak/models/utils/UserModelDelegate.java b/model/api/src/main/java/org/keycloak/models/utils/UserModelDelegate.java
index 90f54bd..0e84ca9 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/UserModelDelegate.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/UserModelDelegate.java
@@ -1,6 +1,6 @@
 package org.keycloak.models.utils;
 
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserCredentialModel;
 import org.keycloak.models.UserCredentialValueModel;
@@ -152,8 +152,8 @@ public class UserModelDelegate implements UserModel {
     }
 
     @Override
-    public Set<RoleModel> getApplicationRoleMappings(ApplicationModel app) {
-        return delegate.getApplicationRoleMappings(app);
+    public Set<RoleModel> getClientRoleMappings(ClientModel app) {
+        return delegate.getClientRoleMappings(app);
     }
 
     @Override
diff --git a/model/file/src/main/java/org/keycloak/models/file/adapter/ClientAdapter.java b/model/file/src/main/java/org/keycloak/models/file/adapter/ClientAdapter.java
index 6c47bdf..18cc9c8 100755
--- a/model/file/src/main/java/org/keycloak/models/file/adapter/ClientAdapter.java
+++ b/model/file/src/main/java/org/keycloak/models/file/adapter/ClientAdapter.java
@@ -1,420 +1,660 @@
-/*
- * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
- * as indicated by the @author tags. All rights reserved.
- *
- * 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.models.file.adapter;
-
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RealmProvider;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.entities.ClientEntity;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.keycloak.models.ClientIdentityProviderMappingModel;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.entities.ClientIdentityProviderMappingEntity;
-import org.keycloak.models.entities.ProtocolMapperEntity;
-import org.keycloak.models.utils.KeycloakModelUtils;
-
-/**
- * ClientModel for JSON persistence.
- *
- * @author Stan Silvert ssilvert@redhat.com (C) 2015 Red Hat Inc.
- */
-public abstract class ClientAdapter implements ClientModel {
-
-    protected final ClientEntity clientEntity;
-    protected final RealmModel realm;
-    protected  KeycloakSession session;
-    private final RealmProvider model;
-
-    private final Map<String, RoleModel> allScopeMappings = new HashMap<String, RoleModel>();
-
-    public ClientAdapter(KeycloakSession session, RealmModel realm, ClientEntity clientEntity) {
-        this.clientEntity = clientEntity;
-        this.realm = realm;
-        this.session = session;
-        this.model = session.realms();
-    }
-
-    @Override
-    public String getId() {
-        return clientEntity.getId();
-    }
-
-    @Override
-    public String getClientId() {
-        return clientEntity.getName();
-    }
-
-    @Override
-    public Set<String> getWebOrigins() {
-        Set<String> result = new HashSet<String>();
-        if (clientEntity.getWebOrigins() != null) {
-            result.addAll(clientEntity.getWebOrigins());
-        }
-        return result;
-    }
-
-    @Override
-    public void setWebOrigins(Set<String> webOrigins) {
-        List<String> result = new ArrayList<String>();
-        result.addAll(webOrigins);
-        clientEntity.setWebOrigins(result);
-    }
-
-    @Override
-    public void addWebOrigin(String webOrigin) {
-        Set<String> webOrigins = getWebOrigins();
-        webOrigins.add(webOrigin);
-        setWebOrigins(webOrigins);
-    }
-
-    @Override
-    public void removeWebOrigin(String webOrigin) {
-        Set<String> webOrigins = getWebOrigins();
-        webOrigins.remove(webOrigin);
-        setWebOrigins(webOrigins);
-    }
-
-    @Override
-    public Set<String> getRedirectUris() {
-        Set<String> result = new HashSet<String>();
-        if (clientEntity.getRedirectUris() != null) {
-            result.addAll(clientEntity.getRedirectUris());
-        }
-        return result;
-    }
-
-    @Override
-    public void setRedirectUris(Set<String> redirectUris) {
-        List<String> result = new ArrayList<String>();
-        result.addAll(redirectUris);
-        clientEntity.setRedirectUris(result);
-    }
-
-    @Override
-    public void addRedirectUri(String redirectUri) {
-        if (clientEntity.getRedirectUris().contains(redirectUri)) return;
-        clientEntity.getRedirectUris().add(redirectUri);
-    }
-
-    @Override
-    public void removeRedirectUri(String redirectUri) {
-        clientEntity.getRedirectUris().remove(redirectUri);
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return clientEntity.isEnabled();
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        clientEntity.setEnabled(enabled);
-    }
-
-    @Override
-    public boolean validateSecret(String secret) {
-        return secret.equals(clientEntity.getSecret());
-    }
-
-    @Override
-    public String getSecret() {
-        return clientEntity.getSecret();
-    }
-
-    @Override
-    public void setSecret(String secret) {
-        clientEntity.setSecret(secret);
-    }
-
-    @Override
-    public boolean isPublicClient() {
-        return clientEntity.isPublicClient();
-    }
-
-    @Override
-    public void setPublicClient(boolean flag) {
-        clientEntity.setPublicClient(flag);
-    }
-
-
-    @Override
-    public boolean isFrontchannelLogout() {
-        return clientEntity.isFrontchannelLogout();
-    }
-
-    @Override
-    public void setFrontchannelLogout(boolean flag) {
-        clientEntity.setFrontchannelLogout(flag);
-    }
-
-    @Override
-    public boolean isFullScopeAllowed() {
-        return clientEntity.isFullScopeAllowed();
-    }
-
-    @Override
-    public void setFullScopeAllowed(boolean value) {
-        clientEntity.setFullScopeAllowed(value);
-
-    }
-
-    @Override
-    public RealmModel getRealm() {
-        return realm;
-    }
-
-    @Override
-    public int getNotBefore() {
-        return clientEntity.getNotBefore();
-    }
-
-    @Override
-    public void setNotBefore(int notBefore) {
-        clientEntity.setNotBefore(notBefore);
-    }
-
-    @Override
-    public Set<RoleModel> getScopeMappings() {
-        return new HashSet<RoleModel>(allScopeMappings.values());
-    }
-
-    @Override
-    public Set<RoleModel> getRealmScopeMappings() {
-        Set<RoleModel> allScopes = getScopeMappings();
-
-        Set<RoleModel> realmRoles = new HashSet<RoleModel>();
-        for (RoleModel role : allScopes) {
-            RoleAdapter roleAdapter = (RoleAdapter)role;
-            if (roleAdapter.isRealmRole()) {
-                realmRoles.add(role);
-            }
-        }
-        return realmRoles;
-    }
-
-    @Override
-    public boolean hasScope(RoleModel role) {
-        if (isFullScopeAllowed()) return true;
-        Set<RoleModel> roles = getScopeMappings();
-        if (roles.contains(role)) return true;
-
-        for (RoleModel mapping : roles) {
-            if (mapping.hasRole(role)) return true;
-        }
-        return false;
-    }
-
-
-    @Override
-    public void addScopeMapping(RoleModel role) {
-        allScopeMappings.put(role.getId(), role);
-    }
-
-    @Override
-    public void deleteScopeMapping(RoleModel role) {
-        allScopeMappings.remove(role.getId());
-    }
-
-    @Override
-    public String getProtocol() {
-        return clientEntity.getProtocol();
-    }
-
-    @Override
-    public void setProtocol(String protocol) {
-        clientEntity.setProtocol(protocol);
-
-    }
-
-    @Override
-    public void setAttribute(String name, String value) {
-        clientEntity.getAttributes().put(name, value);
-
-    }
-
-    @Override
-    public void removeAttribute(String name) {
-        clientEntity.getAttributes().remove(name);
-    }
-
-    @Override
-    public String getAttribute(String name) {
-        return clientEntity.getAttributes().get(name);
-    }
-
-    @Override
-    public Map<String, String> getAttributes() {
-        Map<String, String> copy = new HashMap<String, String>();
-        copy.putAll(clientEntity.getAttributes());
-        return copy;
-    }
-
-    @Override
-    public Set<ProtocolMapperModel> getProtocolMappers() {
-        Set<ProtocolMapperModel> result = new HashSet<ProtocolMapperModel>();
-        for (ProtocolMapperEntity entity : clientEntity.getProtocolMappers()) {
-            ProtocolMapperModel model = getProtocolMapperById(entity.getId());
-            if (model != null) result.add(model);
-        }
-        return result;
-    }
-
-    @Override
-    public ProtocolMapperModel addProtocolMapper(ProtocolMapperModel model) {
-        if (getProtocolMapperByName(model.getProtocol(), model.getName()) != null) {
-            throw new RuntimeException("protocol mapper name must be unique per protocol");
-        }
-        ProtocolMapperEntity entity = new ProtocolMapperEntity();
-        entity.setId(KeycloakModelUtils.generateId());
-        entity.setProtocol(model.getProtocol());
-        entity.setName(model.getName());
-        entity.setProtocolMapper(model.getProtocolMapper());
-        entity.setConfig(model.getConfig());
-        entity.setConsentRequired(model.isConsentRequired());
-        entity.setConsentText(model.getConsentText());
-        clientEntity.getProtocolMappers().add(entity);
-        return entityToModel(entity);
-    }
-
-    @Override
-    public void removeProtocolMapper(ProtocolMapperModel mapping) {
-        ProtocolMapperEntity toBeRemoved = null;
-        for (ProtocolMapperEntity entity : clientEntity.getProtocolMappers()) {
-            if (entity.getId().equals(mapping.getId())) {
-                toBeRemoved = entity;
-                break;
-            }
-        }
-
-        clientEntity.getProtocolMappers().remove(toBeRemoved);
-    }
-
-    @Override
-    public void updateProtocolMapper(ProtocolMapperModel mapping) {
-        ProtocolMapperEntity entity = getProtocolMapperEntityById(mapping.getId());
-        entity.setProtocolMapper(mapping.getProtocolMapper());
-        entity.setConsentRequired(mapping.isConsentRequired());
-        entity.setConsentText(mapping.getConsentText());
-        if (entity.getConfig() != null) {
-            entity.getConfig().clear();
-            entity.getConfig().putAll(mapping.getConfig());
-        } else {
-            entity.setConfig(mapping.getConfig());
-        }
-    }
-
-    protected ProtocolMapperEntity getProtocolMapperEntityById(String id) {
-        for (ProtocolMapperEntity entity : clientEntity.getProtocolMappers()) {
-            if (entity.getId().equals(id)) {
-                return entity;
-            }
-        }
-        return null;
-    }
-
-    protected ProtocolMapperEntity getProtocolMapperEntityByName(String protocol, String name) {
-        for (ProtocolMapperEntity entity : clientEntity.getProtocolMappers()) {
-            if (entity.getProtocol().equals(protocol) && entity.getName().equals(name)) {
-                return entity;
-            }
-        }
-        return null;
-
-    }
-
-    @Override
-    public ProtocolMapperModel getProtocolMapperById(String id) {
-        ProtocolMapperEntity entity = getProtocolMapperEntityById(id);
-        if (entity == null) return null;
-        return entityToModel(entity);
-    }
-
-    @Override
-    public ProtocolMapperModel getProtocolMapperByName(String protocol, String name) {
-        ProtocolMapperEntity entity = getProtocolMapperEntityByName(protocol, name);
-        if (entity == null) return null;
-        return entityToModel(entity);
-    }
-
-    protected ProtocolMapperModel entityToModel(ProtocolMapperEntity entity) {
-        ProtocolMapperModel mapping = new ProtocolMapperModel();
-        mapping.setId(entity.getId());
-        mapping.setName(entity.getName());
-        mapping.setProtocol(entity.getProtocol());
-        mapping.setProtocolMapper(entity.getProtocolMapper());
-        mapping.setConsentRequired(entity.isConsentRequired());
-        mapping.setConsentText(entity.getConsentText());
-        Map<String, String> config = new HashMap<String, String>();
-        if (entity.getConfig() != null) config.putAll(entity.getConfig());
-        mapping.setConfig(config);
-        return mapping;
-    }
-
-    @Override
-    public void updateIdentityProviders(List<ClientIdentityProviderMappingModel> identityProviders) {
-        List<ClientIdentityProviderMappingEntity> stored = new ArrayList<ClientIdentityProviderMappingEntity>();
-
-        for (ClientIdentityProviderMappingModel model : identityProviders) {
-            ClientIdentityProviderMappingEntity entity = new ClientIdentityProviderMappingEntity();
-
-            entity.setId(model.getIdentityProvider());
-            entity.setRetrieveToken(model.isRetrieveToken());
-            stored.add(entity);
-        }
-
-        clientEntity.setIdentityProviders(stored);
-    }
-
-    @Override
-    public List<ClientIdentityProviderMappingModel> getIdentityProviders() {
-        List<ClientIdentityProviderMappingModel> models = new ArrayList<ClientIdentityProviderMappingModel>();
-
-        for (ClientIdentityProviderMappingEntity entity : clientEntity.getIdentityProviders()) {
-            ClientIdentityProviderMappingModel model = new ClientIdentityProviderMappingModel();
-
-            model.setIdentityProvider(entity.getId());
-            model.setRetrieveToken(entity.isRetrieveToken());
-
-            models.add(model);
-        }
-
-        return models;
-    }
-
-    @Override
-    public boolean isAllowedRetrieveTokenFromIdentityProvider(String providerId) {
-        for (ClientIdentityProviderMappingEntity identityProviderMappingModel : clientEntity.getIdentityProviders()) {
-            if (identityProviderMappingModel.getId().equals(providerId)) {
-                return identityProviderMappingModel.isRetrieveToken();
-            }
-        }
-
-        return false;
-    }
-
-}
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * 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.models.file.adapter;
+
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientIdentityProviderMappingModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.keycloak.connections.file.InMemoryModel;
+import org.keycloak.models.ModelDuplicateException;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.entities.ClientEntity;
+import org.keycloak.models.entities.ClientIdentityProviderMappingEntity;
+import org.keycloak.models.entities.ProtocolMapperEntity;
+import org.keycloak.models.entities.RoleEntity;
+import org.keycloak.models.utils.KeycloakModelUtils;
+
+/**
+ * ApplicationModel used for JSON persistence.
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2015 Red Hat Inc.
+ */
+public class ClientAdapter implements ClientModel {
+
+    private final RealmModel realm;
+    private  KeycloakSession session;
+    private final ClientEntity entity;
+    private final InMemoryModel inMemoryModel;
+
+    private final Map<String, RoleAdapter> allRoles = new HashMap<String, RoleAdapter>();
+    private final Map<String, RoleModel> allScopeMappings = new HashMap<String, RoleModel>();
+
+    public ClientAdapter(KeycloakSession session, RealmModel realm, ClientEntity entity, InMemoryModel inMemoryModel) {
+        this.realm = realm;
+        this.session = session;
+        this.entity = entity;
+        this.inMemoryModel = inMemoryModel;
+    }
+
+    @Override
+    public void updateClient() {
+    }
+
+    @Override
+    public String getId() {
+        return entity.getId();
+    }
+
+    @Override
+    public Set<String> getWebOrigins() {
+        Set<String> result = new HashSet<String>();
+        if (entity.getWebOrigins() != null) {
+            result.addAll(entity.getWebOrigins());
+        }
+        return result;
+    }
+
+    @Override
+    public void setWebOrigins(Set<String> webOrigins) {
+        List<String> result = new ArrayList<String>();
+        result.addAll(webOrigins);
+        entity.setWebOrigins(result);
+    }
+
+    @Override
+    public void addWebOrigin(String webOrigin) {
+        Set<String> webOrigins = getWebOrigins();
+        webOrigins.add(webOrigin);
+        setWebOrigins(webOrigins);
+    }
+
+    @Override
+    public void removeWebOrigin(String webOrigin) {
+        Set<String> webOrigins = getWebOrigins();
+        webOrigins.remove(webOrigin);
+        setWebOrigins(webOrigins);
+    }
+
+    @Override
+    public Set<String> getRedirectUris() {
+        Set<String> result = new HashSet<String>();
+        if (entity.getRedirectUris() != null) {
+            result.addAll(entity.getRedirectUris());
+        }
+        return result;
+    }
+
+    @Override
+    public void setRedirectUris(Set<String> redirectUris) {
+        List<String> result = new ArrayList<String>();
+        result.addAll(redirectUris);
+        entity.setRedirectUris(result);
+    }
+
+    @Override
+    public void addRedirectUri(String redirectUri) {
+        if (entity.getRedirectUris().contains(redirectUri)) return;
+        entity.getRedirectUris().add(redirectUri);
+    }
+
+    @Override
+    public void removeRedirectUri(String redirectUri) {
+        entity.getRedirectUris().remove(redirectUri);
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return entity.isEnabled();
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        entity.setEnabled(enabled);
+    }
+
+    @Override
+    public boolean validateSecret(String secret) {
+        return secret.equals(entity.getSecret());
+    }
+
+    @Override
+    public String getSecret() {
+        return entity.getSecret();
+    }
+
+    @Override
+    public void setSecret(String secret) {
+        entity.setSecret(secret);
+    }
+
+    @Override
+    public boolean isPublicClient() {
+        return entity.isPublicClient();
+    }
+
+    @Override
+    public void setPublicClient(boolean flag) {
+        entity.setPublicClient(flag);
+    }
+
+
+    @Override
+    public boolean isFrontchannelLogout() {
+        return entity.isFrontchannelLogout();
+    }
+
+    @Override
+    public void setFrontchannelLogout(boolean flag) {
+        entity.setFrontchannelLogout(flag);
+    }
+
+    @Override
+    public boolean isFullScopeAllowed() {
+        return entity.isFullScopeAllowed();
+    }
+
+    @Override
+    public void setFullScopeAllowed(boolean value) {
+        entity.setFullScopeAllowed(value);
+    }
+
+    @Override
+    public RealmModel getRealm() {
+        return realm;
+    }
+
+    @Override
+    public int getNotBefore() {
+        return entity.getNotBefore();
+    }
+
+    @Override
+    public void setNotBefore(int notBefore) {
+        entity.setNotBefore(notBefore);
+    }
+
+    @Override
+    public Set<RoleModel> getScopeMappings() {
+        return new HashSet<RoleModel>(allScopeMappings.values());
+    }
+
+    @Override
+    public Set<RoleModel> getRealmScopeMappings() {
+        Set<RoleModel> allScopes = getScopeMappings();
+
+        Set<RoleModel> realmRoles = new HashSet<RoleModel>();
+        for (RoleModel role : allScopes) {
+            RoleAdapter roleAdapter = (RoleAdapter)role;
+            if (roleAdapter.isRealmRole()) {
+                realmRoles.add(role);
+            }
+        }
+        return realmRoles;
+    }
+
+    @Override
+    public void addScopeMapping(RoleModel role) {
+        allScopeMappings.put(role.getId(), role);
+    }
+
+    @Override
+    public void deleteScopeMapping(RoleModel role) {
+        allScopeMappings.remove(role.getId());
+    }
+
+    @Override
+    public String getProtocol() {
+        return entity.getProtocol();
+    }
+
+    @Override
+    public void setProtocol(String protocol) {
+        entity.setProtocol(protocol);
+
+    }
+
+    @Override
+    public void setAttribute(String name, String value) {
+        entity.getAttributes().put(name, value);
+
+    }
+
+    @Override
+    public void removeAttribute(String name) {
+        entity.getAttributes().remove(name);
+    }
+
+    @Override
+    public String getAttribute(String name) {
+        return entity.getAttributes().get(name);
+    }
+
+    @Override
+    public Map<String, String> getAttributes() {
+        Map<String, String> copy = new HashMap<String, String>();
+        copy.putAll(entity.getAttributes());
+        return copy;
+    }
+
+    @Override
+    public Set<ProtocolMapperModel> getProtocolMappers() {
+        Set<ProtocolMapperModel> result = new HashSet<ProtocolMapperModel>();
+        for (ProtocolMapperEntity entity : this.entity.getProtocolMappers()) {
+            ProtocolMapperModel model = getProtocolMapperById(entity.getId());
+            if (model != null) result.add(model);
+        }
+        return result;
+    }
+
+    @Override
+    public ProtocolMapperModel addProtocolMapper(ProtocolMapperModel model) {
+        if (getProtocolMapperByName(model.getProtocol(), model.getName()) != null) {
+            throw new RuntimeException("protocol mapper name must be unique per protocol");
+        }
+        ProtocolMapperEntity entity = new ProtocolMapperEntity();
+        entity.setId(KeycloakModelUtils.generateId());
+        entity.setProtocol(model.getProtocol());
+        entity.setName(model.getName());
+        entity.setProtocolMapper(model.getProtocolMapper());
+        entity.setConfig(model.getConfig());
+        entity.setConsentRequired(model.isConsentRequired());
+        entity.setConsentText(model.getConsentText());
+        this.entity.getProtocolMappers().add(entity);
+        return entityToModel(entity);
+    }
+
+    @Override
+    public void removeProtocolMapper(ProtocolMapperModel mapping) {
+        ProtocolMapperEntity toBeRemoved = null;
+        for (ProtocolMapperEntity e : entity.getProtocolMappers()) {
+            if (e.getId().equals(mapping.getId())) {
+                toBeRemoved = e;
+                break;
+            }
+        }
+
+        entity.getProtocolMappers().remove(toBeRemoved);
+    }
+
+    @Override
+    public void updateProtocolMapper(ProtocolMapperModel mapping) {
+        ProtocolMapperEntity entity = getProtocolMapperEntityById(mapping.getId());
+        entity.setProtocolMapper(mapping.getProtocolMapper());
+        entity.setConsentRequired(mapping.isConsentRequired());
+        entity.setConsentText(mapping.getConsentText());
+        if (entity.getConfig() != null) {
+            entity.getConfig().clear();
+            entity.getConfig().putAll(mapping.getConfig());
+        } else {
+            entity.setConfig(mapping.getConfig());
+        }
+    }
+
+    protected ProtocolMapperEntity getProtocolMapperEntityById(String id) {
+        for (ProtocolMapperEntity e : entity.getProtocolMappers()) {
+            if (e.getId().equals(id)) {
+                return e;
+            }
+        }
+        return null;
+    }
+
+    protected ProtocolMapperEntity getProtocolMapperEntityByName(String protocol, String name) {
+        for (ProtocolMapperEntity e : entity.getProtocolMappers()) {
+            if (e.getProtocol().equals(protocol) && e.getName().equals(name)) {
+                return e;
+            }
+        }
+        return null;
+
+    }
+
+    @Override
+    public ProtocolMapperModel getProtocolMapperById(String id) {
+        ProtocolMapperEntity entity = getProtocolMapperEntityById(id);
+        if (entity == null) return null;
+        return entityToModel(entity);
+    }
+
+    @Override
+    public ProtocolMapperModel getProtocolMapperByName(String protocol, String name) {
+        ProtocolMapperEntity entity = getProtocolMapperEntityByName(protocol, name);
+        if (entity == null) return null;
+        return entityToModel(entity);
+    }
+
+    protected ProtocolMapperModel entityToModel(ProtocolMapperEntity entity) {
+        ProtocolMapperModel mapping = new ProtocolMapperModel();
+        mapping.setId(entity.getId());
+        mapping.setName(entity.getName());
+        mapping.setProtocol(entity.getProtocol());
+        mapping.setProtocolMapper(entity.getProtocolMapper());
+        mapping.setConsentRequired(entity.isConsentRequired());
+        mapping.setConsentText(entity.getConsentText());
+        Map<String, String> config = new HashMap<String, String>();
+        if (entity.getConfig() != null) config.putAll(entity.getConfig());
+        mapping.setConfig(config);
+        return mapping;
+    }
+
+    @Override
+    public void updateIdentityProviders(List<ClientIdentityProviderMappingModel> identityProviders) {
+        List<ClientIdentityProviderMappingEntity> stored = new ArrayList<ClientIdentityProviderMappingEntity>();
+
+        for (ClientIdentityProviderMappingModel model : identityProviders) {
+            ClientIdentityProviderMappingEntity entity = new ClientIdentityProviderMappingEntity();
+
+            entity.setId(model.getIdentityProvider());
+            entity.setRetrieveToken(model.isRetrieveToken());
+            stored.add(entity);
+        }
+
+        entity.setIdentityProviders(stored);
+    }
+
+    @Override
+    public List<ClientIdentityProviderMappingModel> getIdentityProviders() {
+        List<ClientIdentityProviderMappingModel> models = new ArrayList<>();
+
+        for (ClientIdentityProviderMappingEntity e : entity.getIdentityProviders()) {
+            ClientIdentityProviderMappingModel model = new ClientIdentityProviderMappingModel();
+
+            model.setIdentityProvider(e.getId());
+            model.setRetrieveToken(e.isRetrieveToken());
+
+            models.add(model);
+        }
+
+        return models;
+    }
+
+    @Override
+    public boolean isAllowedRetrieveTokenFromIdentityProvider(String providerId) {
+        for (ClientIdentityProviderMappingEntity identityProviderMappingModel : entity.getIdentityProviders()) {
+            if (identityProviderMappingModel.getId().equals(providerId)) {
+                return identityProviderMappingModel.isRetrieveToken();
+            }
+        }
+
+        return false;
+    }
+
+    @Override
+    public String getClientId() {
+        return entity.getClientId();
+    }
+
+    @Override
+    public void setClientId(String clientId) {
+        if (appNameExists(clientId)) throw new ModelDuplicateException("Application named " + clientId + " already exists.");
+        entity.setClientId(clientId);
+    }
+
+    private boolean appNameExists(String name) {
+        for (ClientModel app : realm.getClients()) {
+            if (app == this) continue;
+            if (app.getClientId().equals(name)) return true;
+        }
+
+        return false;
+    }
+
+    @Override
+    public boolean isSurrogateAuthRequired() {
+        return entity.isSurrogateAuthRequired();
+    }
+
+    @Override
+    public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
+        entity.setSurrogateAuthRequired(surrogateAuthRequired);
+    }
+
+    @Override
+    public String getManagementUrl() {
+        return entity.getManagementUrl();
+    }
+
+    @Override
+    public void setManagementUrl(String url) {
+        entity.setManagementUrl(url);
+    }
+
+    @Override
+    public void setBaseUrl(String url) {
+        entity.setBaseUrl(url);
+    }
+
+    @Override
+    public String getBaseUrl() {
+        return entity.getBaseUrl();
+    }
+
+    @Override
+    public boolean isBearerOnly() {
+        return entity.isBearerOnly();
+    }
+
+    @Override
+    public void setBearerOnly(boolean only) {
+        entity.setBearerOnly(only);
+    }
+
+    @Override
+    public boolean isConsentRequired() {
+        return entity.isConsentRequired();
+    }
+
+    @Override
+    public void setConsentRequired(boolean consentRequired) {
+        entity.setConsentRequired(consentRequired);
+    }
+
+    @Override
+    public boolean isDirectGrantsOnly() {
+        return entity.isDirectGrantsOnly();
+    }
+
+    @Override
+    public void setDirectGrantsOnly(boolean flag) {
+        entity.setDirectGrantsOnly(flag);
+    }
+
+    @Override
+    public RoleAdapter getRole(String name) {
+        for (RoleAdapter role : allRoles.values()) {
+            if (role.getName().equals(name)) return role;
+        }
+        return null;
+    }
+
+    @Override
+    public RoleAdapter addRole(String name) {
+        return this.addRole(KeycloakModelUtils.generateId(), name);
+    }
+
+    @Override
+    public RoleAdapter addRole(String id, String name) {
+        if (roleNameExists(name)) throw new ModelDuplicateException("Role named " + name + " already exists.");
+        RoleEntity roleEntity = new RoleEntity();
+        roleEntity.setId(id);
+        roleEntity.setName(name);
+        roleEntity.setClientId(getId());
+
+        RoleAdapter role = new RoleAdapter(getRealm(), roleEntity, this);
+        allRoles.put(id, role);
+
+        return role;
+    }
+
+    private boolean roleNameExists(String name) {
+        for (RoleModel role : allRoles.values()) {
+            if (role.getName().equals(name)) return true;
+        }
+
+        return false;
+    }
+
+    @Override
+    public boolean removeRole(RoleModel role) {
+        boolean removed = (allRoles.remove(role.getId()) != null);
+
+        // remove application roles from users
+        for (UserModel user : inMemoryModel.getUsers(realm.getId())) {
+            user.deleteRoleMapping(role);
+        }
+
+        // delete scope mappings from applications
+        for (ClientModel app : realm.getClients()) {
+            app.deleteScopeMapping(role);
+        }
+
+        // remove role from the realm
+        realm.removeRole(role);
+
+        this.deleteScopeMapping(role);
+
+        return removed;
+    }
+
+    @Override
+    public Set<RoleModel> getRoles() {
+        return new HashSet(allRoles.values());
+    }
+
+    @Override
+    public boolean hasScope(RoleModel role) {
+        if (isFullScopeAllowed()) return true;
+        Set<RoleModel> roles = getScopeMappings();
+        if (roles.contains(role)) return true;
+
+        for (RoleModel mapping : roles) {
+            if (mapping.hasRole(role)) return true;
+        }
+        roles = getRoles();
+        if (roles.contains(role)) return true;
+
+        for (RoleModel mapping : roles) {
+            if (mapping.hasRole(role)) return true;
+        }
+        return false;
+    }
+
+    @Override
+    public Set<RoleModel> getClientScopeMappings(ClientModel client) {
+        Set<RoleModel> allScopes = client.getScopeMappings();
+
+        Set<RoleModel> appRoles = new HashSet<RoleModel>();
+        for (RoleModel role : allScopes) {
+            RoleAdapter roleAdapter = (RoleAdapter)role;
+            if (getId().equals(roleAdapter.getRoleEntity().getClientId())) {
+                appRoles.add(role);
+            }
+        }
+        return appRoles;
+    }
+
+    @Override
+    public List<String> getDefaultRoles() {
+        return entity.getDefaultRoles();
+    }
+
+    @Override
+    public void addDefaultRole(String name) {
+        RoleModel role = getRole(name);
+        if (role == null) {
+            addRole(name);
+        }
+
+        List<String> defaultRoles = getDefaultRoles();
+        if (defaultRoles.contains(name)) return;
+
+        String[] defaultRoleNames = defaultRoles.toArray(new String[defaultRoles.size() + 1]);
+        defaultRoleNames[defaultRoleNames.length - 1] = name;
+        updateDefaultRoles(defaultRoleNames);
+    }
+
+    @Override
+    public void updateDefaultRoles(String[] defaultRoles) {
+        List<String> roleNames = new ArrayList<String>();
+        for (String roleName : defaultRoles) {
+            RoleModel role = getRole(roleName);
+            if (role == null) {
+                addRole(roleName);
+            }
+
+            roleNames.add(roleName);
+        }
+
+        entity.setDefaultRoles(roleNames);
+    }
+
+    @Override
+    public int getNodeReRegistrationTimeout() {
+        return entity.getNodeReRegistrationTimeout();
+    }
+
+    @Override
+    public void setNodeReRegistrationTimeout(int timeout) {
+        entity.setNodeReRegistrationTimeout(timeout);
+    }
+
+    @Override
+    public Map<String, Integer> getRegisteredNodes() {
+        return entity.getRegisteredNodes() == null ? Collections.<String, Integer>emptyMap() : Collections.unmodifiableMap(entity.getRegisteredNodes());
+    }
+
+    @Override
+    public void registerNode(String nodeHost, int registrationTime) {
+        if (entity.getRegisteredNodes() == null) {
+            entity.setRegisteredNodes(new HashMap<String, Integer>());
+        }
+
+        entity.getRegisteredNodes().put(nodeHost, registrationTime);
+    }
+
+    @Override
+    public void unregisterNode(String nodeHost) {
+        if (entity.getRegisteredNodes() == null) return;
+
+        entity.getRegisteredNodes().remove(nodeHost);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof ClientModel)) return false;
+
+        ClientModel that = (ClientModel) o;
+        return that.getId().equals(getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
+}
diff --git a/model/file/src/main/java/org/keycloak/models/file/adapter/RealmAdapter.java b/model/file/src/main/java/org/keycloak/models/file/adapter/RealmAdapter.java
index a1490ed..31b4bfc 100755
--- a/model/file/src/main/java/org/keycloak/models/file/adapter/RealmAdapter.java
+++ b/model/file/src/main/java/org/keycloak/models/file/adapter/RealmAdapter.java
@@ -1,1264 +1,1167 @@
-/*
- * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
- * as indicated by the @author tags. All rights reserved.
- *
- * 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.models.file.adapter;
-
-import org.keycloak.enums.SslRequired;
-import org.keycloak.models.ApplicationModel;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.IdentityProviderMapperModel;
-import org.keycloak.models.IdentityProviderModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.OAuthClientModel;
-import org.keycloak.models.PasswordPolicy;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RequiredCredentialModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserFederationProviderModel;
-import org.keycloak.models.entities.IdentityProviderMapperEntity;
-import org.keycloak.models.entities.RequiredCredentialEntity;
-import org.keycloak.models.entities.UserFederationProviderEntity;
-import org.keycloak.models.utils.KeycloakModelUtils;
-
-import java.security.Key;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.keycloak.connections.file.InMemoryModel;
-import org.keycloak.models.ModelDuplicateException;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.entities.ApplicationEntity;
-import org.keycloak.models.entities.ClientEntity;
-import org.keycloak.models.entities.OAuthClientEntity;
-import org.keycloak.models.entities.RealmEntity;
-import org.keycloak.models.entities.RoleEntity;
-
-/**
- * RealmModel for JSON persistence.
- *
- * @author Stan Silvert ssilvert@redhat.com (C) 2015 Red Hat Inc.
- */
-public class RealmAdapter implements RealmModel {
-
-    private final InMemoryModel inMemoryModel;
-    private final RealmEntity realm;
-
-    protected volatile transient PublicKey publicKey;
-    protected volatile transient PrivateKey privateKey;
-    protected volatile transient X509Certificate certificate;
-    protected volatile transient Key codeSecretKey;
-
-    private volatile transient PasswordPolicy passwordPolicy;
-    private volatile transient KeycloakSession session;
-
-    private final Map<String, ApplicationModel> allApps = new HashMap<String, ApplicationModel>();
-    private ApplicationModel masterAdminApp = null;
-    private final Map<String, RoleAdapter> allRoles = new HashMap<String, RoleAdapter>();
-    private final Map<String, OAuthClientAdapter> allOAuthClients = new HashMap<String, OAuthClientAdapter>();
-    private final Map<String, IdentityProviderModel> allIdProviders = new HashMap<String, IdentityProviderModel>();
-
-    public RealmAdapter(KeycloakSession session, RealmEntity realm, InMemoryModel inMemoryModel) {
-        this.session = session;
-        this.realm = realm;
-        this.inMemoryModel = inMemoryModel;
-    }
-
-    public RealmEntity getRealmEnity() {
-        return realm;
-    }
-
-    @Override
-    public String getId() {
-        return realm.getId();
-    }
-
-    @Override
-    public String getName() {
-        return realm.getName();
-    }
-
-    @Override
-    public void setName(String name) {
-        if (getName() == null) {
-            realm.setName(name);
-            return;
-        }
-
-        if (getName().equals(name)) return; // allow setting name to same value
-
-        if (inMemoryModel.getRealmByName(name) != null) throw new ModelDuplicateException("Realm " + name + " already exists.");
-        realm.setName(name);
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return realm.isEnabled();
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        realm.setEnabled(enabled);
-    }
-
-    @Override
-    public SslRequired getSslRequired() {
-        return SslRequired.valueOf(realm.getSslRequired());
-    }
-
-    @Override
-    public void setSslRequired(SslRequired sslRequired) {
-        realm.setSslRequired(sslRequired.name());
-    }
-
-    @Override
-    public boolean isPasswordCredentialGrantAllowed() {
-        return realm.isPasswordCredentialGrantAllowed();
-    }
-
-    @Override
-    public void setPasswordCredentialGrantAllowed(boolean passwordCredentialGrantAllowed) {
-        realm.setPasswordCredentialGrantAllowed(passwordCredentialGrantAllowed);
-    }
-
-    @Override
-    public boolean isRegistrationAllowed() {
-        return realm.isRegistrationAllowed();
-    }
-
-    @Override
-    public void setRegistrationAllowed(boolean registrationAllowed) {
-        realm.setRegistrationAllowed(registrationAllowed);
-    }
-
-    @Override
-    public boolean isRegistrationEmailAsUsername() {
-        return realm.isRegistrationEmailAsUsername();
-    }
-
-    @Override
-    public void setRegistrationEmailAsUsername(boolean registrationEmailAsUsername) {
-        realm.setRegistrationEmailAsUsername(registrationEmailAsUsername);
-    }
-
-    @Override
-    public boolean isRememberMe() {
-        return realm.isRememberMe();
-    }
-
-    @Override
-    public void setRememberMe(boolean rememberMe) {
-        realm.setRememberMe(rememberMe);
-    }
-
-    @Override
-    public boolean isBruteForceProtected() {
-        return realm.isBruteForceProtected();
-    }
-
-    @Override
-    public void setBruteForceProtected(boolean value) {
-        realm.setBruteForceProtected(value);
-    }
-
-    @Override
-    public int getMaxFailureWaitSeconds() {
-        return realm.getMaxFailureWaitSeconds();
-    }
-
-    @Override
-    public void setMaxFailureWaitSeconds(int val) {
-        realm.setMaxFailureWaitSeconds(val);
-    }
-
-    @Override
-    public int getWaitIncrementSeconds() {
-        return realm.getWaitIncrementSeconds();
-    }
-
-    @Override
-    public void setWaitIncrementSeconds(int val) {
-        realm.setWaitIncrementSeconds(val);
-    }
-
-    @Override
-    public long getQuickLoginCheckMilliSeconds() {
-        return realm.getQuickLoginCheckMilliSeconds();
-    }
-
-    @Override
-    public void setQuickLoginCheckMilliSeconds(long val) {
-        realm.setQuickLoginCheckMilliSeconds(val);
-    }
-
-    @Override
-    public int getMinimumQuickLoginWaitSeconds() {
-        return realm.getMinimumQuickLoginWaitSeconds();
-    }
-
-    @Override
-    public void setMinimumQuickLoginWaitSeconds(int val) {
-        realm.setMinimumQuickLoginWaitSeconds(val);
-    }
-
-
-    @Override
-    public int getMaxDeltaTimeSeconds() {
-        return realm.getMaxDeltaTimeSeconds();
-    }
-
-    @Override
-    public void setMaxDeltaTimeSeconds(int val) {
-        realm.setMaxDeltaTimeSeconds(val);
-    }
-
-    @Override
-    public int getFailureFactor() {
-        return realm.getFailureFactor();
-    }
-
-    @Override
-    public void setFailureFactor(int failureFactor) {
-        realm.setFailureFactor(failureFactor);
-    }
-
-
-    @Override
-    public boolean isVerifyEmail() {
-        return realm.isVerifyEmail();
-    }
-
-    @Override
-    public void setVerifyEmail(boolean verifyEmail) {
-        realm.setVerifyEmail(verifyEmail);
-    }
-
-    @Override
-    public boolean isResetPasswordAllowed() {
-        return realm.isResetPasswordAllowed();
-    }
-
-    @Override
-    public void setResetPasswordAllowed(boolean resetPassword) {
-        realm.setResetPasswordAllowed(resetPassword);
-    }
-
-    @Override
-    public PasswordPolicy getPasswordPolicy() {
-        if (passwordPolicy == null) {
-            passwordPolicy = new PasswordPolicy(realm.getPasswordPolicy());
-        }
-        return passwordPolicy;
-    }
-
-    @Override
-    public void setPasswordPolicy(PasswordPolicy policy) {
-        this.passwordPolicy = policy;
-        realm.setPasswordPolicy(policy.toString());
-    }
-
-    @Override
-    public int getNotBefore() {
-        return realm.getNotBefore();
-    }
-
-    @Override
-    public void setNotBefore(int notBefore) {
-        realm.setNotBefore(notBefore);
-    }
-
-
-    @Override
-    public int getSsoSessionIdleTimeout() {
-        return realm.getSsoSessionIdleTimeout();
-    }
-
-    @Override
-    public void setSsoSessionIdleTimeout(int seconds) {
-        realm.setSsoSessionIdleTimeout(seconds);
-    }
-
-    @Override
-    public int getSsoSessionMaxLifespan() {
-        return realm.getSsoSessionMaxLifespan();
-    }
-
-    @Override
-    public void setSsoSessionMaxLifespan(int seconds) {
-        realm.setSsoSessionMaxLifespan(seconds);
-    }
-
-    @Override
-    public int getAccessTokenLifespan() {
-        return realm.getAccessTokenLifespan();
-    }
-
-    @Override
-    public void setAccessTokenLifespan(int tokenLifespan) {
-        realm.setAccessTokenLifespan(tokenLifespan);
-    }
-
-    @Override
-    public int getAccessCodeLifespan() {
-        return realm.getAccessCodeLifespan();
-    }
-
-    @Override
-    public void setAccessCodeLifespan(int accessCodeLifespan) {
-        realm.setAccessCodeLifespan(accessCodeLifespan);
-    }
-
-    @Override
-    public int getAccessCodeLifespanUserAction() {
-        return realm.getAccessCodeLifespanUserAction();
-    }
-
-    @Override
-    public void setAccessCodeLifespanUserAction(int accessCodeLifespanUserAction) {
-        realm.setAccessCodeLifespanUserAction(accessCodeLifespanUserAction);
-    }
-
-    @Override
-    public String getPublicKeyPem() {
-        return realm.getPublicKeyPem();
-    }
-
-    @Override
-    public void setPublicKeyPem(String publicKeyPem) {
-        realm.setPublicKeyPem(publicKeyPem);
-        this.publicKey = null;
-    }
-
-    @Override
-    public X509Certificate getCertificate() {
-        if (certificate != null) return certificate;
-        certificate = KeycloakModelUtils.getCertificate(getCertificatePem());
-        return certificate;
-    }
-
-    @Override
-    public void setCertificate(X509Certificate certificate) {
-        this.certificate = certificate;
-        String certificatePem = KeycloakModelUtils.getPemFromCertificate(certificate);
-        setCertificatePem(certificatePem);
-    }
-
-    @Override
-    public String getCertificatePem() {
-        return realm.getCertificatePem();
-    }
-
-    @Override
-    public void setCertificatePem(String certificate) {
-        realm.setCertificatePem(certificate);
-
-    }
-
-
-    @Override
-    public String getPrivateKeyPem() {
-        return realm.getPrivateKeyPem();
-    }
-
-    @Override
-    public void setPrivateKeyPem(String privateKeyPem) {
-        realm.setPrivateKeyPem(privateKeyPem);
-        this.privateKey = null;
-    }
-
-    @Override
-    public PublicKey getPublicKey() {
-        if (publicKey != null) return publicKey;
-        publicKey = KeycloakModelUtils.getPublicKey(getPublicKeyPem());
-        return publicKey;
-    }
-
-    @Override
-    public void setPublicKey(PublicKey publicKey) {
-        this.publicKey = publicKey;
-        String publicKeyPem = KeycloakModelUtils.getPemFromKey(publicKey);
-        setPublicKeyPem(publicKeyPem);
-    }
-
-    @Override
-    public PrivateKey getPrivateKey() {
-        if (privateKey != null) return privateKey;
-        privateKey = KeycloakModelUtils.getPrivateKey(getPrivateKeyPem());
-        return privateKey;
-    }
-
-    @Override
-    public void setPrivateKey(PrivateKey privateKey) {
-        this.privateKey = privateKey;
-        String privateKeyPem = KeycloakModelUtils.getPemFromKey(privateKey);
-        setPrivateKeyPem(privateKeyPem);
-    }
-
-    @Override
-    public String getCodeSecret() {
-        return realm.getCodeSecret();
-    }
-
-    @Override
-    public Key getCodeSecretKey() {
-        if (codeSecretKey == null) {
-            codeSecretKey = KeycloakModelUtils.getSecretKey(getCodeSecret());
-        }
-        return codeSecretKey;
-    }
-
-    @Override
-    public void setCodeSecret(String codeSecret) {
-        realm.setCodeSecret(codeSecret);
-    }
-
-    @Override
-    public String getLoginTheme() {
-        return realm.getLoginTheme();
-    }
-
-    @Override
-    public void setLoginTheme(String name) {
-        realm.setLoginTheme(name);
-    }
-
-    @Override
-    public String getAccountTheme() {
-        return realm.getAccountTheme();
-    }
-
-    @Override
-    public void setAccountTheme(String name) {
-        realm.setAccountTheme(name);
-    }
-
-    @Override
-    public String getAdminTheme() {
-        return realm.getAdminTheme();
-    }
-
-    @Override
-    public void setAdminTheme(String name) {
-        realm.setAdminTheme(name);
-    }
-
-    @Override
-    public String getEmailTheme() {
-        return realm.getEmailTheme();
-    }
-
-    @Override
-    public void setEmailTheme(String name) {
-        realm.setEmailTheme(name);
-    }
-
-    @Override
-    public RoleAdapter getRole(String name) {
-        for (RoleAdapter role : allRoles.values()) {
-            if (role.getName().equals(name)) return role;
-        }
-        return null;
-    }
-
-    @Override
-    public RoleModel addRole(String name) {
-        return this.addRole(KeycloakModelUtils.generateId(), name);
-    }
-
-    @Override
-    public RoleModel addRole(String id, String name) {
-        if (id == null) throw new NullPointerException("id == null");
-        if (name == null) throw new NullPointerException("name == null");
-        if (hasRoleWithName(name)) throw new ModelDuplicateException("Realm already contains role with name " + name + ".");
-
-        RoleEntity roleEntity = new RoleEntity();
-        roleEntity.setId(id);
-        roleEntity.setName(name);
-        roleEntity.setRealmId(getId());
-
-        RoleAdapter roleModel = new RoleAdapter(this, roleEntity, this);
-        allRoles.put(id, roleModel);
-        return roleModel;
-    }
-
-    @Override
-    public boolean removeRole(RoleModel role) {
-        return removeRoleById(role.getId());
-    }
-
-    @Override
-    public boolean removeRoleById(String id) {
-        if (id == null) throw new NullPointerException("id == null");
-
-        // try realm roles first
-        if (allRoles.remove(id) != null) return true;
-
-        for (ApplicationModel app : getApplications()) {
-            for (RoleModel appRole : app.getRoles()) {
-                if (id.equals(appRole.getId())) {
-                    app.removeRole(appRole);
-                    return true;
-                }
-            }
-        }
-
-        return false;
-    }
-
-    @Override
-    public Set<RoleModel> getRoles() {
-        return new HashSet(allRoles.values());
-    }
-
-    @Override
-    public RoleModel getRoleById(String id) {
-        RoleModel found = allRoles.get(id);
-        if (found != null) return found;
-
-        for (ApplicationModel app : getApplications()) {
-            for (RoleModel appRole : app.getRoles()) {
-                if (appRole.getId().equals(id)) return appRole;
-            }
-        }
-
-        return null;
-    }
-
-    @Override
-    public List<String> getDefaultRoles() {
-        return realm.getDefaultRoles();
-    }
-
-    @Override
-    public void addDefaultRole(String name) {
-        RoleModel role = getRole(name);
-        if (role == null) {
-            addRole(name);
-        }
-
-        List<String> roleNames = getDefaultRoles();
-        if (roleNames.contains(name)) throw new IllegalArgumentException("Realm " + realm.getName() + " already contains default role named " + name);
-
-        roleNames.add(name);
-        realm.setDefaultRoles(roleNames);
-    }
-
-    boolean hasRoleWithName(String name) {
-        for (RoleModel role : allRoles.values()) {
-            if (role.getName().equals(name)) return true;
-        }
-
-        return false;
-    }
-
-    @Override
-    public void updateDefaultRoles(String[] defaultRoles) {
-        List<String> roleNames = new ArrayList<String>();
-        for (String roleName : defaultRoles) {
-            RoleModel role = getRole(roleName);
-            if (role == null) {
-                addRole(roleName);
-            }
-
-            roleNames.add(roleName);
-        }
-
-        realm.setDefaultRoles(roleNames);
-    }
-
-    @Override
-    public ClientModel findClient(String clientId) {
-        ClientModel model = getApplicationByName(clientId);
-        if (model != null) return model;
-        return getOAuthClient(clientId);
-    }
-
-    @Override
-    public ClientModel findClientById(String id) {
-        ClientModel clientModel = getApplicationById(id);
-        if (clientModel != null) return clientModel;
-        return getOAuthClientById(id);
-    }
-
-
-
-    @Override
-    public ApplicationModel getApplicationById(String id) {
-        return allApps.get(id);
-    }
-
-    @Override
-    public ApplicationModel getApplicationByName(String name) {
-        for (ApplicationModel app : getApplications()) {
-            if (app.getName().equals(name)) return app;
-        }
-
-        return null;
-    }
-
-    @Override
-    public Map<String, ApplicationModel> getApplicationNameMap() {
-        Map<String, ApplicationModel> resourceMap = new HashMap<String, ApplicationModel>();
-        for (ApplicationModel resource : getApplications()) {
-            resourceMap.put(resource.getName(), resource);
-        }
-        return resourceMap;
-    }
-
-    @Override
-    public List<ApplicationModel> getApplications() {
-        return new ArrayList<ApplicationModel>(allApps.values());
-    }
-
-    @Override
-    public ApplicationModel addApplication(String name) {
-        return this.addApplication(KeycloakModelUtils.generateId(), name);
-    }
-
-    @Override
-    public ApplicationModel addApplication(String id, String name) {
-        if (name == null) throw new NullPointerException("name == null");
-        if (id == null) throw new NullPointerException("id == null");
-
-        if (getApplicationNameMap().containsKey(name)) {
-            throw new ModelDuplicateException("Application named '" + name + "' already exists.");
-        }
-
-        ApplicationEntity appEntity = new ApplicationEntity();
-        appEntity.setId(id);
-        appEntity.setName(name);
-        appEntity.setRealmId(getId());
-        appEntity.setEnabled(true);
-
-        ClientEntity clientEntity = new ClientEntity();
-        clientEntity.setId(id);
-        clientEntity.setName(name);
-        clientEntity.setRealmId(getId());
-        clientEntity.setEnabled(true);
-
-        final ApplicationModel app = new ApplicationAdapter(session, this, appEntity, clientEntity, inMemoryModel);
-        session.getKeycloakSessionFactory().publish(new ApplicationCreationEvent() {
-            @Override
-            public ApplicationModel getCreatedApplication() {
-                return app;
-            }
-
-            @Override
-            public ClientModel getCreatedClient() {
-                return app;
-            }
-        });
-
-        allApps.put(id, app);
-
-        return app;
-    }
-
-    @Override
-    public boolean removeApplication(String id) {
-        ApplicationModel appToBeRemoved = this.getApplicationById(id);
-        if (appToBeRemoved == null) return false;
-
-        // remove any composite role assignments for this app
-        for (RoleModel role : this.getRoles()) {
-            RoleAdapter roleAdapter = (RoleAdapter)role;
-            roleAdapter.removeApplicationComposites(id);
-        }
-
-        for (RoleModel role : appToBeRemoved.getRoles()) {
-            appToBeRemoved.removeRole(role);
-        }
-
-        return (allApps.remove(id) != null);
-    }
-
-    @Override
-    public OAuthClientModel addOAuthClient(String name) {
-        return this.addOAuthClient(KeycloakModelUtils.generateId(), name);
-    }
-
-    @Override
-    public OAuthClientModel addOAuthClient(String id, String name) {
-        if (id == null) throw new NullPointerException("id == null");
-        if (name == null) throw new NullPointerException("name == null");
-        if (hasOAuthClientWithName(name)) throw new ModelDuplicateException("OAuth Client with name " + name + " already exists.");
-        OAuthClientEntity oauthClient = new OAuthClientEntity();
-        oauthClient.setId(id);
-        oauthClient.setRealmId(getId());
-        oauthClient.setName(name);
-
-        OAuthClientAdapter oAuthClient = new OAuthClientAdapter(session, this, oauthClient);
-        allOAuthClients.put(id, oAuthClient);
-
-        return oAuthClient;
-    }
-
-    boolean hasOAuthClientWithName(String name) {
-        for (OAuthClientAdapter oaClient : allOAuthClients.values()) {
-            if (oaClient.getName().equals(name)) return true;
-        }
-
-        return false;
-    }
-
-    boolean hasOAuthClientWithClientId(String id) {
-        for (OAuthClientAdapter oaClient : allOAuthClients.values()) {
-            if (oaClient.getClientId().equals(id)) return true;
-        }
-
-        return false;
-    }
-
-    boolean hasUserWithEmail(String email) {
-        for (UserModel user : inMemoryModel.getUsers(getId())) {
-            if (user.getEmail() == null) continue;
-            if (user.getEmail().equals(email)) return true;
-        }
-
-        return false;
-    }
-
-    @Override
-    public boolean removeOAuthClient(String id) {
-        return allOAuthClients.remove(id) != null;
-    }
-
-    @Override
-    public OAuthClientModel getOAuthClient(String name) {
-        for (OAuthClientAdapter oAuthClient : allOAuthClients.values()) {
-            if (oAuthClient.getName().equals(name)) return oAuthClient;
-        }
-
-        return null;
-    }
-
-    @Override
-    public OAuthClientModel getOAuthClientById(String id) {
-        for (OAuthClientAdapter oAuthClient : allOAuthClients.values()) {
-            if (oAuthClient.getId().equals(id)) return oAuthClient;
-        }
-
-        return null;
-    }
-
-    @Override
-    public List<OAuthClientModel> getOAuthClients() {
-        return new ArrayList(allOAuthClients.values());
-    }
-
-    @Override
-    public void addRequiredCredential(String type) {
-        if (type == null) throw new NullPointerException("Credential type can not be null");
-
-        RequiredCredentialModel credentialModel = initRequiredCredentialModel(type);
-
-        List<RequiredCredentialEntity> requiredCredList = realm.getRequiredCredentials();
-        for (RequiredCredentialEntity cred : requiredCredList) {
-            if (type.equals(cred.getType())) return;
-        }
-
-        addRequiredCredential(credentialModel, requiredCredList);
-    }
-
-    protected void addRequiredCredential(RequiredCredentialModel credentialModel, List<RequiredCredentialEntity> persistentCollection) {
-        RequiredCredentialEntity credEntity = new RequiredCredentialEntity();
-        credEntity.setType(credentialModel.getType());
-        credEntity.setFormLabel(credentialModel.getFormLabel());
-        credEntity.setInput(credentialModel.isInput());
-        credEntity.setSecret(credentialModel.isSecret());
-
-        persistentCollection.add(credEntity);
-    }
-
-    @Override
-    public void updateRequiredCredentials(Set<String> creds) {
-        updateRequiredCredentials(creds, realm.getRequiredCredentials());
-    }
-
-    protected void updateRequiredCredentials(Set<String> creds, List<RequiredCredentialEntity> credsEntities) {
-        Set<String> already = new HashSet<String>();
-        Set<RequiredCredentialEntity> toRemove = new HashSet<RequiredCredentialEntity>();
-        for (RequiredCredentialEntity entity : credsEntities) {
-            if (!creds.contains(entity.getType())) {
-                toRemove.add(entity);
-            } else {
-                already.add(entity.getType());
-            }
-        }
-        for (RequiredCredentialEntity entity : toRemove) {
-            credsEntities.remove(entity);
-        }
-        for (String cred : creds) {
-            if (!already.contains(cred)) {
-                RequiredCredentialModel credentialModel = initRequiredCredentialModel(cred);
-                addRequiredCredential(credentialModel, credsEntities);
-            }
-        }
-    }
-
-    @Override
-    public List<RequiredCredentialModel> getRequiredCredentials() {
-        return convertRequiredCredentialEntities(realm.getRequiredCredentials());
-    }
-
-    protected List<RequiredCredentialModel> convertRequiredCredentialEntities(Collection<RequiredCredentialEntity> credEntities) {
-
-        List<RequiredCredentialModel> result = new ArrayList<RequiredCredentialModel>();
-        for (RequiredCredentialEntity entity : credEntities) {
-            RequiredCredentialModel credentialModel = new RequiredCredentialModel();
-            credentialModel.setFormLabel(entity.getFormLabel());
-            credentialModel.setInput(entity.isInput());
-            credentialModel.setSecret(entity.isSecret());
-            credentialModel.setType(entity.getType());
-
-            result.add(credentialModel);
-        }
-        return result;
-    }
-
-    protected RequiredCredentialModel initRequiredCredentialModel(String type) {
-        RequiredCredentialModel credentialModel = RequiredCredentialModel.BUILT_IN.get(type);
-        if (credentialModel == null) {
-            throw new RuntimeException("Unknown credential type " + type);
-        }
-        return credentialModel;
-    }
-
-    @Override
-    public Map<String, String> getBrowserSecurityHeaders() {
-        return realm.getBrowserSecurityHeaders();
-    }
-
-    @Override
-    public void setBrowserSecurityHeaders(Map<String, String> headers) {
-        realm.setBrowserSecurityHeaders(headers);
-    }
-
-    @Override
-    public Map<String, String> getSmtpConfig() {
-        return realm.getSmtpConfig();
-    }
-
-    @Override
-    public void setSmtpConfig(Map<String, String> smtpConfig) {
-        realm.setSmtpConfig(smtpConfig);
-    }
-
-    @Override
-    public List<IdentityProviderModel> getIdentityProviders() {
-        return new ArrayList(allIdProviders.values());
-    }
-
-    @Override
-    public IdentityProviderModel getIdentityProviderByAlias(String alias) {
-        for (IdentityProviderModel identityProviderModel : getIdentityProviders()) {
-            if (identityProviderModel.getAlias().equals(alias)) {
-                return identityProviderModel;
-            }
-        }
-
-        return null;
-    }
-
-    @Override
-    public void addIdentityProvider(IdentityProviderModel identityProvider) {
-        if (identityProvider.getAlias() == null) throw new NullPointerException("identityProvider.getAlias() == null");
-        if (identityProvider.getInternalId() == null) identityProvider.setInternalId(KeycloakModelUtils.generateId());
-        allIdProviders.put(identityProvider.getInternalId(), identityProvider);
-    }
-
-    @Override
-    public void removeIdentityProviderByAlias(String alias) {
-        for (IdentityProviderModel provider : getIdentityProviders()) {
-            if (provider.getAlias().equals(alias)) {
-                allIdProviders.remove(provider.getInternalId());
-                break;
-            }
-        }
-    }
-
-    @Override
-    public void updateIdentityProvider(IdentityProviderModel identityProvider) {
-        removeIdentityProviderByAlias(identityProvider.getAlias());
-        addIdentityProvider(identityProvider);
-    }
-
-    @Override
-    public UserFederationProviderModel addUserFederationProvider(String providerName, Map<String, String> config, int priority, String displayName, int fullSyncPeriod, int changedSyncPeriod, int lastSync) {
-        UserFederationProviderEntity entity = new UserFederationProviderEntity();
-        entity.setId(KeycloakModelUtils.generateId());
-        entity.setPriority(priority);
-        entity.setProviderName(providerName);
-        entity.setConfig(config);
-        if (displayName == null) {
-            displayName = entity.getId();
-        }
-        entity.setDisplayName(displayName);
-        entity.setFullSyncPeriod(fullSyncPeriod);
-        entity.setChangedSyncPeriod(changedSyncPeriod);
-        entity.setLastSync(lastSync);
-        realm.getUserFederationProviders().add(entity);
-
-        return new UserFederationProviderModel(entity.getId(), providerName, config, priority, displayName, fullSyncPeriod, changedSyncPeriod, lastSync);
-    }
-
-    @Override
-    public void removeUserFederationProvider(UserFederationProviderModel provider) {
-        Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
-        while (it.hasNext()) {
-            UserFederationProviderEntity entity = it.next();
-            if (entity.getId().equals(provider.getId())) {
-                session.users().preRemove(this, new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(),
-                        entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync()));
-                it.remove();
-            }
-        }
-    }
-
-    @Override
-    public void updateUserFederationProvider(UserFederationProviderModel model) {
-        Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
-        while (it.hasNext()) {
-            UserFederationProviderEntity entity = it.next();
-            if (entity.getId().equals(model.getId())) {
-                entity.setProviderName(model.getProviderName());
-                entity.setConfig(model.getConfig());
-                entity.setPriority(model.getPriority());
-                String displayName = model.getDisplayName();
-                if (displayName != null) {
-                    entity.setDisplayName(model.getDisplayName());
-                }
-                entity.setFullSyncPeriod(model.getFullSyncPeriod());
-                entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
-                entity.setLastSync(model.getLastSync());
-            }
-        }
-    }
-
-    @Override
-    public List<UserFederationProviderModel> getUserFederationProviders() {
-        List<UserFederationProviderEntity> entities = realm.getUserFederationProviders();
-        List<UserFederationProviderEntity> copy = new LinkedList<UserFederationProviderEntity>();
-        for (UserFederationProviderEntity entity : entities) {
-            copy.add(entity);
-
-        }
-        Collections.sort(copy, new Comparator<UserFederationProviderEntity>() {
-
-            @Override
-            public int compare(UserFederationProviderEntity o1, UserFederationProviderEntity o2) {
-                return o1.getPriority() - o2.getPriority();
-            }
-
-        });
-        List<UserFederationProviderModel> result = new LinkedList<UserFederationProviderModel>();
-        for (UserFederationProviderEntity entity : copy) {
-            result.add(new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(),
-                    entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync()));
-        }
-
-        return result;
-    }
-
-    @Override
-    public void setUserFederationProviders(List<UserFederationProviderModel> providers) {
-        List<UserFederationProviderEntity> entities = new LinkedList<UserFederationProviderEntity>();
-        for (UserFederationProviderModel model : providers) {
-            UserFederationProviderEntity entity = new UserFederationProviderEntity();
-            if (model.getId() != null) entity.setId(model.getId());
-            else entity.setId(KeycloakModelUtils.generateId());
-            entity.setProviderName(model.getProviderName());
-            entity.setConfig(model.getConfig());
-            entity.setPriority(model.getPriority());
-            String displayName = model.getDisplayName();
-            if (displayName == null) {
-                entity.setDisplayName(entity.getId());
-            }
-            entity.setDisplayName(displayName);
-            entity.setFullSyncPeriod(model.getFullSyncPeriod());
-            entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
-            entity.setLastSync(model.getLastSync());
-            entities.add(entity);
-        }
-
-        realm.setUserFederationProviders(entities);
-    }
-
-    @Override
-    public boolean isEventsEnabled() {
-        return realm.isEventsEnabled();
-    }
-
-    @Override
-    public void setEventsEnabled(boolean enabled) {
-        realm.setEventsEnabled(enabled);
-    }
-
-    @Override
-    public long getEventsExpiration() {
-        return realm.getEventsExpiration();
-    }
-
-    @Override
-    public void setEventsExpiration(long expiration) {
-        realm.setEventsExpiration(expiration);
-    }
-
-    @Override
-    public Set<String> getEventsListeners() {
-        return new HashSet<String>(realm.getEventsListeners());
-    }
-
-    @Override
-    public void setEventsListeners(Set<String> listeners) {
-        if (listeners != null) {
-            realm.setEventsListeners(new ArrayList<String>(listeners));
-        } else {
-            realm.setEventsListeners(Collections.EMPTY_LIST);
-        }
-    }
-    
-    @Override
-    public Set<String> getEnabledEventTypes() {
-        return new HashSet<String>(realm.getEnabledEventTypes());
-    }
-
-    @Override
-    public void setEnabledEventTypes(Set<String> enabledEventTypes) {
-        if (enabledEventTypes != null) {
-            realm.setEnabledEventTypes(new ArrayList<String>(enabledEventTypes));
-        } else {
-            realm.setEnabledEventTypes(Collections.EMPTY_LIST);
-        }        
-    }
-
-    @Override
-    public ApplicationModel getMasterAdminApp() {
-        return this.masterAdminApp;
-    }
-
-    @Override
-    public void setMasterAdminApp(ApplicationModel app) {
-        if (app == null) {
-            realm.setAdminAppId(null);
-            this.masterAdminApp = null;
-        } else {
-            String appId = app.getId();
-            if (appId == null) {
-                throw new IllegalStateException("Master Admin app not initialized.");
-            }
-            realm.setAdminAppId(appId);
-            this.masterAdminApp = app;
-        }
-    }
-
-    @Override
-    public boolean isIdentityFederationEnabled() {
-        //TODO: not sure if we will support identity federation storage for file
-        return getIdentityProviders() != null && !getIdentityProviders().isEmpty();
-    }
-
-    @Override
-    public int getAccessCodeLifespanLogin() {
-        return realm.getAccessCodeLifespanLogin();
-    }
-
-    @Override
-    public void setAccessCodeLifespanLogin(int accessCodeLifespanLogin) {
-        realm.setAccessCodeLifespanLogin(accessCodeLifespanLogin);
-    }
-
-    @Override
-    public boolean isInternationalizationEnabled() {
-        return realm.isInternationalizationEnabled();
-    }
-
-    @Override
-    public void setInternationalizationEnabled(boolean enabled) {
-        realm.setInternationalizationEnabled(enabled);
-    }
-
-    @Override
-    public Set<String> getSupportedLocales() {
-        return new HashSet<>(realm.getSupportedLocales());
-    }
-
-    @Override
-    public void setSupportedLocales(Set<String> locales) {
-        realm.setSupportedLocales(new ArrayList<>(locales));
-    }
-
-    @Override
-    public String getDefaultLocale() {
-        return realm.getDefaultLocale();
-    }
-
-    @Override
-    public void setDefaultLocale(String locale) {
-        realm.setDefaultLocale(locale);
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || !(o instanceof RealmModel)) return false;
-
-        RealmModel that = (RealmModel) o;
-        return that.getId().equals(getId());
-    }
-
-    @Override
-    public int hashCode() {
-        return getId().hashCode();
-    }
-
-    @Override
-    public Set<IdentityProviderMapperModel> getIdentityProviderMappers() {
-        Set<IdentityProviderMapperModel> mappings = new HashSet<>();
-        for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) {
-            IdentityProviderMapperModel mapping = new IdentityProviderMapperModel();
-            mapping.setId(entity.getId());
-            mapping.setName(entity.getName());
-            mapping.setIdentityProviderAlias(entity.getIdentityProviderAlias());
-            mapping.setIdentityProviderMapper(entity.getIdentityProviderMapper());
-            Map<String, String> config = new HashMap<String, String>();
-            if (entity.getConfig() != null) {
-                config.putAll(entity.getConfig());
-            }
-            mapping.setConfig(config);
-            mappings.add(mapping);
-        }
-        return mappings;
-    }
-    @Override
-    public Set<IdentityProviderMapperModel> getIdentityProviderMappersByAlias(String brokerAlias) {
-        Set<IdentityProviderMapperModel> mappings = new HashSet<>();
-        for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) {
-            if (!entity.getIdentityProviderAlias().equals(brokerAlias)) {
-                continue;
-            }
-            IdentityProviderMapperModel mapping = new IdentityProviderMapperModel();
-            mapping.setId(entity.getId());
-            mapping.setName(entity.getName());
-            mapping.setIdentityProviderAlias(entity.getIdentityProviderAlias());
-            mapping.setIdentityProviderMapper(entity.getIdentityProviderMapper());
-            Map<String, String> config = new HashMap<String, String>();
-            if (entity.getConfig() != null) {
-                config.putAll(entity.getConfig());
-            }
-            mapping.setConfig(config);
-            mappings.add(mapping);
-        }
-        return mappings;
-    }
-
-    @Override
-    public IdentityProviderMapperModel addIdentityProviderMapper(IdentityProviderMapperModel model) {
-        if (getIdentityProviderMapperByName(model.getIdentityProviderAlias(), model.getIdentityProviderMapper()) != null) {
-            throw new RuntimeException("protocol mapper name must be unique per protocol");
-        }
-        String id = KeycloakModelUtils.generateId();
-        IdentityProviderMapperEntity entity = new IdentityProviderMapperEntity();
-        entity.setId(id);
-        entity.setName(model.getName());
-        entity.setIdentityProviderAlias(model.getIdentityProviderAlias());
-        entity.setIdentityProviderMapper(model.getIdentityProviderMapper());
-        entity.setConfig(model.getConfig());
-
-        this.realm.getIdentityProviderMappers().add(entity);
-        return entityToModel(entity);
-    }
-
-    protected IdentityProviderMapperEntity getIdentityProviderMapperEntity(String id) {
-        for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) {
-            if (entity.getId().equals(id)) {
-                return entity;
-            }
-        }
-        return null;
-
-    }
-
-    protected IdentityProviderMapperEntity getIdentityProviderMapperEntityByName(String alias, String name) {
-        for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) {
-            if (entity.getIdentityProviderAlias().equals(alias) && entity.getName().equals(name)) {
-                return entity;
-            }
-        }
-        return null;
-
-    }
-
-    @Override
-    public void removeIdentityProviderMapper(IdentityProviderMapperModel mapping) {
-        IdentityProviderMapperEntity toDelete = getIdentityProviderMapperEntity(mapping.getId());
-        if (toDelete != null) {
-            this.realm.getIdentityProviderMappers().remove(toDelete);
-        }
-
-    }
-
-    @Override
-    public void updateIdentityProviderMapper(IdentityProviderMapperModel mapping) {
-        IdentityProviderMapperEntity entity = getIdentityProviderMapperEntity(mapping.getId());
-        entity.setIdentityProviderAlias(mapping.getIdentityProviderAlias());
-        entity.setIdentityProviderMapper(mapping.getIdentityProviderMapper());
-        if (entity.getConfig() == null) {
-            entity.setConfig(mapping.getConfig());
-        } else {
-            entity.getConfig().clear();
-            entity.getConfig().putAll(mapping.getConfig());
-        }
-
-    }
-
-    @Override
-    public IdentityProviderMapperModel getIdentityProviderMapperById(String id) {
-        IdentityProviderMapperEntity entity = getIdentityProviderMapperEntity(id);
-        if (entity == null) return null;
-        return entityToModel(entity);
-    }
-
-    @Override
-    public IdentityProviderMapperModel getIdentityProviderMapperByName(String alias, String name) {
-        IdentityProviderMapperEntity entity = getIdentityProviderMapperEntityByName(alias, name);
-        if (entity == null) return null;
-        return entityToModel(entity);
-    }
-
-    protected IdentityProviderMapperModel entityToModel(IdentityProviderMapperEntity entity) {
-        IdentityProviderMapperModel mapping = new IdentityProviderMapperModel();
-        mapping.setId(entity.getId());
-        mapping.setName(entity.getName());
-        mapping.setIdentityProviderAlias(entity.getIdentityProviderAlias());
-        mapping.setIdentityProviderMapper(entity.getIdentityProviderMapper());
-        Map<String, String> config = new HashMap<String, String>();
-        if (entity.getConfig() != null) config.putAll(entity.getConfig());
-        mapping.setConfig(config);
-        return mapping;
-    }
-
-}
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * 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.models.file.adapter;
+
+import org.keycloak.connections.file.InMemoryModel;
+import org.keycloak.enums.SslRequired;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.IdentityProviderMapperModel;
+import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ModelDuplicateException;
+import org.keycloak.models.PasswordPolicy;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RequiredCredentialModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.entities.ClientEntity;
+import org.keycloak.models.entities.IdentityProviderMapperEntity;
+import org.keycloak.models.entities.RealmEntity;
+import org.keycloak.models.entities.RequiredCredentialEntity;
+import org.keycloak.models.entities.RoleEntity;
+import org.keycloak.models.entities.UserFederationProviderEntity;
+import org.keycloak.models.utils.KeycloakModelUtils;
+
+import java.security.Key;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * RealmModel for JSON persistence.
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2015 Red Hat Inc.
+ */
+public class RealmAdapter implements RealmModel {
+
+    private final InMemoryModel inMemoryModel;
+    private final RealmEntity realm;
+
+    protected volatile transient PublicKey publicKey;
+    protected volatile transient PrivateKey privateKey;
+    protected volatile transient X509Certificate certificate;
+    protected volatile transient Key codeSecretKey;
+
+    private volatile transient PasswordPolicy passwordPolicy;
+    private volatile transient KeycloakSession session;
+
+    private final Map<String, ClientModel> allApps = new HashMap<String, ClientModel>();
+    private ClientModel masterAdminApp = null;
+    private final Map<String, RoleAdapter> allRoles = new HashMap<String, RoleAdapter>();
+    private final Map<String, IdentityProviderModel> allIdProviders = new HashMap<String, IdentityProviderModel>();
+
+    public RealmAdapter(KeycloakSession session, RealmEntity realm, InMemoryModel inMemoryModel) {
+        this.session = session;
+        this.realm = realm;
+        this.inMemoryModel = inMemoryModel;
+    }
+
+    public RealmEntity getRealmEnity() {
+        return realm;
+    }
+
+    @Override
+    public String getId() {
+        return realm.getId();
+    }
+
+    @Override
+    public String getName() {
+        return realm.getName();
+    }
+
+    @Override
+    public void setName(String name) {
+        if (getName() == null) {
+            realm.setName(name);
+            return;
+        }
+
+        if (getName().equals(name)) return; // allow setting name to same value
+
+        if (inMemoryModel.getRealmByName(name) != null) throw new ModelDuplicateException("Realm " + name + " already exists.");
+        realm.setName(name);
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return realm.isEnabled();
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        realm.setEnabled(enabled);
+    }
+
+    @Override
+    public SslRequired getSslRequired() {
+        return SslRequired.valueOf(realm.getSslRequired());
+    }
+
+    @Override
+    public void setSslRequired(SslRequired sslRequired) {
+        realm.setSslRequired(sslRequired.name());
+    }
+
+    @Override
+    public boolean isPasswordCredentialGrantAllowed() {
+        return realm.isPasswordCredentialGrantAllowed();
+    }
+
+    @Override
+    public void setPasswordCredentialGrantAllowed(boolean passwordCredentialGrantAllowed) {
+        realm.setPasswordCredentialGrantAllowed(passwordCredentialGrantAllowed);
+    }
+
+    @Override
+    public boolean isRegistrationAllowed() {
+        return realm.isRegistrationAllowed();
+    }
+
+    @Override
+    public void setRegistrationAllowed(boolean registrationAllowed) {
+        realm.setRegistrationAllowed(registrationAllowed);
+    }
+
+    @Override
+    public boolean isRegistrationEmailAsUsername() {
+        return realm.isRegistrationEmailAsUsername();
+    }
+
+    @Override
+    public void setRegistrationEmailAsUsername(boolean registrationEmailAsUsername) {
+        realm.setRegistrationEmailAsUsername(registrationEmailAsUsername);
+    }
+
+    @Override
+    public boolean isRememberMe() {
+        return realm.isRememberMe();
+    }
+
+    @Override
+    public void setRememberMe(boolean rememberMe) {
+        realm.setRememberMe(rememberMe);
+    }
+
+    @Override
+    public boolean isBruteForceProtected() {
+        return realm.isBruteForceProtected();
+    }
+
+    @Override
+    public void setBruteForceProtected(boolean value) {
+        realm.setBruteForceProtected(value);
+    }
+
+    @Override
+    public int getMaxFailureWaitSeconds() {
+        return realm.getMaxFailureWaitSeconds();
+    }
+
+    @Override
+    public void setMaxFailureWaitSeconds(int val) {
+        realm.setMaxFailureWaitSeconds(val);
+    }
+
+    @Override
+    public int getWaitIncrementSeconds() {
+        return realm.getWaitIncrementSeconds();
+    }
+
+    @Override
+    public void setWaitIncrementSeconds(int val) {
+        realm.setWaitIncrementSeconds(val);
+    }
+
+    @Override
+    public long getQuickLoginCheckMilliSeconds() {
+        return realm.getQuickLoginCheckMilliSeconds();
+    }
+
+    @Override
+    public void setQuickLoginCheckMilliSeconds(long val) {
+        realm.setQuickLoginCheckMilliSeconds(val);
+    }
+
+    @Override
+    public int getMinimumQuickLoginWaitSeconds() {
+        return realm.getMinimumQuickLoginWaitSeconds();
+    }
+
+    @Override
+    public void setMinimumQuickLoginWaitSeconds(int val) {
+        realm.setMinimumQuickLoginWaitSeconds(val);
+    }
+
+
+    @Override
+    public int getMaxDeltaTimeSeconds() {
+        return realm.getMaxDeltaTimeSeconds();
+    }
+
+    @Override
+    public void setMaxDeltaTimeSeconds(int val) {
+        realm.setMaxDeltaTimeSeconds(val);
+    }
+
+    @Override
+    public int getFailureFactor() {
+        return realm.getFailureFactor();
+    }
+
+    @Override
+    public void setFailureFactor(int failureFactor) {
+        realm.setFailureFactor(failureFactor);
+    }
+
+
+    @Override
+    public boolean isVerifyEmail() {
+        return realm.isVerifyEmail();
+    }
+
+    @Override
+    public void setVerifyEmail(boolean verifyEmail) {
+        realm.setVerifyEmail(verifyEmail);
+    }
+
+    @Override
+    public boolean isResetPasswordAllowed() {
+        return realm.isResetPasswordAllowed();
+    }
+
+    @Override
+    public void setResetPasswordAllowed(boolean resetPassword) {
+        realm.setResetPasswordAllowed(resetPassword);
+    }
+
+    @Override
+    public PasswordPolicy getPasswordPolicy() {
+        if (passwordPolicy == null) {
+            passwordPolicy = new PasswordPolicy(realm.getPasswordPolicy());
+        }
+        return passwordPolicy;
+    }
+
+    @Override
+    public void setPasswordPolicy(PasswordPolicy policy) {
+        this.passwordPolicy = policy;
+        realm.setPasswordPolicy(policy.toString());
+    }
+
+    @Override
+    public int getNotBefore() {
+        return realm.getNotBefore();
+    }
+
+    @Override
+    public void setNotBefore(int notBefore) {
+        realm.setNotBefore(notBefore);
+    }
+
+
+    @Override
+    public int getSsoSessionIdleTimeout() {
+        return realm.getSsoSessionIdleTimeout();
+    }
+
+    @Override
+    public void setSsoSessionIdleTimeout(int seconds) {
+        realm.setSsoSessionIdleTimeout(seconds);
+    }
+
+    @Override
+    public int getSsoSessionMaxLifespan() {
+        return realm.getSsoSessionMaxLifespan();
+    }
+
+    @Override
+    public void setSsoSessionMaxLifespan(int seconds) {
+        realm.setSsoSessionMaxLifespan(seconds);
+    }
+
+    @Override
+    public int getAccessTokenLifespan() {
+        return realm.getAccessTokenLifespan();
+    }
+
+    @Override
+    public void setAccessTokenLifespan(int tokenLifespan) {
+        realm.setAccessTokenLifespan(tokenLifespan);
+    }
+
+    @Override
+    public int getAccessCodeLifespan() {
+        return realm.getAccessCodeLifespan();
+    }
+
+    @Override
+    public void setAccessCodeLifespan(int accessCodeLifespan) {
+        realm.setAccessCodeLifespan(accessCodeLifespan);
+    }
+
+    @Override
+    public int getAccessCodeLifespanUserAction() {
+        return realm.getAccessCodeLifespanUserAction();
+    }
+
+    @Override
+    public void setAccessCodeLifespanUserAction(int accessCodeLifespanUserAction) {
+        realm.setAccessCodeLifespanUserAction(accessCodeLifespanUserAction);
+    }
+
+    @Override
+    public String getPublicKeyPem() {
+        return realm.getPublicKeyPem();
+    }
+
+    @Override
+    public void setPublicKeyPem(String publicKeyPem) {
+        realm.setPublicKeyPem(publicKeyPem);
+        this.publicKey = null;
+    }
+
+    @Override
+    public X509Certificate getCertificate() {
+        if (certificate != null) return certificate;
+        certificate = KeycloakModelUtils.getCertificate(getCertificatePem());
+        return certificate;
+    }
+
+    @Override
+    public void setCertificate(X509Certificate certificate) {
+        this.certificate = certificate;
+        String certificatePem = KeycloakModelUtils.getPemFromCertificate(certificate);
+        setCertificatePem(certificatePem);
+    }
+
+    @Override
+    public String getCertificatePem() {
+        return realm.getCertificatePem();
+    }
+
+    @Override
+    public void setCertificatePem(String certificate) {
+        realm.setCertificatePem(certificate);
+
+    }
+
+
+    @Override
+    public String getPrivateKeyPem() {
+        return realm.getPrivateKeyPem();
+    }
+
+    @Override
+    public void setPrivateKeyPem(String privateKeyPem) {
+        realm.setPrivateKeyPem(privateKeyPem);
+        this.privateKey = null;
+    }
+
+    @Override
+    public PublicKey getPublicKey() {
+        if (publicKey != null) return publicKey;
+        publicKey = KeycloakModelUtils.getPublicKey(getPublicKeyPem());
+        return publicKey;
+    }
+
+    @Override
+    public void setPublicKey(PublicKey publicKey) {
+        this.publicKey = publicKey;
+        String publicKeyPem = KeycloakModelUtils.getPemFromKey(publicKey);
+        setPublicKeyPem(publicKeyPem);
+    }
+
+    @Override
+    public PrivateKey getPrivateKey() {
+        if (privateKey != null) return privateKey;
+        privateKey = KeycloakModelUtils.getPrivateKey(getPrivateKeyPem());
+        return privateKey;
+    }
+
+    @Override
+    public void setPrivateKey(PrivateKey privateKey) {
+        this.privateKey = privateKey;
+        String privateKeyPem = KeycloakModelUtils.getPemFromKey(privateKey);
+        setPrivateKeyPem(privateKeyPem);
+    }
+
+    @Override
+    public String getCodeSecret() {
+        return realm.getCodeSecret();
+    }
+
+    @Override
+    public Key getCodeSecretKey() {
+        if (codeSecretKey == null) {
+            codeSecretKey = KeycloakModelUtils.getSecretKey(getCodeSecret());
+        }
+        return codeSecretKey;
+    }
+
+    @Override
+    public void setCodeSecret(String codeSecret) {
+        realm.setCodeSecret(codeSecret);
+    }
+
+    @Override
+    public String getLoginTheme() {
+        return realm.getLoginTheme();
+    }
+
+    @Override
+    public void setLoginTheme(String name) {
+        realm.setLoginTheme(name);
+    }
+
+    @Override
+    public String getAccountTheme() {
+        return realm.getAccountTheme();
+    }
+
+    @Override
+    public void setAccountTheme(String name) {
+        realm.setAccountTheme(name);
+    }
+
+    @Override
+    public String getAdminTheme() {
+        return realm.getAdminTheme();
+    }
+
+    @Override
+    public void setAdminTheme(String name) {
+        realm.setAdminTheme(name);
+    }
+
+    @Override
+    public String getEmailTheme() {
+        return realm.getEmailTheme();
+    }
+
+    @Override
+    public void setEmailTheme(String name) {
+        realm.setEmailTheme(name);
+    }
+
+    @Override
+    public RoleAdapter getRole(String name) {
+        for (RoleAdapter role : allRoles.values()) {
+            if (role.getName().equals(name)) return role;
+        }
+        return null;
+    }
+
+    @Override
+    public RoleModel addRole(String name) {
+        return this.addRole(KeycloakModelUtils.generateId(), name);
+    }
+
+    @Override
+    public RoleModel addRole(String id, String name) {
+        if (id == null) throw new NullPointerException("id == null");
+        if (name == null) throw new NullPointerException("name == null");
+        if (hasRoleWithName(name)) throw new ModelDuplicateException("Realm already contains role with name " + name + ".");
+
+        RoleEntity roleEntity = new RoleEntity();
+        roleEntity.setId(id);
+        roleEntity.setName(name);
+        roleEntity.setRealmId(getId());
+
+        RoleAdapter roleModel = new RoleAdapter(this, roleEntity, this);
+        allRoles.put(id, roleModel);
+        return roleModel;
+    }
+
+    @Override
+    public boolean removeRole(RoleModel role) {
+        return removeRoleById(role.getId());
+    }
+
+    @Override
+    public boolean removeRoleById(String id) {
+        if (id == null) throw new NullPointerException("id == null");
+
+        // try realm roles first
+        if (allRoles.remove(id) != null) return true;
+
+        for (ClientModel app : getClients()) {
+            for (RoleModel appRole : app.getRoles()) {
+                if (id.equals(appRole.getId())) {
+                    app.removeRole(appRole);
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    @Override
+    public Set<RoleModel> getRoles() {
+        return new HashSet(allRoles.values());
+    }
+
+    @Override
+    public RoleModel getRoleById(String id) {
+        RoleModel found = allRoles.get(id);
+        if (found != null) return found;
+
+        for (ClientModel app : getClients()) {
+            for (RoleModel appRole : app.getRoles()) {
+                if (appRole.getId().equals(id)) return appRole;
+            }
+        }
+
+        return null;
+    }
+
+    @Override
+    public List<String> getDefaultRoles() {
+        return realm.getDefaultRoles();
+    }
+
+    @Override
+    public void addDefaultRole(String name) {
+        RoleModel role = getRole(name);
+        if (role == null) {
+            addRole(name);
+        }
+
+        List<String> roleNames = getDefaultRoles();
+        if (roleNames.contains(name)) throw new IllegalArgumentException("Realm " + realm.getName() + " already contains default role named " + name);
+
+        roleNames.add(name);
+        realm.setDefaultRoles(roleNames);
+    }
+
+    boolean hasRoleWithName(String name) {
+        for (RoleModel role : allRoles.values()) {
+            if (role.getName().equals(name)) return true;
+        }
+
+        return false;
+    }
+
+    @Override
+    public void updateDefaultRoles(String[] defaultRoles) {
+        List<String> roleNames = new ArrayList<String>();
+        for (String roleName : defaultRoles) {
+            RoleModel role = getRole(roleName);
+            if (role == null) {
+                addRole(roleName);
+            }
+
+            roleNames.add(roleName);
+        }
+
+        realm.setDefaultRoles(roleNames);
+    }
+
+    @Override
+    public ClientModel getClientById(String id) {
+        return allApps.get(id);
+    }
+
+    @Override
+    public ClientModel getClientByClientId(String clientId) {
+        for (ClientModel app : getClients()) {
+            if (app.getClientId().equals(clientId)) return app;
+        }
+
+        return null;
+    }
+
+    @Override
+    public Map<String, ClientModel> getClientNameMap() {
+        Map<String, ClientModel> resourceMap = new HashMap<String, ClientModel>();
+        for (ClientModel resource : getClients()) {
+            resourceMap.put(resource.getClientId(), resource);
+        }
+        return resourceMap;
+    }
+
+    @Override
+    public List<ClientModel> getClients() {
+        return new ArrayList<ClientModel>(allApps.values());
+    }
+
+    @Override
+    public ClientModel addClient(String name) {
+        return this.addClient(KeycloakModelUtils.generateId(), name);
+    }
+
+    @Override
+    public ClientModel addClient(String id, String clientId) {
+        if (clientId == null) throw new NullPointerException("name == null");
+        if (id == null) throw new NullPointerException("id == null");
+
+        if (getClientNameMap().containsKey(clientId)) {
+            throw new ModelDuplicateException("Application named '" + clientId + "' already exists.");
+        }
+
+        ClientEntity appEntity = new ClientEntity();
+        appEntity.setId(id);
+        appEntity.setClientId(clientId);
+        appEntity.setRealmId(getId());
+        appEntity.setEnabled(true);
+
+        final ClientModel app = new ClientAdapter(session, this, appEntity, inMemoryModel);
+        session.getKeycloakSessionFactory().publish(new ClientCreationEvent() {
+            @Override
+            public ClientModel getCreatedClient() {
+                return app;
+            }
+        });
+
+        allApps.put(id, app);
+
+        return app;
+    }
+
+    @Override
+    public boolean removeClient(String id) {
+        ClientModel appToBeRemoved = this.getClientById(id);
+        if (appToBeRemoved == null) return false;
+
+        // remove any composite role assignments for this app
+        for (RoleModel role : this.getRoles()) {
+            RoleAdapter roleAdapter = (RoleAdapter)role;
+            roleAdapter.removeApplicationComposites(id);
+        }
+
+        for (RoleModel role : appToBeRemoved.getRoles()) {
+            appToBeRemoved.removeRole(role);
+        }
+
+        return (allApps.remove(id) != null);
+    }
+
+    boolean hasUserWithEmail(String email) {
+        for (UserModel user : inMemoryModel.getUsers(getId())) {
+            if (user.getEmail() == null) continue;
+            if (user.getEmail().equals(email)) return true;
+        }
+
+        return false;
+    }
+
+    @Override
+    public void addRequiredCredential(String type) {
+        if (type == null) throw new NullPointerException("Credential type can not be null");
+
+        RequiredCredentialModel credentialModel = initRequiredCredentialModel(type);
+
+        List<RequiredCredentialEntity> requiredCredList = realm.getRequiredCredentials();
+        for (RequiredCredentialEntity cred : requiredCredList) {
+            if (type.equals(cred.getType())) return;
+        }
+
+        addRequiredCredential(credentialModel, requiredCredList);
+    }
+
+    protected void addRequiredCredential(RequiredCredentialModel credentialModel, List<RequiredCredentialEntity> persistentCollection) {
+        RequiredCredentialEntity credEntity = new RequiredCredentialEntity();
+        credEntity.setType(credentialModel.getType());
+        credEntity.setFormLabel(credentialModel.getFormLabel());
+        credEntity.setInput(credentialModel.isInput());
+        credEntity.setSecret(credentialModel.isSecret());
+
+        persistentCollection.add(credEntity);
+    }
+
+    @Override
+    public void updateRequiredCredentials(Set<String> creds) {
+        updateRequiredCredentials(creds, realm.getRequiredCredentials());
+    }
+
+    protected void updateRequiredCredentials(Set<String> creds, List<RequiredCredentialEntity> credsEntities) {
+        Set<String> already = new HashSet<String>();
+        Set<RequiredCredentialEntity> toRemove = new HashSet<RequiredCredentialEntity>();
+        for (RequiredCredentialEntity entity : credsEntities) {
+            if (!creds.contains(entity.getType())) {
+                toRemove.add(entity);
+            } else {
+                already.add(entity.getType());
+            }
+        }
+        for (RequiredCredentialEntity entity : toRemove) {
+            credsEntities.remove(entity);
+        }
+        for (String cred : creds) {
+            if (!already.contains(cred)) {
+                RequiredCredentialModel credentialModel = initRequiredCredentialModel(cred);
+                addRequiredCredential(credentialModel, credsEntities);
+            }
+        }
+    }
+
+    @Override
+    public List<RequiredCredentialModel> getRequiredCredentials() {
+        return convertRequiredCredentialEntities(realm.getRequiredCredentials());
+    }
+
+    protected List<RequiredCredentialModel> convertRequiredCredentialEntities(Collection<RequiredCredentialEntity> credEntities) {
+
+        List<RequiredCredentialModel> result = new ArrayList<RequiredCredentialModel>();
+        for (RequiredCredentialEntity entity : credEntities) {
+            RequiredCredentialModel credentialModel = new RequiredCredentialModel();
+            credentialModel.setFormLabel(entity.getFormLabel());
+            credentialModel.setInput(entity.isInput());
+            credentialModel.setSecret(entity.isSecret());
+            credentialModel.setType(entity.getType());
+
+            result.add(credentialModel);
+        }
+        return result;
+    }
+
+    protected RequiredCredentialModel initRequiredCredentialModel(String type) {
+        RequiredCredentialModel credentialModel = RequiredCredentialModel.BUILT_IN.get(type);
+        if (credentialModel == null) {
+            throw new RuntimeException("Unknown credential type " + type);
+        }
+        return credentialModel;
+    }
+
+    @Override
+    public Map<String, String> getBrowserSecurityHeaders() {
+        return realm.getBrowserSecurityHeaders();
+    }
+
+    @Override
+    public void setBrowserSecurityHeaders(Map<String, String> headers) {
+        realm.setBrowserSecurityHeaders(headers);
+    }
+
+    @Override
+    public Map<String, String> getSmtpConfig() {
+        return realm.getSmtpConfig();
+    }
+
+    @Override
+    public void setSmtpConfig(Map<String, String> smtpConfig) {
+        realm.setSmtpConfig(smtpConfig);
+    }
+
+    @Override
+    public List<IdentityProviderModel> getIdentityProviders() {
+        return new ArrayList(allIdProviders.values());
+    }
+
+    @Override
+    public IdentityProviderModel getIdentityProviderByAlias(String alias) {
+        for (IdentityProviderModel identityProviderModel : getIdentityProviders()) {
+            if (identityProviderModel.getAlias().equals(alias)) {
+                return identityProviderModel;
+            }
+        }
+
+        return null;
+    }
+
+    @Override
+    public void addIdentityProvider(IdentityProviderModel identityProvider) {
+        if (identityProvider.getAlias() == null) throw new NullPointerException("identityProvider.getAlias() == null");
+        if (identityProvider.getInternalId() == null) identityProvider.setInternalId(KeycloakModelUtils.generateId());
+        allIdProviders.put(identityProvider.getInternalId(), identityProvider);
+    }
+
+    @Override
+    public void removeIdentityProviderByAlias(String alias) {
+        for (IdentityProviderModel provider : getIdentityProviders()) {
+            if (provider.getAlias().equals(alias)) {
+                allIdProviders.remove(provider.getInternalId());
+                break;
+            }
+        }
+    }
+
+    @Override
+    public void updateIdentityProvider(IdentityProviderModel identityProvider) {
+        removeIdentityProviderByAlias(identityProvider.getAlias());
+        addIdentityProvider(identityProvider);
+    }
+
+    @Override
+    public UserFederationProviderModel addUserFederationProvider(String providerName, Map<String, String> config, int priority, String displayName, int fullSyncPeriod, int changedSyncPeriod, int lastSync) {
+        UserFederationProviderEntity entity = new UserFederationProviderEntity();
+        entity.setId(KeycloakModelUtils.generateId());
+        entity.setPriority(priority);
+        entity.setProviderName(providerName);
+        entity.setConfig(config);
+        if (displayName == null) {
+            displayName = entity.getId();
+        }
+        entity.setDisplayName(displayName);
+        entity.setFullSyncPeriod(fullSyncPeriod);
+        entity.setChangedSyncPeriod(changedSyncPeriod);
+        entity.setLastSync(lastSync);
+        realm.getUserFederationProviders().add(entity);
+
+        return new UserFederationProviderModel(entity.getId(), providerName, config, priority, displayName, fullSyncPeriod, changedSyncPeriod, lastSync);
+    }
+
+    @Override
+    public void removeUserFederationProvider(UserFederationProviderModel provider) {
+        Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
+        while (it.hasNext()) {
+            UserFederationProviderEntity entity = it.next();
+            if (entity.getId().equals(provider.getId())) {
+                session.users().preRemove(this, new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(),
+                        entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync()));
+                it.remove();
+            }
+        }
+    }
+
+    @Override
+    public void updateUserFederationProvider(UserFederationProviderModel model) {
+        Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
+        while (it.hasNext()) {
+            UserFederationProviderEntity entity = it.next();
+            if (entity.getId().equals(model.getId())) {
+                entity.setProviderName(model.getProviderName());
+                entity.setConfig(model.getConfig());
+                entity.setPriority(model.getPriority());
+                String displayName = model.getDisplayName();
+                if (displayName != null) {
+                    entity.setDisplayName(model.getDisplayName());
+                }
+                entity.setFullSyncPeriod(model.getFullSyncPeriod());
+                entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
+                entity.setLastSync(model.getLastSync());
+            }
+        }
+    }
+
+    @Override
+    public List<UserFederationProviderModel> getUserFederationProviders() {
+        List<UserFederationProviderEntity> entities = realm.getUserFederationProviders();
+        List<UserFederationProviderEntity> copy = new LinkedList<UserFederationProviderEntity>();
+        for (UserFederationProviderEntity entity : entities) {
+            copy.add(entity);
+
+        }
+        Collections.sort(copy, new Comparator<UserFederationProviderEntity>() {
+
+            @Override
+            public int compare(UserFederationProviderEntity o1, UserFederationProviderEntity o2) {
+                return o1.getPriority() - o2.getPriority();
+            }
+
+        });
+        List<UserFederationProviderModel> result = new LinkedList<UserFederationProviderModel>();
+        for (UserFederationProviderEntity entity : copy) {
+            result.add(new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(),
+                    entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync()));
+        }
+
+        return result;
+    }
+
+    @Override
+    public void setUserFederationProviders(List<UserFederationProviderModel> providers) {
+        List<UserFederationProviderEntity> entities = new LinkedList<UserFederationProviderEntity>();
+        for (UserFederationProviderModel model : providers) {
+            UserFederationProviderEntity entity = new UserFederationProviderEntity();
+            if (model.getId() != null) entity.setId(model.getId());
+            else entity.setId(KeycloakModelUtils.generateId());
+            entity.setProviderName(model.getProviderName());
+            entity.setConfig(model.getConfig());
+            entity.setPriority(model.getPriority());
+            String displayName = model.getDisplayName();
+            if (displayName == null) {
+                entity.setDisplayName(entity.getId());
+            }
+            entity.setDisplayName(displayName);
+            entity.setFullSyncPeriod(model.getFullSyncPeriod());
+            entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
+            entity.setLastSync(model.getLastSync());
+            entities.add(entity);
+        }
+
+        realm.setUserFederationProviders(entities);
+    }
+
+    @Override
+    public boolean isEventsEnabled() {
+        return realm.isEventsEnabled();
+    }
+
+    @Override
+    public void setEventsEnabled(boolean enabled) {
+        realm.setEventsEnabled(enabled);
+    }
+
+    @Override
+    public long getEventsExpiration() {
+        return realm.getEventsExpiration();
+    }
+
+    @Override
+    public void setEventsExpiration(long expiration) {
+        realm.setEventsExpiration(expiration);
+    }
+
+    @Override
+    public Set<String> getEventsListeners() {
+        return new HashSet<String>(realm.getEventsListeners());
+    }
+
+    @Override
+    public void setEventsListeners(Set<String> listeners) {
+        if (listeners != null) {
+            realm.setEventsListeners(new ArrayList<String>(listeners));
+        } else {
+            realm.setEventsListeners(Collections.EMPTY_LIST);
+        }
+    }
+    
+    @Override
+    public Set<String> getEnabledEventTypes() {
+        return new HashSet<String>(realm.getEnabledEventTypes());
+    }
+
+    @Override
+    public void setEnabledEventTypes(Set<String> enabledEventTypes) {
+        if (enabledEventTypes != null) {
+            realm.setEnabledEventTypes(new ArrayList<String>(enabledEventTypes));
+        } else {
+            realm.setEnabledEventTypes(Collections.EMPTY_LIST);
+        }        
+    }
+
+    @Override
+    public ClientModel getMasterAdminClient() {
+        return this.masterAdminApp;
+    }
+
+    @Override
+    public void setMasterAdminClient(ClientModel client) {
+        if (client == null) {
+            realm.setAdminAppId(null);
+            this.masterAdminApp = null;
+        } else {
+            String appId = client.getId();
+            if (appId == null) {
+                throw new IllegalStateException("Master Admin app not initialized.");
+            }
+            realm.setAdminAppId(appId);
+            this.masterAdminApp = client;
+        }
+    }
+
+    @Override
+    public boolean isIdentityFederationEnabled() {
+        //TODO: not sure if we will support identity federation storage for file
+        return getIdentityProviders() != null && !getIdentityProviders().isEmpty();
+    }
+
+    @Override
+    public int getAccessCodeLifespanLogin() {
+        return realm.getAccessCodeLifespanLogin();
+    }
+
+    @Override
+    public void setAccessCodeLifespanLogin(int accessCodeLifespanLogin) {
+        realm.setAccessCodeLifespanLogin(accessCodeLifespanLogin);
+    }
+
+    @Override
+    public boolean isInternationalizationEnabled() {
+        return realm.isInternationalizationEnabled();
+    }
+
+    @Override
+    public void setInternationalizationEnabled(boolean enabled) {
+        realm.setInternationalizationEnabled(enabled);
+    }
+
+    @Override
+    public Set<String> getSupportedLocales() {
+        return new HashSet<>(realm.getSupportedLocales());
+    }
+
+    @Override
+    public void setSupportedLocales(Set<String> locales) {
+        realm.setSupportedLocales(new ArrayList<>(locales));
+    }
+
+    @Override
+    public String getDefaultLocale() {
+        return realm.getDefaultLocale();
+    }
+
+    @Override
+    public void setDefaultLocale(String locale) {
+        realm.setDefaultLocale(locale);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof RealmModel)) return false;
+
+        RealmModel that = (RealmModel) o;
+        return that.getId().equals(getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
+
+    @Override
+    public Set<IdentityProviderMapperModel> getIdentityProviderMappers() {
+        Set<IdentityProviderMapperModel> mappings = new HashSet<>();
+        for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) {
+            IdentityProviderMapperModel mapping = new IdentityProviderMapperModel();
+            mapping.setId(entity.getId());
+            mapping.setName(entity.getName());
+            mapping.setIdentityProviderAlias(entity.getIdentityProviderAlias());
+            mapping.setIdentityProviderMapper(entity.getIdentityProviderMapper());
+            Map<String, String> config = new HashMap<String, String>();
+            if (entity.getConfig() != null) {
+                config.putAll(entity.getConfig());
+            }
+            mapping.setConfig(config);
+            mappings.add(mapping);
+        }
+        return mappings;
+    }
+    @Override
+    public Set<IdentityProviderMapperModel> getIdentityProviderMappersByAlias(String brokerAlias) {
+        Set<IdentityProviderMapperModel> mappings = new HashSet<>();
+        for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) {
+            if (!entity.getIdentityProviderAlias().equals(brokerAlias)) {
+                continue;
+            }
+            IdentityProviderMapperModel mapping = new IdentityProviderMapperModel();
+            mapping.setId(entity.getId());
+            mapping.setName(entity.getName());
+            mapping.setIdentityProviderAlias(entity.getIdentityProviderAlias());
+            mapping.setIdentityProviderMapper(entity.getIdentityProviderMapper());
+            Map<String, String> config = new HashMap<String, String>();
+            if (entity.getConfig() != null) {
+                config.putAll(entity.getConfig());
+            }
+            mapping.setConfig(config);
+            mappings.add(mapping);
+        }
+        return mappings;
+    }
+
+    @Override
+    public IdentityProviderMapperModel addIdentityProviderMapper(IdentityProviderMapperModel model) {
+        if (getIdentityProviderMapperByName(model.getIdentityProviderAlias(), model.getIdentityProviderMapper()) != null) {
+            throw new RuntimeException("protocol mapper name must be unique per protocol");
+        }
+        String id = KeycloakModelUtils.generateId();
+        IdentityProviderMapperEntity entity = new IdentityProviderMapperEntity();
+        entity.setId(id);
+        entity.setName(model.getName());
+        entity.setIdentityProviderAlias(model.getIdentityProviderAlias());
+        entity.setIdentityProviderMapper(model.getIdentityProviderMapper());
+        entity.setConfig(model.getConfig());
+
+        this.realm.getIdentityProviderMappers().add(entity);
+        return entityToModel(entity);
+    }
+
+    protected IdentityProviderMapperEntity getIdentityProviderMapperEntity(String id) {
+        for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) {
+            if (entity.getId().equals(id)) {
+                return entity;
+            }
+        }
+        return null;
+
+    }
+
+    protected IdentityProviderMapperEntity getIdentityProviderMapperEntityByName(String alias, String name) {
+        for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) {
+            if (entity.getIdentityProviderAlias().equals(alias) && entity.getName().equals(name)) {
+                return entity;
+            }
+        }
+        return null;
+
+    }
+
+    @Override
+    public void removeIdentityProviderMapper(IdentityProviderMapperModel mapping) {
+        IdentityProviderMapperEntity toDelete = getIdentityProviderMapperEntity(mapping.getId());
+        if (toDelete != null) {
+            this.realm.getIdentityProviderMappers().remove(toDelete);
+        }
+
+    }
+
+    @Override
+    public void updateIdentityProviderMapper(IdentityProviderMapperModel mapping) {
+        IdentityProviderMapperEntity entity = getIdentityProviderMapperEntity(mapping.getId());
+        entity.setIdentityProviderAlias(mapping.getIdentityProviderAlias());
+        entity.setIdentityProviderMapper(mapping.getIdentityProviderMapper());
+        if (entity.getConfig() == null) {
+            entity.setConfig(mapping.getConfig());
+        } else {
+            entity.getConfig().clear();
+            entity.getConfig().putAll(mapping.getConfig());
+        }
+
+    }
+
+    @Override
+    public IdentityProviderMapperModel getIdentityProviderMapperById(String id) {
+        IdentityProviderMapperEntity entity = getIdentityProviderMapperEntity(id);
+        if (entity == null) return null;
+        return entityToModel(entity);
+    }
+
+    @Override
+    public IdentityProviderMapperModel getIdentityProviderMapperByName(String alias, String name) {
+        IdentityProviderMapperEntity entity = getIdentityProviderMapperEntityByName(alias, name);
+        if (entity == null) return null;
+        return entityToModel(entity);
+    }
+
+    protected IdentityProviderMapperModel entityToModel(IdentityProviderMapperEntity entity) {
+        IdentityProviderMapperModel mapping = new IdentityProviderMapperModel();
+        mapping.setId(entity.getId());
+        mapping.setName(entity.getName());
+        mapping.setIdentityProviderAlias(entity.getIdentityProviderAlias());
+        mapping.setIdentityProviderMapper(entity.getIdentityProviderMapper());
+        Map<String, String> config = new HashMap<String, String>();
+        if (entity.getConfig() != null) config.putAll(entity.getConfig());
+        mapping.setConfig(config);
+        return mapping;
+    }
+
+}
diff --git a/model/file/src/main/java/org/keycloak/models/file/adapter/RoleAdapter.java b/model/file/src/main/java/org/keycloak/models/file/adapter/RoleAdapter.java
index 28a2f90..f53c0ce 100755
--- a/model/file/src/main/java/org/keycloak/models/file/adapter/RoleAdapter.java
+++ b/model/file/src/main/java/org/keycloak/models/file/adapter/RoleAdapter.java
@@ -111,7 +111,7 @@ public class RoleAdapter implements RoleModel {
         Set<RoleModel> toBeRemoved = new HashSet<RoleModel>();
         for (RoleModel compositeRole : getComposites()) {
             RoleAdapter roleAdapter = (RoleAdapter)compositeRole;
-            if (appId.equals(roleAdapter.getRoleEntity().getApplicationId())) {
+            if (appId.equals(roleAdapter.getRoleEntity().getClientId())) {
                 toBeRemoved.add(compositeRole);
             } else {
                 roleAdapter.removeApplicationComposites(appId);
@@ -143,8 +143,8 @@ public class RoleAdapter implements RoleModel {
             // Compute it
             if (role.getRealmId() != null) {
                 roleContainer = realm;//new RealmAdapter(session, realm);
-            } else if (role.getApplicationId() != null) {
-                roleContainer = realm.getApplicationById(role.getApplicationId());//new ApplicationAdapter(session, realm, appEntity);
+            } else if (role.getClientId() != null) {
+                roleContainer = realm.getClientById(role.getClientId());//new ApplicationAdapter(session, realm, appEntity);
             } else {
                 throw new IllegalStateException("Both realmId and applicationId are null for role: " + this);
             }
diff --git a/model/file/src/main/java/org/keycloak/models/file/adapter/UserAdapter.java b/model/file/src/main/java/org/keycloak/models/file/adapter/UserAdapter.java
index f1a7a28..e9ba84a 100755
--- a/model/file/src/main/java/org/keycloak/models/file/adapter/UserAdapter.java
+++ b/model/file/src/main/java/org/keycloak/models/file/adapter/UserAdapter.java
@@ -16,7 +16,7 @@
  */
 package org.keycloak.models.file.adapter;
 
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.PasswordPolicy;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
@@ -325,12 +325,12 @@ public class UserAdapter implements UserModel, Comparable {
     }
 
     @Override
-    public Set<RoleModel> getApplicationRoleMappings(ApplicationModel app) {
+    public Set<RoleModel> getClientRoleMappings(ClientModel app) {
         Set<RoleModel> result = new HashSet<RoleModel>();
 
         for (RoleModel role : allRoles) {
             RoleEntity roleEntity = ((RoleAdapter)role).getRoleEntity();
-            if (app.getId().equals(roleEntity.getApplicationId())) {
+            if (app.getId().equals(roleEntity.getClientId())) {
                 result.add(new RoleAdapter(realm, roleEntity, app));
             }
         }
diff --git a/model/file/src/main/java/org/keycloak/models/file/FileRealmProvider.java b/model/file/src/main/java/org/keycloak/models/file/FileRealmProvider.java
index 52b3f39..3f23b5c 100644
--- a/model/file/src/main/java/org/keycloak/models/file/FileRealmProvider.java
+++ b/model/file/src/main/java/org/keycloak/models/file/FileRealmProvider.java
@@ -16,21 +16,20 @@
  */
 package org.keycloak.models.file;
 
-import org.keycloak.models.file.adapter.RealmAdapter;
-import java.util.ArrayList;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.connections.file.FileConnectionProvider;
+import org.keycloak.connections.file.InMemoryModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.OAuthClientModel;
+import org.keycloak.models.ModelDuplicateException;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RealmProvider;
 import org.keycloak.models.RoleModel;
+import org.keycloak.models.entities.RealmEntity;
+import org.keycloak.models.file.adapter.RealmAdapter;
 import org.keycloak.models.utils.KeycloakModelUtils;
 
+import java.util.ArrayList;
 import java.util.List;
-import org.keycloak.connections.file.FileConnectionProvider;
-import org.keycloak.connections.file.InMemoryModel;
-import org.keycloak.models.ModelDuplicateException;
-import org.keycloak.models.entities.RealmEntity;
 
 /**
  * Realm Provider for JSON persistence.
@@ -100,13 +99,8 @@ public class FileRealmProvider implements RealmProvider {
     }
 
     @Override
-    public ApplicationModel getApplicationById(String id, RealmModel realm) {
-        return realm.getApplicationById(id);
-    }
-
-    @Override
-    public OAuthClientModel getOAuthClientById(String id, RealmModel realm) {
-        return realm.getOAuthClientById(id);
+    public ClientModel getClientById(String id, RealmModel realm) {
+        return realm.getClientById(id);
     }
 
 }
diff --git a/model/file/src/main/java/org/keycloak/models/file/FileUserProvider.java b/model/file/src/main/java/org/keycloak/models/file/FileUserProvider.java
index 456831f..850d1a7 100644
--- a/model/file/src/main/java/org/keycloak/models/file/FileUserProvider.java
+++ b/model/file/src/main/java/org/keycloak/models/file/FileUserProvider.java
@@ -36,7 +36,7 @@ import java.util.Set;
 import java.util.regex.Pattern;
 import org.keycloak.connections.file.FileConnectionProvider;
 import org.keycloak.connections.file.InMemoryModel;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.CredentialValidationOutput;
 import org.keycloak.models.ModelDuplicateException;
 import org.keycloak.models.entities.FederatedIdentityEntity;
@@ -276,7 +276,7 @@ public class FileUserProvider implements UserProvider {
                 userModel.grantRole(realm.getRole(r));
             }
 
-            for (ApplicationModel application : realm.getApplications()) {
+            for (ClientModel application : realm.getClients()) {
                 for (String r : application.getDefaultRoles()) {
                     userModel.grantRole(application.getRole(r));
                 }
diff --git a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanRealmCache.java b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanRealmCache.java
index a01a135..b5204e8 100755
--- a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanRealmCache.java
+++ b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanRealmCache.java
@@ -4,7 +4,6 @@ import org.infinispan.Cache;
 import org.jboss.logging.Logger;
 import org.keycloak.models.cache.RealmCache;
 import org.keycloak.models.cache.entities.CachedApplication;
-import org.keycloak.models.cache.entities.CachedOAuthClient;
 import org.keycloak.models.cache.entities.CachedRealm;
 import org.keycloak.models.cache.entities.CachedRole;
 
@@ -103,31 +102,6 @@ public class InfinispanRealmCache implements RealmCache {
     }
 
     @Override
-    public CachedOAuthClient getOAuthClient(String id) {
-        if (!enabled) return null;
-        return get(id, CachedOAuthClient.class);
-    }
-
-    @Override
-    public void invalidateOAuthClient(CachedOAuthClient client) {
-        logger.tracev("Removing oauth client {0}", client.getId());
-        cache.remove(client.getId());
-    }
-
-    @Override
-    public void addCachedOAuthClient(CachedOAuthClient client) {
-        if (!enabled) return;
-        logger.tracev("Adding oauth client {0}", client.getId());
-        cache.put(client.getId(), client);
-    }
-
-    @Override
-    public void invalidateCachedOAuthClientById(String id) {
-        logger.tracev("Removing oauth client {0}", id);
-        cache.remove(id);
-    }
-
-    @Override
     public CachedRole getRole(String id) {
         if (!enabled) return null;
         return get(id, CachedRole.class);
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheRealmProvider.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheRealmProvider.java
index 8a4c869..9810d50 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheRealmProvider.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheRealmProvider.java
@@ -17,8 +17,4 @@ public interface CacheRealmProvider extends RealmProvider {
     void registerApplicationInvalidation(String id);
 
     void registerRoleInvalidation(String id);
-
-    void registerOAuthClientInvalidation(String id);
-
-    void registerUserInvalidation(String id);
 }
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java
index 12e89e1..5330fbc 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java
@@ -1,12 +1,12 @@
 package org.keycloak.models.cache;
 
-import org.keycloak.models.ClientIdentityProviderMappingModel;
 import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientIdentityProviderMappingModel;
 import org.keycloak.models.ProtocolMapperModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleContainerModel;
 import org.keycloak.models.RoleModel;
-import org.keycloak.models.cache.entities.CachedClient;
+import org.keycloak.models.cache.entities.CachedApplication;
 
 import java.util.HashMap;
 import java.util.HashSet;
@@ -18,80 +18,88 @@ import java.util.Set;
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public abstract class ClientAdapter implements ClientModel {
-    protected CachedClient cachedClient;
+public class ClientAdapter implements ClientModel {
     protected CacheRealmProvider cacheSession;
-    protected ClientModel updatedClient;
     protected RealmModel cachedRealm;
     protected RealmCache cache;
 
-    public ClientAdapter(RealmModel cachedRealm, CachedClient cached, RealmCache cache, CacheRealmProvider cacheSession) {
+    protected ClientModel updated;
+    protected CachedApplication cached;
+
+    public ClientAdapter(RealmModel cachedRealm, CachedApplication cached, CacheRealmProvider cacheSession, RealmCache cache) {
         this.cachedRealm = cachedRealm;
         this.cache = cache;
         this.cacheSession = cacheSession;
-        this.cachedClient = cached;
+        this.cached = cached;
     }
 
-    protected abstract void getDelegateForUpdate();
+    private void getDelegateForUpdate() {
+        if (updated == null) {
+            cacheSession.registerApplicationInvalidation(getId());
+            updated = updated = cacheSession.getDelegate().getClientById(getId(), cachedRealm);
+            if (updated == null) throw new IllegalStateException("Not found in database");
+        }
+    }
 
     @Override
-    public String getId() {
-        if (updatedClient != null) return updatedClient.getId();
-        return cachedClient.getId();
+    public void updateClient() {
+        if (updated != null) updated.updateClient();
     }
 
-
     @Override
-    public abstract String getClientId();
+    public String getId() {
+        if (updated != null) return updated.getId();
+        return cached.getId();
+    }
 
     public Set<String> getWebOrigins() {
-        if (updatedClient != null) return updatedClient.getWebOrigins();
-        return cachedClient.getWebOrigins();
+        if (updated != null) return updated.getWebOrigins();
+        return cached.getWebOrigins();
     }
 
     public void setWebOrigins(Set<String> webOrigins) {
         getDelegateForUpdate();
-        updatedClient.setWebOrigins(webOrigins);
+        updated.setWebOrigins(webOrigins);
     }
 
     public void addWebOrigin(String webOrigin) {
         getDelegateForUpdate();
-        updatedClient.addWebOrigin(webOrigin);
+        updated.addWebOrigin(webOrigin);
     }
 
     public void removeWebOrigin(String webOrigin) {
         getDelegateForUpdate();
-        updatedClient.removeWebOrigin(webOrigin);
+        updated.removeWebOrigin(webOrigin);
     }
 
     public Set<String> getRedirectUris() {
-        if (updatedClient != null) return updatedClient.getRedirectUris();
-        return cachedClient.getRedirectUris();
+        if (updated != null) return updated.getRedirectUris();
+        return cached.getRedirectUris();
     }
 
     public void setRedirectUris(Set<String> redirectUris) {
         getDelegateForUpdate();
-        updatedClient.setRedirectUris(redirectUris);
+        updated.setRedirectUris(redirectUris);
     }
 
     public void addRedirectUri(String redirectUri) {
         getDelegateForUpdate();
-        updatedClient.addRedirectUri(redirectUri);
+        updated.addRedirectUri(redirectUri);
     }
 
     public void removeRedirectUri(String redirectUri) {
         getDelegateForUpdate();
-        updatedClient.removeRedirectUri(redirectUri);
+        updated.removeRedirectUri(redirectUri);
     }
 
     public boolean isEnabled() {
-        if (updatedClient != null) return updatedClient.isEnabled();
-        return cachedClient.isEnabled();
+        if (updated != null) return updated.isEnabled();
+        return cached.isEnabled();
     }
 
     public void setEnabled(boolean enabled) {
         getDelegateForUpdate();
-        updatedClient.setEnabled(enabled);
+        updated.setEnabled(enabled);
     }
 
     public boolean validateSecret(String secret) {
@@ -99,62 +107,62 @@ public abstract class ClientAdapter implements ClientModel {
     }
 
     public String getSecret() {
-        if (updatedClient != null) return updatedClient.getSecret();
-        return cachedClient.getSecret();
+        if (updated != null) return updated.getSecret();
+        return cached.getSecret();
     }
 
     public void setSecret(String secret) {
         getDelegateForUpdate();
-        updatedClient.setSecret(secret);
+        updated.setSecret(secret);
     }
 
     public boolean isPublicClient() {
-        if (updatedClient != null) return updatedClient.isPublicClient();
-        return cachedClient.isPublicClient();
+        if (updated != null) return updated.isPublicClient();
+        return cached.isPublicClient();
     }
 
     public void setPublicClient(boolean flag) {
         getDelegateForUpdate();
-        updatedClient.setPublicClient(flag);
+        updated.setPublicClient(flag);
     }
 
     public boolean isFrontchannelLogout() {
-        if (updatedClient != null) return updatedClient.isPublicClient();
-        return cachedClient.isFrontchannelLogout();
+        if (updated != null) return updated.isPublicClient();
+        return cached.isFrontchannelLogout();
     }
 
     public void setFrontchannelLogout(boolean flag) {
         getDelegateForUpdate();
-        updatedClient.setFrontchannelLogout(flag);
+        updated.setFrontchannelLogout(flag);
     }
 
     @Override
     public boolean isFullScopeAllowed() {
-        if (updatedClient != null) return updatedClient.isFullScopeAllowed();
-        return cachedClient.isFullScopeAllowed();
+        if (updated != null) return updated.isFullScopeAllowed();
+        return cached.isFullScopeAllowed();
     }
 
     @Override
     public void setFullScopeAllowed(boolean value) {
         getDelegateForUpdate();
-        updatedClient.setFullScopeAllowed(value);
+        updated.setFullScopeAllowed(value);
 
     }
 
     public boolean isDirectGrantsOnly() {
-        if (updatedClient != null) return updatedClient.isDirectGrantsOnly();
-        return cachedClient.isDirectGrantsOnly();
+        if (updated != null) return updated.isDirectGrantsOnly();
+        return cached.isDirectGrantsOnly();
     }
 
     public void setDirectGrantsOnly(boolean flag) {
         getDelegateForUpdate();
-        updatedClient.setDirectGrantsOnly(flag);
+        updated.setDirectGrantsOnly(flag);
     }
 
     public Set<RoleModel> getScopeMappings() {
-        if (updatedClient != null) return updatedClient.getScopeMappings();
+        if (updated != null) return updated.getScopeMappings();
         Set<RoleModel> roles = new HashSet<RoleModel>();
-        for (String id : cachedClient.getScope()) {
+        for (String id : cached.getScope()) {
             roles.add(cacheSession.getRoleById(id, getRealm()));
 
         }
@@ -163,12 +171,12 @@ public abstract class ClientAdapter implements ClientModel {
 
     public void addScopeMapping(RoleModel role) {
         getDelegateForUpdate();
-        updatedClient.addScopeMapping(role);
+        updated.addScopeMapping(role);
     }
 
     public void deleteScopeMapping(RoleModel role) {
         getDelegateForUpdate();
-        updatedClient.deleteScopeMapping(role);
+        updated.deleteScopeMapping(role);
     }
 
     public Set<RoleModel> getRealmScopeMappings() {
@@ -187,119 +195,107 @@ public abstract class ClientAdapter implements ClientModel {
         return appRoles;
     }
 
-    public boolean hasScope(RoleModel role) {
-        if (updatedClient != null) return updatedClient.hasScope(role);
-        if (cachedClient.isFullScopeAllowed() || cachedClient.getScope().contains(role.getId())) return true;
-
-        Set<RoleModel> roles = getScopeMappings();
-
-        for (RoleModel mapping : roles) {
-            if (mapping.hasRole(role)) return true;
-        }
-        return false;
-    }
-
     public RealmModel getRealm() {
         return cachedRealm;
     }
 
     public int getNotBefore() {
-        if (updatedClient != null) return updatedClient.getNotBefore();
-        return cachedClient.getNotBefore();
+        if (updated != null) return updated.getNotBefore();
+        return cached.getNotBefore();
     }
 
     public void setNotBefore(int notBefore) {
         getDelegateForUpdate();
-        updatedClient.setNotBefore(notBefore);
+        updated.setNotBefore(notBefore);
     }
 
     @Override
     public String getProtocol() {
-        if (updatedClient != null) return updatedClient.getProtocol();
-        return cachedClient.getProtocol();
+        if (updated != null) return updated.getProtocol();
+        return cached.getProtocol();
     }
 
     @Override
     public void setProtocol(String protocol) {
         getDelegateForUpdate();
-        updatedClient.setProtocol(protocol);
+        updated.setProtocol(protocol);
     }
 
     @Override
     public void setAttribute(String name, String value) {
         getDelegateForUpdate();
-        updatedClient.setAttribute(name, value);
+        updated.setAttribute(name, value);
 
     }
 
     @Override
     public void removeAttribute(String name) {
         getDelegateForUpdate();
-        updatedClient.removeAttribute(name);
+        updated.removeAttribute(name);
 
     }
 
     @Override
     public String getAttribute(String name) {
-        if (updatedClient != null) return updatedClient.getAttribute(name);
-        return cachedClient.getAttributes().get(name);
+        if (updated != null) return updated.getAttribute(name);
+        return cached.getAttributes().get(name);
     }
 
     @Override
     public Map<String, String> getAttributes() {
-        if (updatedClient != null) return updatedClient.getAttributes();
+        if (updated != null) return updated.getAttributes();
         Map<String, String> copy = new HashMap<String, String>();
-        copy.putAll(cachedClient.getAttributes());
+        copy.putAll(cached.getAttributes());
         return copy;
     }
 
     @Override
     public void updateIdentityProviders(List<ClientIdentityProviderMappingModel> identityProviders) {
         getDelegateForUpdate();
-        updatedClient.updateIdentityProviders(identityProviders);
+        updated.updateIdentityProviders(identityProviders);
     }
 
     @Override
     public List<ClientIdentityProviderMappingModel> getIdentityProviders() {
-        if (updatedClient != null) return updatedClient.getIdentityProviders();
-        return cachedClient.getIdentityProviders();
+        if (updated != null) return updated.getIdentityProviders();
+        return cached.getIdentityProviders();
     }
 
     @Override
     public boolean isAllowedRetrieveTokenFromIdentityProvider(String providerId) {
-        if (updatedClient != null) return updatedClient.isAllowedRetrieveTokenFromIdentityProvider(providerId);
-        return cachedClient.isAllowedRetrieveTokenFromIdentityProvider(providerId);
+        if (updated != null) return updated.isAllowedRetrieveTokenFromIdentityProvider(providerId);
+        return cached.isAllowedRetrieveTokenFromIdentityProvider(providerId);
     }
 
     @Override
     public Set<ProtocolMapperModel> getProtocolMappers() {
-        if (updatedClient != null) return updatedClient.getProtocolMappers();
-        return cachedClient.getProtocolMappers();
+        if (updated != null) return updated.getProtocolMappers();
+        return cached.getProtocolMappers();
     }
 
     @Override
     public ProtocolMapperModel addProtocolMapper(ProtocolMapperModel model) {
         getDelegateForUpdate();
-        return updatedClient.addProtocolMapper(model);
+        return updated.addProtocolMapper(model);
     }
 
     @Override
     public void removeProtocolMapper(ProtocolMapperModel mapping) {
         getDelegateForUpdate();
-        updatedClient.removeProtocolMapper(mapping);
+        updated.removeProtocolMapper(mapping);
 
     }
 
     @Override
     public void updateProtocolMapper(ProtocolMapperModel mapping) {
         getDelegateForUpdate();
-        updatedClient.updateProtocolMapper(mapping);
+        updated.updateProtocolMapper(mapping);
 
     }
 
     @Override
     public ProtocolMapperModel getProtocolMapperById(String id) {
-        for (ProtocolMapperModel mapping : cachedClient.getProtocolMappers()) {
+        for (ProtocolMapperModel mapping : cached.getProtocolMappers()) {
             if (mapping.getId().equals(id)) return mapping;
         }
         return null;
@@ -307,9 +303,228 @@ public abstract class ClientAdapter implements ClientModel {
 
     @Override
     public ProtocolMapperModel getProtocolMapperByName(String protocol, String name) {
-        for (ProtocolMapperModel mapping : cachedClient.getProtocolMappers()) {
+        for (ProtocolMapperModel mapping : cached.getProtocolMappers()) {
             if (mapping.getProtocol().equals(protocol) && mapping.getName().equals(name)) return mapping;
         }
         return null;
     }
+
+    @Override
+    public String getClientId() {
+        if (updated != null) return updated.getClientId();
+        return cached.getName();
+    }
+
+    @Override
+    public void setClientId(String clientId) {
+        getDelegateForUpdate();
+        updated.setClientId(clientId);
+        cacheSession.registerRealmInvalidation(cachedRealm.getId());
+    }
+
+    @Override
+    public boolean isSurrogateAuthRequired() {
+        if (updated != null) return updated.isSurrogateAuthRequired();
+        return cached.isSurrogateAuthRequired();
+    }
+
+    @Override
+    public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
+        getDelegateForUpdate();
+        updated.setSurrogateAuthRequired(surrogateAuthRequired);
+    }
+
+    @Override
+    public String getManagementUrl() {
+        if (updated != null) return updated.getManagementUrl();
+        return cached.getManagementUrl();
+    }
+
+    @Override
+    public void setManagementUrl(String url) {
+        getDelegateForUpdate();
+        updated.setManagementUrl(url);
+    }
+
+    @Override
+    public String getBaseUrl() {
+        if (updated != null) return updated.getBaseUrl();
+        return cached.getBaseUrl();
+    }
+
+    @Override
+    public void setBaseUrl(String url) {
+        getDelegateForUpdate();
+        updated.setBaseUrl(url);
+    }
+
+    @Override
+    public List<String> getDefaultRoles() {
+        if (updated != null) return updated.getDefaultRoles();
+        return cached.getDefaultRoles();
+    }
+
+    @Override
+    public void addDefaultRole(String name) {
+        getDelegateForUpdate();
+        updated.addDefaultRole(name);
+    }
+
+    @Override
+    public void updateDefaultRoles(String[] defaultRoles) {
+        getDelegateForUpdate();
+        updated.updateDefaultRoles(defaultRoles);
+    }
+
+    @Override
+    public Set<RoleModel> getClientScopeMappings(ClientModel client) {
+        Set<RoleModel> roleMappings = client.getScopeMappings();
+
+        Set<RoleModel> appRoles = new HashSet<RoleModel>();
+        for (RoleModel role : roleMappings) {
+            RoleContainerModel container = role.getContainer();
+            if (container instanceof RealmModel) {
+            } else {
+                ClientModel app = (ClientModel)container;
+                if (app.getId().equals(getId())) {
+                    appRoles.add(role);
+                }
+            }
+        }
+
+        return appRoles;
+    }
+
+    @Override
+    public boolean isBearerOnly() {
+        if (updated != null) return updated.isBearerOnly();
+        return cached.isBearerOnly();
+    }
+
+    @Override
+    public void setBearerOnly(boolean only) {
+        getDelegateForUpdate();
+        updated.setBearerOnly(only);
+    }
+
+    @Override
+    public boolean isConsentRequired() {
+        if (updated != null) return updated.isConsentRequired();
+        return cached.isConsentRequired();
+    }
+
+    @Override
+    public void setConsentRequired(boolean consentRequired) {
+        getDelegateForUpdate();
+        updated.setConsentRequired(consentRequired);
+    }
+
+    @Override
+    public RoleModel getRole(String name) {
+        if (updated != null) return updated.getRole(name);
+        String id = cached.getRoles().get(name);
+        if (id == null) return null;
+        return cacheSession.getRoleById(id, cachedRealm);
+    }
+
+    @Override
+    public RoleModel addRole(String name) {
+        getDelegateForUpdate();
+        RoleModel role = updated.addRole(name);
+        cacheSession.registerRoleInvalidation(role.getId());
+        return role;
+    }
+
+    @Override
+    public RoleModel addRole(String id, String name) {
+        getDelegateForUpdate();
+        RoleModel role =  updated.addRole(id, name);
+        cacheSession.registerRoleInvalidation(role.getId());
+        return role;
+    }
+
+    @Override
+    public boolean removeRole(RoleModel role) {
+        cacheSession.registerRoleInvalidation(role.getId());
+        getDelegateForUpdate();
+        return updated.removeRole(role);
+    }
+
+    @Override
+    public Set<RoleModel> getRoles() {
+        if (updated != null) return updated.getRoles();
+
+        Set<RoleModel> roles = new HashSet<RoleModel>();
+        for (String id : cached.getRoles().values()) {
+            RoleModel roleById = cacheSession.getRoleById(id, cachedRealm);
+            if (roleById == null) continue;
+            roles.add(roleById);
+        }
+        return roles;
+    }
+
+    @Override
+    public int getNodeReRegistrationTimeout() {
+        if (updated != null) return updated.getNodeReRegistrationTimeout();
+        return cached.getNodeReRegistrationTimeout();
+    }
+
+    @Override
+    public void setNodeReRegistrationTimeout(int timeout) {
+        getDelegateForUpdate();
+        updated.setNodeReRegistrationTimeout(timeout);
+    }
+
+    @Override
+    public Map<String, Integer> getRegisteredNodes() {
+        if (updated != null) return updated.getRegisteredNodes();
+        return cached.getRegisteredNodes();
+    }
+
+    @Override
+    public void registerNode(String nodeHost, int registrationTime) {
+        getDelegateForUpdate();
+        updated.registerNode(nodeHost, registrationTime);
+    }
+
+    @Override
+    public void unregisterNode(String nodeHost) {
+        getDelegateForUpdate();
+        updated.unregisterNode(nodeHost);
+    }
+
+    @Override
+    public boolean hasScope(RoleModel role) {
+        if (updated != null) return updated.hasScope(role);
+        if (cached.isFullScopeAllowed() || cached.getScope().contains(role.getId())) return true;
+
+        Set<RoleModel> roles = getScopeMappings();
+
+        for (RoleModel mapping : roles) {
+            if (mapping.hasRole(role)) return true;
+        }
+
+        roles = getRoles();
+        if (roles.contains(role)) return true;
+
+        for (RoleModel mapping : roles) {
+            if (mapping.hasRole(role)) return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof ClientModel)) return false;
+
+        ClientModel that = (ClientModel) o;
+        return that.getId().equals(getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
+
 }
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheRealmProvider.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheRealmProvider.java
index a1d232e..933ac74 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheRealmProvider.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheRealmProvider.java
@@ -1,15 +1,13 @@
 package org.keycloak.models.cache;
 
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakTransaction;
-import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RealmProvider;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.cache.entities.CachedApplication;
 import org.keycloak.models.cache.entities.CachedApplicationRole;
-import org.keycloak.models.cache.entities.CachedOAuthClient;
 import org.keycloak.models.cache.entities.CachedRealm;
 import org.keycloak.models.cache.entities.CachedRealmRole;
 import org.keycloak.models.cache.entities.CachedRole;
@@ -34,11 +32,8 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider {
     protected Set<String> realmInvalidations = new HashSet<String>();
     protected Set<String> appInvalidations = new HashSet<String>();
     protected Set<String> roleInvalidations = new HashSet<String>();
-    protected Set<String> clientInvalidations = new HashSet<String>();
-    protected Set<String> userInvalidations = new HashSet<String>();
     protected Map<String, RealmModel> managedRealms = new HashMap<String, RealmModel>();
-    protected Map<String, ApplicationModel> managedApplications = new HashMap<String, ApplicationModel>();
-    protected Map<String, OAuthClientModel> managedClients = new HashMap<String, OAuthClientModel>();
+    protected Map<String, ClientModel> managedApplications = new HashMap<String, ClientModel>();
     protected Map<String, RoleModel> managedRoles = new HashMap<String, RoleModel>();
 
     protected boolean clearAll;
@@ -83,16 +78,6 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider {
         roleInvalidations.add(id);
     }
 
-    @Override
-    public void registerOAuthClientInvalidation(String id) {
-        clientInvalidations.add(id);
-    }
-
-    @Override
-    public void registerUserInvalidation(String id) {
-        userInvalidations.add(id);
-    }
-
     protected void runInvalidations() {
         for (String id : realmInvalidations) {
             cache.invalidateCachedRealmById(id);
@@ -103,9 +88,6 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider {
         for (String id : appInvalidations) {
             cache.invalidateCachedApplicationById(id);
         }
-        for (String id : clientInvalidations) {
-            cache.invalidateCachedOAuthClientById(id);
-        }
     }
 
     private KeycloakTransaction getTransaction() {
@@ -252,8 +234,8 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider {
             RoleModel model = getDelegate().getRoleById(id, realm);
             if (model == null) return null;
             if (roleInvalidations.contains(id)) return model;
-            if (model.getContainer() instanceof ApplicationModel) {
-                cached = new CachedApplicationRole(((ApplicationModel) model.getContainer()).getId(), model, realm);
+            if (model.getContainer() instanceof ClientModel) {
+                cached = new CachedApplicationRole(((ClientModel) model.getContainer()).getId(), model, realm);
             } else {
                 cached = new CachedRealmRole(model, realm);
             }
@@ -270,51 +252,27 @@ public class DefaultCacheRealmProvider implements CacheRealmProvider {
     }
 
     @Override
-    public ApplicationModel getApplicationById(String id, RealmModel realm) {
-        if (!cache.isEnabled()) return getDelegate().getApplicationById(id, realm);
+    public ClientModel getClientById(String id, RealmModel realm) {
+        if (!cache.isEnabled()) return getDelegate().getClientById(id, realm);
         CachedApplication cached = cache.getApplication(id);
         if (cached != null && !cached.getRealm().equals(realm.getId())) {
             cached = null;
         }
 
         if (cached == null) {
-            ApplicationModel model = getDelegate().getApplicationById(id, realm);
+            ClientModel model = getDelegate().getClientById(id, realm);
             if (model == null) return null;
             if (appInvalidations.contains(id)) return model;
             cached = new CachedApplication(cache, getDelegate(), realm, model);
             cache.addCachedApplication(cached);
         } else if (appInvalidations.contains(id)) {
-            return getDelegate().getApplicationById(id, realm);
+            return getDelegate().getClientById(id, realm);
         } else if (managedApplications.containsKey(id)) {
             return managedApplications.get(id);
         }
-        ApplicationAdapter adapter = new ApplicationAdapter(realm, cached, this, cache);
+        ClientAdapter adapter = new ClientAdapter(realm, cached, this, cache);
         managedApplications.put(id, adapter);
         return adapter;
     }
 
-    @Override
-    public OAuthClientModel getOAuthClientById(String id, RealmModel realm) {
-        if (!cache.isEnabled()) return getDelegate().getOAuthClientById(id, realm);
-        CachedOAuthClient cached = cache.getOAuthClient(id);
-        if (cached != null && !cached.getRealm().equals(realm.getId())) {
-            cached = null;
-        }
-
-        if (cached == null) {
-            OAuthClientModel model = getDelegate().getOAuthClientById(id, realm);
-            if (model == null) return null;
-            if (clientInvalidations.contains(id)) return model;
-            cached = new CachedOAuthClient(cache, getDelegate(), realm, model);
-            cache.addCachedOAuthClient(cached);
-        } else if (clientInvalidations.contains(id)) {
-            return getDelegate().getOAuthClientById(id, realm);
-        } else if (managedClients.containsKey(id)) {
-            return managedClients.get(id);
-        }
-        OAuthClientAdapter adapter = new OAuthClientAdapter(realm, cached, this, cache);
-        managedClients.put(id, adapter);
-        return adapter;
-    }
-
 }
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedApplication.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedApplication.java
index e537ea7..896dfc9 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedApplication.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedApplication.java
@@ -1,38 +1,82 @@
 package org.keycloak.models.cache.entities;
 
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientIdentityProviderMappingModel;
+import org.keycloak.models.ProtocolMapperModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RealmProvider;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.cache.RealmCache;
 
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.TreeMap;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public class CachedApplication extends CachedClient {
+public class CachedApplication {
+    private String id;
+    private String name;
+    private String realm;
+    private Set<String> redirectUris = new HashSet<String>();
+    private boolean enabled;
+    private String secret;
+    private String protocol;
+    private Map<String, String> attributes = new HashMap<String, String>();
+    private boolean publicClient;
+    private boolean fullScopeAllowed;
+    private boolean directGrantsOnly;
+    private boolean frontchannelLogout;
+    private int notBefore;
+    private Set<String> scope = new HashSet<String>();
+    private Set<String> webOrigins = new HashSet<String>();
+    private List<ClientIdentityProviderMappingModel> identityProviders = new ArrayList<ClientIdentityProviderMappingModel>();
+    private Set<ProtocolMapperModel> protocolMappers = new HashSet<ProtocolMapperModel>();
     private boolean surrogateAuthRequired;
     private String managementUrl;
     private String baseUrl;
     private List<String> defaultRoles = new LinkedList<String>();
     private boolean bearerOnly;
+    private boolean consentRequired;
     private Map<String, String> roles = new HashMap<String, String>();
     private int nodeReRegistrationTimeout;
     private Map<String, Integer> registeredNodes;
 
-    public CachedApplication(RealmCache cache, RealmProvider delegate, RealmModel realm, ApplicationModel model) {
-        super(cache, delegate, realm, model);
+    public CachedApplication(RealmCache cache, RealmProvider delegate, RealmModel realm, ClientModel model) {
+        id = model.getId();
+        secret = model.getSecret();
+        name = model.getClientId();
+        this.realm = realm.getId();
+        enabled = model.isEnabled();
+        protocol = model.getProtocol();
+        attributes.putAll(model.getAttributes());
+        notBefore = model.getNotBefore();
+        directGrantsOnly = model.isDirectGrantsOnly();
+        frontchannelLogout = model.isFrontchannelLogout();
+        publicClient = model.isPublicClient();
+        fullScopeAllowed = model.isFullScopeAllowed();
+        redirectUris.addAll(model.getRedirectUris());
+        webOrigins.addAll(model.getWebOrigins());
+        for (RoleModel role : model.getScopeMappings())  {
+            scope.add(role.getId());
+        }
+        this.identityProviders = model.getIdentityProviders();
+        for (ProtocolMapperModel mapper : model.getProtocolMappers()) {
+            this.protocolMappers.add(mapper);
+        }
         surrogateAuthRequired = model.isSurrogateAuthRequired();
         managementUrl = model.getManagementUrl();
         baseUrl = model.getBaseUrl();
         defaultRoles.addAll(model.getDefaultRoles());
         bearerOnly = model.isBearerOnly();
+        consentRequired = model.isConsentRequired();
         for (RoleModel role : model.getRoles()) {
             roles.put(role.getName(), role.getId());
             cache.addCachedRole(new CachedApplicationRole(id, role, realm));
@@ -41,6 +85,93 @@ public class CachedApplication extends CachedClient {
         nodeReRegistrationTimeout = model.getNodeReRegistrationTimeout();
         registeredNodes = new TreeMap<String, Integer>(model.getRegisteredNodes());
     }
+    public String getId() {
+        return id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getRealm() {
+        return realm;
+    }
+
+    public Set<String> getRedirectUris() {
+        return redirectUris;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public String getSecret() {
+        return secret;
+    }
+
+    public boolean isPublicClient() {
+        return publicClient;
+    }
+
+    public boolean isDirectGrantsOnly() {
+        return directGrantsOnly;
+    }
+
+    public int getNotBefore() {
+        return notBefore;
+    }
+
+    public Set<String> getScope() {
+        return scope;
+    }
+
+    public Set<String> getWebOrigins() {
+        return webOrigins;
+    }
+
+    public boolean isFullScopeAllowed() {
+        return fullScopeAllowed;
+    }
+
+    public String getProtocol() {
+        return protocol;
+    }
+
+    public Map<String, String> getAttributes() {
+        return attributes;
+    }
+
+    public boolean isFrontchannelLogout() {
+        return frontchannelLogout;
+    }
+
+    public List<ClientIdentityProviderMappingModel> getIdentityProviders() {
+        return this.identityProviders;
+    }
+
+    public boolean hasIdentityProvider(String providerId) {
+        for (ClientIdentityProviderMappingModel model : getIdentityProviders()) {
+            if (model.getIdentityProvider().equals(providerId)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    public Set<ProtocolMapperModel> getProtocolMappers() {
+        return protocolMappers;
+    }
+
+    public boolean isAllowedRetrieveTokenFromIdentityProvider(String providerId) {
+        for (ClientIdentityProviderMappingModel model : getIdentityProviders()) {
+            if (model.getIdentityProvider().equals(providerId)) {
+                return model.isRetrieveToken();
+            }
+        }
+
+        return false;
+    }
 
     public boolean isSurrogateAuthRequired() {
         return surrogateAuthRequired;
@@ -62,6 +193,10 @@ public class CachedApplication extends CachedClient {
         return bearerOnly;
     }
 
+    public boolean isConsentRequired() {
+        return consentRequired;
+    }
+
     public Map<String, String> getRoles() {
         return roles;
     }
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java
index a88cf47..d302c48 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java
@@ -1,392 +1,385 @@
-package org.keycloak.models.cache.entities;
-
-import org.keycloak.enums.SslRequired;
-import org.keycloak.models.ApplicationModel;
-import org.keycloak.models.IdentityProviderMapperModel;
-import org.keycloak.models.IdentityProviderModel;
-import org.keycloak.models.OAuthClientModel;
-import org.keycloak.models.PasswordPolicy;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RealmProvider;
-import org.keycloak.models.RequiredCredentialModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserFederationProviderModel;
-import org.keycloak.models.cache.RealmCache;
-import org.keycloak.util.MultivaluedHashMap;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class CachedRealm {
-
-    private String id;
-    private String name;
-    private boolean enabled;
-    private SslRequired sslRequired;
-    private boolean registrationAllowed;
-    private boolean registrationEmailAsUsername;
-    private boolean rememberMe;
-    private boolean verifyEmail;
-    private boolean passwordCredentialGrantAllowed;
-    private boolean resetPasswordAllowed;
-    private boolean identityFederationEnabled;
-    //--- brute force settings
-    private boolean bruteForceProtected;
-    private int maxFailureWaitSeconds;
-    private int minimumQuickLoginWaitSeconds;
-    private int waitIncrementSeconds;
-    private long quickLoginCheckMilliSeconds;
-    private int maxDeltaTimeSeconds;
-    private int failureFactor;
-    //--- end brute force settings
-
-    private int ssoSessionIdleTimeout;
-    private int ssoSessionMaxLifespan;
-    private int accessTokenLifespan;
-    private int accessCodeLifespan;
-    private int accessCodeLifespanUserAction;
-    private int accessCodeLifespanLogin;
-    private int notBefore;
-    private PasswordPolicy passwordPolicy;
-
-    private String publicKeyPem;
-    private String privateKeyPem;
-    private String certificatePem;
-    private String codeSecret;
-
-    private String loginTheme;
-    private String accountTheme;
-    private String adminTheme;
-    private String emailTheme;
-    private String masterAdminApp;
-
-    private List<RequiredCredentialModel> requiredCredentials = new ArrayList<RequiredCredentialModel>();
-    private List<UserFederationProviderModel> userFederationProviders = new ArrayList<UserFederationProviderModel>();
-    private List<IdentityProviderModel> identityProviders = new ArrayList<IdentityProviderModel>();
-
-    private Map<String, String> browserSecurityHeaders = new HashMap<String, String>();
-    private Map<String, String> smtpConfig = new HashMap<String, String>();
-
-    private boolean eventsEnabled;
-    private long eventsExpiration;
-    private Set<String> eventsListeners = new HashSet<String>();
-    private Set<String> enabledEventTypes = new HashSet<String>();
-    private List<String> defaultRoles = new LinkedList<String>();
-    private Map<String, String> realmRoles = new HashMap<String, String>();
-    private Map<String, String> applications = new HashMap<String, String>();
-    private Map<String, String> clients = new HashMap<String, String>();
-    private boolean internationalizationEnabled;
-    private Set<String> supportedLocales = new HashSet<String>();
-    private String defaultLocale;
-    private MultivaluedHashMap<String, IdentityProviderMapperModel> identityProviderMappers = new MultivaluedHashMap<>();
-
-    public CachedRealm() {
-    }
-
-    public CachedRealm(RealmCache cache, RealmProvider delegate, RealmModel model) {
-        id = model.getId();
-        name = model.getName();
-        enabled = model.isEnabled();
-        sslRequired = model.getSslRequired();
-        registrationAllowed = model.isRegistrationAllowed();
-        registrationEmailAsUsername = model.isRegistrationEmailAsUsername();
-        rememberMe = model.isRememberMe();
-        verifyEmail = model.isVerifyEmail();
-        passwordCredentialGrantAllowed = model.isPasswordCredentialGrantAllowed();
-        resetPasswordAllowed = model.isResetPasswordAllowed();
-        identityFederationEnabled = model.isIdentityFederationEnabled();
-        //--- brute force settings
-        bruteForceProtected = model.isBruteForceProtected();
-        maxFailureWaitSeconds = model.getMaxFailureWaitSeconds();
-        minimumQuickLoginWaitSeconds = model.getMinimumQuickLoginWaitSeconds();
-        waitIncrementSeconds = model.getWaitIncrementSeconds();
-        quickLoginCheckMilliSeconds = model.getQuickLoginCheckMilliSeconds();
-        maxDeltaTimeSeconds = model.getMaxDeltaTimeSeconds();
-        failureFactor = model.getFailureFactor();
-        //--- end brute force settings
-
-        ssoSessionIdleTimeout = model.getSsoSessionIdleTimeout();
-        ssoSessionMaxLifespan = model.getSsoSessionMaxLifespan();
-        accessTokenLifespan = model.getAccessTokenLifespan();
-        accessCodeLifespan = model.getAccessCodeLifespan();
-        accessCodeLifespanUserAction = model.getAccessCodeLifespanUserAction();
-        accessCodeLifespanLogin = model.getAccessCodeLifespanLogin();
-        notBefore = model.getNotBefore();
-        passwordPolicy = model.getPasswordPolicy();
-
-        publicKeyPem = model.getPublicKeyPem();
-        privateKeyPem = model.getPrivateKeyPem();
-        certificatePem = model.getCertificatePem();
-        codeSecret = model.getCodeSecret();
-
-        loginTheme = model.getLoginTheme();
-        accountTheme = model.getAccountTheme();
-        adminTheme = model.getAdminTheme();
-        emailTheme = model.getEmailTheme();
-
-        requiredCredentials = model.getRequiredCredentials();
-        userFederationProviders = model.getUserFederationProviders();
-
-        this.identityProviders = new ArrayList<>();
-
-        for (IdentityProviderModel identityProviderModel : model.getIdentityProviders()) {
-            this.identityProviders.add(new IdentityProviderModel(identityProviderModel));
-        }
-
-        for (IdentityProviderMapperModel mapper : model.getIdentityProviderMappers()) {
-            identityProviderMappers.add(mapper.getIdentityProviderAlias(), mapper);
-        }
-
-
-
-        smtpConfig.putAll(model.getSmtpConfig());
-        browserSecurityHeaders.putAll(model.getBrowserSecurityHeaders());
-
-        eventsEnabled = model.isEventsEnabled();
-        eventsExpiration = model.getEventsExpiration();
-        eventsListeners.addAll(model.getEventsListeners());
-        enabledEventTypes.addAll(model.getEnabledEventTypes());
-        defaultRoles.addAll(model.getDefaultRoles());
-        masterAdminApp = model.getMasterAdminApp().getId();
-
-        for (RoleModel role : model.getRoles()) {
-            realmRoles.put(role.getName(), role.getId());
-            CachedRole cachedRole = new CachedRealmRole(role, model);
-            cache.addCachedRole(cachedRole);
-        }
-
-        for (ApplicationModel app : model.getApplications()) {
-            applications.put(app.getName(), app.getId());
-            CachedApplication cachedApp = new CachedApplication(cache, delegate, model, app);
-            cache.addCachedApplication(cachedApp);
-        }
-
-        for (OAuthClientModel client : model.getOAuthClients()) {
-            clients.put(client.getClientId(), client.getId());
-            CachedOAuthClient cachedApp = new CachedOAuthClient(cache, delegate, model, client);
-            cache.addCachedOAuthClient(cachedApp);
-        }
-
-        internationalizationEnabled = model.isInternationalizationEnabled();
-        supportedLocales.addAll(model.getSupportedLocales());
-        defaultLocale = model.getDefaultLocale();
-
-    }
-
-
-    public String getId() {
-        return id;
-    }
-
-    public String getMasterAdminApp() {
-        return masterAdminApp;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public List<String> getDefaultRoles() {
-        return defaultRoles;
-    }
-
-    public Map<String, String> getRealmRoles() {
-        return realmRoles;
-    }
-
-    public Map<String, String> getApplications() {
-        return applications;
-    }
-
-    public Map<String, String> getClients() {
-        return clients;
-    }
-
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-    public SslRequired getSslRequired() {
-        return sslRequired;
-    }
-
-    public boolean isRegistrationAllowed() {
-        return registrationAllowed;
-    }
-
-    public boolean isRegistrationEmailAsUsername() {
-        return registrationEmailAsUsername;
-    }
-
-    public boolean isPasswordCredentialGrantAllowed() {
-        return passwordCredentialGrantAllowed;
-    }
-
-    public boolean isRememberMe() {
-        return this.rememberMe;
-    }
-
-    public boolean isBruteForceProtected() {
-        return bruteForceProtected;
-    }
-
-    public int getMaxFailureWaitSeconds() {
-        return this.maxFailureWaitSeconds;
-    }
-
-    public int getWaitIncrementSeconds() {
-        return this.waitIncrementSeconds;
-    }
-
-    public int getMinimumQuickLoginWaitSeconds() {
-        return this.minimumQuickLoginWaitSeconds;
-    }
-
-    public long getQuickLoginCheckMilliSeconds() {
-        return quickLoginCheckMilliSeconds;
-    }
-
-    public int getMaxDeltaTimeSeconds() {
-        return maxDeltaTimeSeconds;
-    }
-
-    public int getFailureFactor() {
-        return failureFactor;
-    }
-
-    public boolean isVerifyEmail() {
-        return verifyEmail;
-    }
-
-    public boolean isResetPasswordAllowed() {
-        return resetPasswordAllowed;
-    }
-
-    public int getSsoSessionIdleTimeout() {
-        return ssoSessionIdleTimeout;
-    }
-
-    public int getSsoSessionMaxLifespan() {
-        return ssoSessionMaxLifespan;
-    }
-
-    public int getAccessTokenLifespan() {
-        return accessTokenLifespan;
-    }
-
-    public int getAccessCodeLifespan() {
-        return accessCodeLifespan;
-    }
-
-    public int getAccessCodeLifespanUserAction() {
-        return accessCodeLifespanUserAction;
-    }
-    public int getAccessCodeLifespanLogin() {
-        return accessCodeLifespanLogin;
-    }
-
-    public String getPublicKeyPem() {
-        return publicKeyPem;
-    }
-
-    public String getPrivateKeyPem() {
-        return privateKeyPem;
-    }
-
-    public String getCodeSecret() {
-        return codeSecret;
-    }
-
-    public List<RequiredCredentialModel> getRequiredCredentials() {
-        return requiredCredentials;
-    }
-
-    public PasswordPolicy getPasswordPolicy() {
-        return passwordPolicy;
-    }
-
-    public boolean isIdentityFederationEnabled() {
-        return identityFederationEnabled;
-    }
-
-    public Map<String, String> getSmtpConfig() {
-        return smtpConfig;
-    }
-
-    public Map<String, String> getBrowserSecurityHeaders() {
-        return browserSecurityHeaders;
-    }
-
-    public String getLoginTheme() {
-        return loginTheme;
-    }
-
-    public String getAccountTheme() {
-        return accountTheme;
-    }
-
-    public String getAdminTheme() {
-        return this.adminTheme;
-    }
-
-    public String getEmailTheme() {
-        return emailTheme;
-    }
-
-    public int getNotBefore() {
-        return notBefore;
-    }
-
-    public boolean isEventsEnabled() {
-        return eventsEnabled;
-    }
-
-    public long getEventsExpiration() {
-        return eventsExpiration;
-    }
-
-    public Set<String> getEventsListeners() {
-        return eventsListeners;
-    }
-    
-    public Set<String> getEnabledEventTypes() {
-        return enabledEventTypes;
-    }
-
-    public List<UserFederationProviderModel> getUserFederationProviders() {
-        return userFederationProviders;
-    }
-
-    public String getCertificatePem() {
-        return certificatePem;
-    }
-
-    public List<IdentityProviderModel> getIdentityProviders() {
-        return identityProviders;
-    }
-
-    public boolean isInternationalizationEnabled() {
-        return internationalizationEnabled;
-    }
-
-    public Set<String> getSupportedLocales() {
-        return supportedLocales;
-    }
-
-    public String getDefaultLocale() {
-        return defaultLocale;
-    }
-
-    public MultivaluedHashMap<String, IdentityProviderMapperModel> getIdentityProviderMappers() {
-        return identityProviderMappers;
-    }
-}
+package org.keycloak.models.cache.entities;
+
+import org.keycloak.enums.SslRequired;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.IdentityProviderMapperModel;
+import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.PasswordPolicy;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RealmProvider;
+import org.keycloak.models.RequiredCredentialModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.models.cache.RealmCache;
+import org.keycloak.util.MultivaluedHashMap;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class CachedRealm {
+
+    private String id;
+    private String name;
+    private boolean enabled;
+    private SslRequired sslRequired;
+    private boolean registrationAllowed;
+    private boolean registrationEmailAsUsername;
+    private boolean rememberMe;
+    private boolean verifyEmail;
+    private boolean passwordCredentialGrantAllowed;
+    private boolean resetPasswordAllowed;
+    private boolean identityFederationEnabled;
+    //--- brute force settings
+    private boolean bruteForceProtected;
+    private int maxFailureWaitSeconds;
+    private int minimumQuickLoginWaitSeconds;
+    private int waitIncrementSeconds;
+    private long quickLoginCheckMilliSeconds;
+    private int maxDeltaTimeSeconds;
+    private int failureFactor;
+    //--- end brute force settings
+
+    private int ssoSessionIdleTimeout;
+    private int ssoSessionMaxLifespan;
+    private int accessTokenLifespan;
+    private int accessCodeLifespan;
+    private int accessCodeLifespanUserAction;
+    private int accessCodeLifespanLogin;
+    private int notBefore;
+    private PasswordPolicy passwordPolicy;
+
+    private String publicKeyPem;
+    private String privateKeyPem;
+    private String certificatePem;
+    private String codeSecret;
+
+    private String loginTheme;
+    private String accountTheme;
+    private String adminTheme;
+    private String emailTheme;
+    private String masterAdminApp;
+
+    private List<RequiredCredentialModel> requiredCredentials = new ArrayList<RequiredCredentialModel>();
+    private List<UserFederationProviderModel> userFederationProviders = new ArrayList<UserFederationProviderModel>();
+    private List<IdentityProviderModel> identityProviders = new ArrayList<IdentityProviderModel>();
+
+    private Map<String, String> browserSecurityHeaders = new HashMap<String, String>();
+    private Map<String, String> smtpConfig = new HashMap<String, String>();
+
+    private boolean eventsEnabled;
+    private long eventsExpiration;
+    private Set<String> eventsListeners = new HashSet<String>();
+    private Set<String> enabledEventTypes = new HashSet<String>();
+    private List<String> defaultRoles = new LinkedList<String>();
+    private Map<String, String> realmRoles = new HashMap<String, String>();
+    private Map<String, String> applications = new HashMap<String, String>();
+    private Map<String, String> clients = new HashMap<String, String>();
+    private boolean internationalizationEnabled;
+    private Set<String> supportedLocales = new HashSet<String>();
+    private String defaultLocale;
+    private MultivaluedHashMap<String, IdentityProviderMapperModel> identityProviderMappers = new MultivaluedHashMap<>();
+
+    public CachedRealm() {
+    }
+
+    public CachedRealm(RealmCache cache, RealmProvider delegate, RealmModel model) {
+        id = model.getId();
+        name = model.getName();
+        enabled = model.isEnabled();
+        sslRequired = model.getSslRequired();
+        registrationAllowed = model.isRegistrationAllowed();
+        registrationEmailAsUsername = model.isRegistrationEmailAsUsername();
+        rememberMe = model.isRememberMe();
+        verifyEmail = model.isVerifyEmail();
+        passwordCredentialGrantAllowed = model.isPasswordCredentialGrantAllowed();
+        resetPasswordAllowed = model.isResetPasswordAllowed();
+        identityFederationEnabled = model.isIdentityFederationEnabled();
+        //--- brute force settings
+        bruteForceProtected = model.isBruteForceProtected();
+        maxFailureWaitSeconds = model.getMaxFailureWaitSeconds();
+        minimumQuickLoginWaitSeconds = model.getMinimumQuickLoginWaitSeconds();
+        waitIncrementSeconds = model.getWaitIncrementSeconds();
+        quickLoginCheckMilliSeconds = model.getQuickLoginCheckMilliSeconds();
+        maxDeltaTimeSeconds = model.getMaxDeltaTimeSeconds();
+        failureFactor = model.getFailureFactor();
+        //--- end brute force settings
+
+        ssoSessionIdleTimeout = model.getSsoSessionIdleTimeout();
+        ssoSessionMaxLifespan = model.getSsoSessionMaxLifespan();
+        accessTokenLifespan = model.getAccessTokenLifespan();
+        accessCodeLifespan = model.getAccessCodeLifespan();
+        accessCodeLifespanUserAction = model.getAccessCodeLifespanUserAction();
+        accessCodeLifespanLogin = model.getAccessCodeLifespanLogin();
+        notBefore = model.getNotBefore();
+        passwordPolicy = model.getPasswordPolicy();
+
+        publicKeyPem = model.getPublicKeyPem();
+        privateKeyPem = model.getPrivateKeyPem();
+        certificatePem = model.getCertificatePem();
+        codeSecret = model.getCodeSecret();
+
+        loginTheme = model.getLoginTheme();
+        accountTheme = model.getAccountTheme();
+        adminTheme = model.getAdminTheme();
+        emailTheme = model.getEmailTheme();
+
+        requiredCredentials = model.getRequiredCredentials();
+        userFederationProviders = model.getUserFederationProviders();
+
+        this.identityProviders = new ArrayList<>();
+
+        for (IdentityProviderModel identityProviderModel : model.getIdentityProviders()) {
+            this.identityProviders.add(new IdentityProviderModel(identityProviderModel));
+        }
+
+        for (IdentityProviderMapperModel mapper : model.getIdentityProviderMappers()) {
+            identityProviderMappers.add(mapper.getIdentityProviderAlias(), mapper);
+        }
+
+
+
+        smtpConfig.putAll(model.getSmtpConfig());
+        browserSecurityHeaders.putAll(model.getBrowserSecurityHeaders());
+
+        eventsEnabled = model.isEventsEnabled();
+        eventsExpiration = model.getEventsExpiration();
+        eventsListeners.addAll(model.getEventsListeners());
+        enabledEventTypes.addAll(model.getEnabledEventTypes());
+        defaultRoles.addAll(model.getDefaultRoles());
+        masterAdminApp = model.getMasterAdminClient().getId();
+
+        for (RoleModel role : model.getRoles()) {
+            realmRoles.put(role.getName(), role.getId());
+            CachedRole cachedRole = new CachedRealmRole(role, model);
+            cache.addCachedRole(cachedRole);
+        }
+
+        for (ClientModel app : model.getClients()) {
+            applications.put(app.getClientId(), app.getId());
+            CachedApplication cachedApp = new CachedApplication(cache, delegate, model, app);
+            cache.addCachedApplication(cachedApp);
+        }
+
+        internationalizationEnabled = model.isInternationalizationEnabled();
+        supportedLocales.addAll(model.getSupportedLocales());
+        defaultLocale = model.getDefaultLocale();
+
+    }
+
+
+    public String getId() {
+        return id;
+    }
+
+    public String getMasterAdminApp() {
+        return masterAdminApp;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public List<String> getDefaultRoles() {
+        return defaultRoles;
+    }
+
+    public Map<String, String> getRealmRoles() {
+        return realmRoles;
+    }
+
+    public Map<String, String> getApplications() {
+        return applications;
+    }
+
+    public Map<String, String> getClients() {
+        return clients;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public SslRequired getSslRequired() {
+        return sslRequired;
+    }
+
+    public boolean isRegistrationAllowed() {
+        return registrationAllowed;
+    }
+
+    public boolean isRegistrationEmailAsUsername() {
+        return registrationEmailAsUsername;
+    }
+
+    public boolean isPasswordCredentialGrantAllowed() {
+        return passwordCredentialGrantAllowed;
+    }
+
+    public boolean isRememberMe() {
+        return this.rememberMe;
+    }
+
+    public boolean isBruteForceProtected() {
+        return bruteForceProtected;
+    }
+
+    public int getMaxFailureWaitSeconds() {
+        return this.maxFailureWaitSeconds;
+    }
+
+    public int getWaitIncrementSeconds() {
+        return this.waitIncrementSeconds;
+    }
+
+    public int getMinimumQuickLoginWaitSeconds() {
+        return this.minimumQuickLoginWaitSeconds;
+    }
+
+    public long getQuickLoginCheckMilliSeconds() {
+        return quickLoginCheckMilliSeconds;
+    }
+
+    public int getMaxDeltaTimeSeconds() {
+        return maxDeltaTimeSeconds;
+    }
+
+    public int getFailureFactor() {
+        return failureFactor;
+    }
+
+    public boolean isVerifyEmail() {
+        return verifyEmail;
+    }
+
+    public boolean isResetPasswordAllowed() {
+        return resetPasswordAllowed;
+    }
+
+    public int getSsoSessionIdleTimeout() {
+        return ssoSessionIdleTimeout;
+    }
+
+    public int getSsoSessionMaxLifespan() {
+        return ssoSessionMaxLifespan;
+    }
+
+    public int getAccessTokenLifespan() {
+        return accessTokenLifespan;
+    }
+
+    public int getAccessCodeLifespan() {
+        return accessCodeLifespan;
+    }
+
+    public int getAccessCodeLifespanUserAction() {
+        return accessCodeLifespanUserAction;
+    }
+    public int getAccessCodeLifespanLogin() {
+        return accessCodeLifespanLogin;
+    }
+
+    public String getPublicKeyPem() {
+        return publicKeyPem;
+    }
+
+    public String getPrivateKeyPem() {
+        return privateKeyPem;
+    }
+
+    public String getCodeSecret() {
+        return codeSecret;
+    }
+
+    public List<RequiredCredentialModel> getRequiredCredentials() {
+        return requiredCredentials;
+    }
+
+    public PasswordPolicy getPasswordPolicy() {
+        return passwordPolicy;
+    }
+
+    public boolean isIdentityFederationEnabled() {
+        return identityFederationEnabled;
+    }
+
+    public Map<String, String> getSmtpConfig() {
+        return smtpConfig;
+    }
+
+    public Map<String, String> getBrowserSecurityHeaders() {
+        return browserSecurityHeaders;
+    }
+
+    public String getLoginTheme() {
+        return loginTheme;
+    }
+
+    public String getAccountTheme() {
+        return accountTheme;
+    }
+
+    public String getAdminTheme() {
+        return this.adminTheme;
+    }
+
+    public String getEmailTheme() {
+        return emailTheme;
+    }
+
+    public int getNotBefore() {
+        return notBefore;
+    }
+
+    public boolean isEventsEnabled() {
+        return eventsEnabled;
+    }
+
+    public long getEventsExpiration() {
+        return eventsExpiration;
+    }
+
+    public Set<String> getEventsListeners() {
+        return eventsListeners;
+    }
+    
+    public Set<String> getEnabledEventTypes() {
+        return enabledEventTypes;
+    }
+
+    public List<UserFederationProviderModel> getUserFederationProviders() {
+        return userFederationProviders;
+    }
+
+    public String getCertificatePem() {
+        return certificatePem;
+    }
+
+    public List<IdentityProviderModel> getIdentityProviders() {
+        return identityProviders;
+    }
+
+    public boolean isInternationalizationEnabled() {
+        return internationalizationEnabled;
+    }
+
+    public Set<String> getSupportedLocales() {
+        return supportedLocales;
+    }
+
+    public String getDefaultLocale() {
+        return defaultLocale;
+    }
+
+    public MultivaluedHashMap<String, IdentityProviderMapperModel> getIdentityProviderMappers() {
+        return identityProviderMappers;
+    }
+}
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/MemoryRealmCache.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/MemoryRealmCache.java
index 2373f9f..25064c6 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/MemoryRealmCache.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/MemoryRealmCache.java
@@ -1,7 +1,6 @@
 package org.keycloak.models.cache;
 
 import org.keycloak.models.cache.entities.CachedApplication;
-import org.keycloak.models.cache.entities.CachedOAuthClient;
 import org.keycloak.models.cache.entities.CachedRealm;
 import org.keycloak.models.cache.entities.CachedRole;
 
@@ -16,7 +15,6 @@ public class MemoryRealmCache implements RealmCache {
     protected ConcurrentHashMap<String, CachedRealm> realmCache = new ConcurrentHashMap<String, CachedRealm>();
     protected ConcurrentHashMap<String, CachedRealm> realmCacheByName = new ConcurrentHashMap<String, CachedRealm>();
     protected ConcurrentHashMap<String, CachedApplication> applicationCache = new ConcurrentHashMap<String, CachedApplication>();
-    protected ConcurrentHashMap<String, CachedOAuthClient> clientCache = new ConcurrentHashMap<String, CachedOAuthClient>();
     protected ConcurrentHashMap<String, CachedRole> roleCache = new ConcurrentHashMap<String, CachedRole>();
     protected volatile boolean enabled = true;
 
@@ -25,7 +23,6 @@ public class MemoryRealmCache implements RealmCache {
         realmCache.clear();
         realmCacheByName.clear();
         applicationCache.clear();
-        clientCache.clear();
         roleCache.clear();
     }
 
@@ -97,28 +94,6 @@ public class MemoryRealmCache implements RealmCache {
     }
 
     @Override
-    public CachedOAuthClient getOAuthClient(String id) {
-        if (!enabled) return null;
-        return clientCache.get(id);
-    }
-
-    @Override
-    public void invalidateOAuthClient(CachedOAuthClient client) {
-        clientCache.remove(client.getId());
-    }
-
-    @Override
-    public void addCachedOAuthClient(CachedOAuthClient client) {
-        if (!enabled) return;
-        clientCache.put(client.getId(), client);
-    }
-
-    @Override
-    public void invalidateCachedOAuthClientById(String id) {
-        clientCache.remove(id);
-    }
-
-    @Override
     public CachedRole getRole(String id) {
         if (!enabled) return null;
         return roleCache.get(id);
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheRealmProvider.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheRealmProvider.java
index e7b1551..12c28f6 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheRealmProvider.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheRealmProvider.java
@@ -1,8 +1,7 @@
 package org.keycloak.models.cache;
 
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RealmProvider;
 import org.keycloak.models.RoleModel;
@@ -51,10 +50,6 @@ public class NoCacheRealmProvider implements CacheRealmProvider {
     }
 
     @Override
-    public void registerOAuthClientInvalidation(String id) {
-    }
-
-    @Override
     public RealmModel createRealm(String name) {
         return getDelegate().createRealm(name);
     }
@@ -96,17 +91,7 @@ public class NoCacheRealmProvider implements CacheRealmProvider {
     }
 
     @Override
-    public ApplicationModel getApplicationById(String id, RealmModel realm) {
-        return getDelegate().getApplicationById(id, realm);
-    }
-
-    @Override
-    public OAuthClientModel getOAuthClientById(String id, RealmModel realm) {
-        return getDelegate().getOAuthClientById(id, realm);
-    }
-
-    @Override
-    public void registerUserInvalidation(String id) {
-        //To change body of implemented methods use File | Settings | File Templates.
+    public ClientModel getClientById(String id, RealmModel realm) {
+        return getDelegate().getClientById(id, realm);
     }
 }
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java
index ef18caa..f2532af 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java
@@ -2,20 +2,15 @@ package org.keycloak.models.cache;
 
 import org.keycloak.Config;
 import org.keycloak.enums.SslRequired;
-import org.keycloak.models.ApplicationModel;
-import org.keycloak.models.ClaimTypeModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.IdentityProviderMapperModel;
 import org.keycloak.models.IdentityProviderModel;
-import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.PasswordPolicy;
-import org.keycloak.models.ProtocolMapperModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RequiredCredentialModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserFederationProviderModel;
 import org.keycloak.models.cache.entities.CachedRealm;
-import org.keycloak.models.entities.IdentityProviderMapperEntity;
 import org.keycloak.models.utils.KeycloakModelUtils;
 
 import java.security.Key;
@@ -476,39 +471,25 @@ public class RealmAdapter implements RealmModel {
     }
 
     @Override
-    public ClientModel findClient(String clientId) {
-        if (updated != null) return updated.findClient(clientId);
-        String appId = cached.getApplications().get(clientId);
-        if (appId != null) {
-            return cacheSession.getApplicationById(appId, this);
-        }
-        String oauth = cached.getClients().get(clientId);
-        if (oauth != null) {
-            return cacheSession.getOAuthClientById(oauth, this);
-        }
-        return null;
-    }
-
-    @Override
-    public Map<String, ApplicationModel> getApplicationNameMap() {
-        if (updated != null) return updated.getApplicationNameMap();
-        Map<String, ApplicationModel> map = new HashMap<String, ApplicationModel>();
+    public Map<String, ClientModel> getClientNameMap() {
+        if (updated != null) return updated.getClientNameMap();
+        Map<String, ClientModel> map = new HashMap<String, ClientModel>();
         for (String id : cached.getApplications().values()) {
-            ApplicationModel model = cacheSession.getApplicationById(id, this);
+            ClientModel model = cacheSession.getClientById(id, this);
             if (model == null) {
                 throw new IllegalStateException("Cached application not found: " + id);
             }
-            map.put(model.getName(), model);
+            map.put(model.getClientId(), model);
         }
         return map;
     }
 
     @Override
-    public List<ApplicationModel> getApplications() {
-        if (updated != null) return updated.getApplications();
-        List<ApplicationModel> apps = new LinkedList<ApplicationModel>();
+    public List<ClientModel> getClients() {
+        if (updated != null) return updated.getClients();
+        List<ClientModel> apps = new LinkedList<ClientModel>();
         for (String id : cached.getApplications().values()) {
-            ApplicationModel model = cacheSession.getApplicationById(id, this);
+            ClientModel model = cacheSession.getClientById(id, this);
             if (model == null) {
                 throw new IllegalStateException("Cached application not found: " + id);
             }
@@ -519,40 +500,40 @@ public class RealmAdapter implements RealmModel {
     }
 
     @Override
-    public ApplicationModel addApplication(String name) {
+    public ClientModel addClient(String name) {
         getDelegateForUpdate();
-        ApplicationModel app = updated.addApplication(name);
+        ClientModel app = updated.addClient(name);
         cacheSession.registerApplicationInvalidation(app.getId());
         return app;
     }
 
     @Override
-    public ApplicationModel addApplication(String id, String name) {
+    public ClientModel addClient(String id, String clientId) {
         getDelegateForUpdate();
-        ApplicationModel app =  updated.addApplication(id, name);
+        ClientModel app =  updated.addClient(id, clientId);
         cacheSession.registerApplicationInvalidation(app.getId());
         return app;
     }
 
     @Override
-    public boolean removeApplication(String id) {
+    public boolean removeClient(String id) {
         cacheSession.registerApplicationInvalidation(id);
         getDelegateForUpdate();
-        return updated.removeApplication(id);
+        return updated.removeClient(id);
     }
 
     @Override
-    public ApplicationModel getApplicationById(String id) {
-        if (updated != null) return updated.getApplicationById(id);
-        return cacheSession.getApplicationById(id, this);
+    public ClientModel getClientById(String id) {
+        if (updated != null) return updated.getClientById(id);
+        return cacheSession.getClientById(id, this);
     }
 
     @Override
-    public ApplicationModel getApplicationByName(String name) {
-        if (updated != null) return updated.getApplicationByName(name);
-        String id = cached.getApplications().get(name);
+    public ClientModel getClientByClientId(String clientId) {
+        if (updated != null) return updated.getClientByClientId(clientId);
+        String id = cached.getApplications().get(clientId);
         if (id == null) return null;
-        return getApplicationById(id);
+        return getClientById(id);
     }
 
     @Override
@@ -562,57 +543,6 @@ public class RealmAdapter implements RealmModel {
     }
 
     @Override
-    public OAuthClientModel addOAuthClient(String name) {
-        getDelegateForUpdate();
-        OAuthClientModel client = updated.addOAuthClient(name);
-        cacheSession.registerOAuthClientInvalidation(client.getId());
-        return client;
-    }
-
-    @Override
-    public OAuthClientModel addOAuthClient(String id, String name) {
-        getDelegateForUpdate();
-        OAuthClientModel client =  updated.addOAuthClient(id, name);
-        cacheSession.registerOAuthClientInvalidation(client.getId());
-        return client;
-    }
-
-    @Override
-    public OAuthClientModel getOAuthClient(String name) {
-        if (updated != null) return updated.getOAuthClient(name);
-        String id = cached.getClients().get(name);
-        if (id == null) return null;
-        return getOAuthClientById(id);
-    }
-
-    @Override
-    public OAuthClientModel getOAuthClientById(String id) {
-        if (updated != null) return updated.getOAuthClientById(id);
-        return cacheSession.getOAuthClientById(id, this);
-    }
-
-    @Override
-    public boolean removeOAuthClient(String id) {
-        cacheSession.registerOAuthClientInvalidation(id);
-        getDelegateForUpdate();
-        return updated.removeOAuthClient(id);
-    }
-
-    @Override
-    public List<OAuthClientModel> getOAuthClients() {
-        if (updated != null) return updated.getOAuthClients();
-        List<OAuthClientModel> clients = new LinkedList<OAuthClientModel>();
-        for (String id : cached.getClients().values()) {
-            OAuthClientModel model = cacheSession.getOAuthClientById(id, this);
-            if (model == null) {
-                throw new IllegalStateException("Cached oauth client not found: " + id);
-            }
-            clients.add(model);
-        }
-        return clients;
-    }
-
-    @Override
     public Map<String, String> getBrowserSecurityHeaders() {
         if (updated != null) return updated.getBrowserSecurityHeaders();
         return cached.getBrowserSecurityHeaders();
@@ -821,14 +751,14 @@ public class RealmAdapter implements RealmModel {
     }
     
     @Override
-    public ApplicationModel getMasterAdminApp() {
-        return cacheSession.getRealm(Config.getAdminRealm()).getApplicationById(cached.getMasterAdminApp());
+    public ClientModel getMasterAdminClient() {
+        return cacheSession.getRealm(Config.getAdminRealm()).getClientById(cached.getMasterAdminApp());
     }
 
     @Override
-    public void setMasterAdminApp(ApplicationModel app) {
+    public void setMasterAdminClient(ClientModel client) {
         getDelegateForUpdate();
-        updated.setMasterAdminApp(app);
+        updated.setMasterAdminClient(client);
     }
 
     @Override
@@ -876,13 +806,6 @@ public class RealmAdapter implements RealmModel {
     }
 
     @Override
-    public ClientModel findClientById(String id) {
-        ClientModel model = getApplicationById(id);
-        if (model != null) return model;
-        return getOAuthClientById(id);
-    }
-
-    @Override
     public boolean isIdentityFederationEnabled() {
         if (updated != null) return updated.isIdentityFederationEnabled();
         return cached.isIdentityFederationEnabled();
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmCache.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmCache.java
index 246a6ea..3d66462 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmCache.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmCache.java
@@ -1,7 +1,6 @@
 package org.keycloak.models.cache;
 
 import org.keycloak.models.cache.entities.CachedApplication;
-import org.keycloak.models.cache.entities.CachedOAuthClient;
 import org.keycloak.models.cache.entities.CachedRealm;
 import org.keycloak.models.cache.entities.CachedRole;
 
@@ -30,14 +29,6 @@ public interface RealmCache {
 
     void invalidateCachedApplicationById(String id);
 
-    CachedOAuthClient getOAuthClient(String id);
-
-    void invalidateOAuthClient(CachedOAuthClient client);
-
-    void addCachedOAuthClient(CachedOAuthClient client);
-
-    void invalidateCachedOAuthClientById(String id);
-
     CachedRole getRole(String id);
 
     void invalidateRole(CachedRole role);
@@ -46,7 +37,6 @@ public interface RealmCache {
 
     void invalidateCachedRoleById(String id);
 
-
     void invalidateRoleById(String id);
 
     boolean isEnabled();
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RoleAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RoleAdapter.java
index 18f6422..0f30ecd 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RoleAdapter.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RoleAdapter.java
@@ -107,7 +107,7 @@ public class RoleAdapter implements RoleModel {
             return realm;
         } else {
             CachedApplicationRole appRole = (CachedApplicationRole)cached;
-            return realm.getApplicationById(appRole.getAppId());
+            return realm.getClientById(appRole.getAppId());
         }
     }
 
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserAdapter.java
index 14aea05..2087fc2 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserAdapter.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserAdapter.java
@@ -1,6 +1,6 @@
 package org.keycloak.models.cache;
 
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleContainerModel;
@@ -219,14 +219,14 @@ public class UserAdapter implements UserModel {
     }
 
     @Override
-    public Set<RoleModel> getApplicationRoleMappings(ApplicationModel app) {
-        if (updated != null) return updated.getApplicationRoleMappings(app);
+    public Set<RoleModel> getClientRoleMappings(ClientModel app) {
+        if (updated != null) return updated.getClientRoleMappings(app);
         Set<RoleModel> roleMappings = getRoleMappings();
         Set<RoleModel> appMappings = new HashSet<RoleModel>();
         for (RoleModel role : roleMappings) {
             RoleContainerModel container = role.getContainer();
-            if (container instanceof ApplicationModel) {
-                if (((ApplicationModel) container).getId().equals(app.getId())) {
+            if (container instanceof ClientModel) {
+                if (((ClientModel) container).getId().equals(app.getId())) {
                     appMappings.add(role);
                 }
             }
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java
index bd44308..b04a92c 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java
@@ -1,9 +1,8 @@
 package org.keycloak.models.jpa;
 
-import org.keycloak.models.ApplicationModel;
-import org.keycloak.models.ClientIdentityProviderMappingModel;
 import org.keycloak.models.ClientModel;
-import org.keycloak.models.OAuthClientModel;
+import org.keycloak.models.ClientIdentityProviderMappingModel;
+import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.ProtocolMapperModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleContainerModel;
@@ -22,8 +21,6 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -32,15 +29,18 @@ import java.util.Set;
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public abstract class ClientAdapter implements ClientModel {
-    protected ClientEntity entity;
+public class ClientAdapter implements ClientModel {
+
+    protected KeycloakSession session;
     protected RealmModel realm;
     protected EntityManager em;
+    protected ClientEntity entity;
 
-    public ClientAdapter(RealmModel realm, ClientEntity entity, EntityManager em) {
+    public ClientAdapter(RealmModel realm, EntityManager em, KeycloakSession session, ClientEntity entity) {
+        this.session = session;
         this.realm = realm;
-        this.entity = entity;
         this.em = em;
+        this.entity = entity;
     }
 
     public ClientEntity getEntity() {
@@ -58,11 +58,6 @@ public abstract class ClientAdapter implements ClientModel {
     }
 
     @Override
-    public String getClientId() {
-        return entity.getName();
-    }
-
-    @Override
     public boolean isEnabled() {
         return entity.isEnabled();
     }
@@ -177,7 +172,7 @@ public abstract class ClientAdapter implements ClientModel {
     public Set<RoleModel> getRealmScopeMappings() {
         Set<RoleModel> roleMappings = getScopeMappings();
 
-        Set<RoleModel> appRoles = new HashSet<RoleModel>();
+        Set<RoleModel> appRoles = new HashSet<>();
         for (RoleModel role : roleMappings) {
             RoleContainerModel container = role.getContainer();
             if (container instanceof RealmModel) {
@@ -190,8 +185,6 @@ public abstract class ClientAdapter implements ClientModel {
         return appRoles;
     }
 
-
-
     @Override
     public Set<RoleModel> getScopeMappings() {
         TypedQuery<String> query = em.createNamedQuery("clientScopeMappingIds", String.class);
@@ -237,32 +230,6 @@ public abstract class ClientAdapter implements ClientModel {
     }
 
     @Override
-    public boolean hasScope(RoleModel role) {
-        if (isFullScopeAllowed()) return true;
-        Set<RoleModel> roles = getScopeMappings();
-        if (roles.contains(role)) return true;
-
-        for (RoleModel mapping : roles) {
-            if (mapping.hasRole(role)) return true;
-        }
-        return false;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (!this.getClass().equals(o.getClass())) return false;
-
-        ClientAdapter that = (ClientAdapter) o;
-        return that.getId().equals(getId());
-    }
-
-    @Override
-    public int hashCode() {
-        return entity.getId().hashCode();
-    }
-
-    @Override
     public String getProtocol() {
         return entity.getProtocol();
     }
@@ -281,7 +248,7 @@ public abstract class ClientAdapter implements ClientModel {
 
     @Override
     public void removeAttribute(String name) {
-       entity.getAttributes().remove(name);
+        entity.getAttributes().remove(name);
     }
 
     @Override
@@ -291,7 +258,7 @@ public abstract class ClientAdapter implements ClientModel {
 
     @Override
     public Map<String, String> getAttributes() {
-        Map<String, String> copy = new HashMap<String, String>();
+        Map<String, String> copy = new HashMap<>();
         copy.putAll(entity.getAttributes());
         return copy;
     }
@@ -299,8 +266,8 @@ public abstract class ClientAdapter implements ClientModel {
     @Override
     public void updateIdentityProviders(List<ClientIdentityProviderMappingModel> identityProviders) {
         Collection<ClientIdentityProviderMappingEntity> entities = entity.getIdentityProviders();
-        Set<String> already = new HashSet<String>();
-        List<ClientIdentityProviderMappingEntity> remove = new ArrayList<ClientIdentityProviderMappingEntity>();
+        Set<String> already = new HashSet<>();
+        List<ClientIdentityProviderMappingEntity> remove = new ArrayList<>();
 
         for (ClientIdentityProviderMappingEntity entity : entities) {
             IdentityProviderEntity identityProvider = entity.getIdentityProvider();
@@ -500,4 +467,282 @@ public abstract class ClientAdapter implements ClientModel {
         mapping.setConfig(config);
         return mapping;
     }
+
+    @Override
+    public void updateClient() {
+        em.flush();
+    }
+
+    @Override
+    public String getClientId() {
+        return entity.getClientId();
+    }
+
+    @Override
+    public void setClientId(String clientId) {
+        entity.setClientId(clientId);
+    }
+
+    @Override
+    public boolean isSurrogateAuthRequired() {
+        return entity.isSurrogateAuthRequired();
+    }
+
+    @Override
+    public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
+        entity.setSurrogateAuthRequired(surrogateAuthRequired);
+    }
+
+    @Override
+    public String getManagementUrl() {
+        return entity.getManagementUrl();
+    }
+
+    @Override
+    public void setManagementUrl(String url) {
+        entity.setManagementUrl(url);
+    }
+
+    @Override
+    public String getBaseUrl() {
+        return entity.getBaseUrl();
+    }
+
+    @Override
+    public void setBaseUrl(String url) {
+        entity.setBaseUrl(url);
+    }
+
+    @Override
+    public boolean isBearerOnly() {
+        return entity.isBearerOnly();
+    }
+
+    @Override
+    public void setBearerOnly(boolean only) {
+        entity.setBearerOnly(only);
+    }
+
+    @Override
+    public boolean isConsentRequired() {
+        return entity.isConsentRequired();
+    }
+
+    @Override
+    public void setConsentRequired(boolean consentRequired) {
+        entity.setConsentRequired(consentRequired);
+    }
+
+    @Override
+    public boolean isDirectGrantsOnly() {
+        return entity.isDirectGrantsOnly();
+    }
+
+    @Override
+    public void setDirectGrantsOnly(boolean flag) {
+        entity.setDirectGrantsOnly(flag);
+    }
+
+    @Override
+    public RoleModel getRole(String name) {
+        TypedQuery<RoleEntity> query = em.createNamedQuery("getAppRoleByName", RoleEntity.class);
+        query.setParameter("name", name);
+        query.setParameter("application", entity);
+        List<RoleEntity> roles = query.getResultList();
+        if (roles.size() == 0) return null;
+        return new RoleAdapter(realm, em, roles.get(0));
+    }
+
+    @Override
+    public RoleModel addRole(String name) {
+        return this.addRole(KeycloakModelUtils.generateId(), name);
+    }
+
+    @Override
+    public RoleModel addRole(String id, String name) {
+        RoleEntity roleEntity = new RoleEntity();
+        roleEntity.setId(id);
+        roleEntity.setName(name);
+        roleEntity.setApplication(entity);
+        roleEntity.setApplicationRole(true);
+        roleEntity.setRealmId(realm.getId());
+        em.persist(roleEntity);
+        entity.getRoles().add(roleEntity);
+        em.flush();
+        return new RoleAdapter(realm, em, roleEntity);
+    }
+
+    @Override
+    public boolean removeRole(RoleModel roleModel) {
+        if (roleModel == null) {
+            return false;
+        }
+        if (!roleModel.getContainer().equals(this)) return false;
+
+        session.users().preRemove(getRealm(), roleModel);
+        RoleEntity role = RoleAdapter.toRoleEntity(roleModel, em);
+        if (!role.isApplicationRole()) return false;
+
+        entity.getRoles().remove(role);
+        entity.getDefaultRoles().remove(role);
+        em.createNativeQuery("delete from COMPOSITE_ROLE where CHILD_ROLE = :role").setParameter("role", role).executeUpdate();
+        em.createNamedQuery("deleteScopeMappingByRole").setParameter("role", role).executeUpdate();
+        role.setApplication(null);
+        em.flush();
+        em.remove(role);
+        em.flush();
+
+        return true;
+    }
+
+    @Override
+    public Set<RoleModel> getRoles() {
+        Set<RoleModel> list = new HashSet<RoleModel>();
+        Collection<RoleEntity> roles = entity.getRoles();
+        if (roles == null) return list;
+        for (RoleEntity entity : roles) {
+            list.add(new RoleAdapter(realm, em, entity));
+        }
+        return list;
+    }
+
+    @Override
+    public boolean hasScope(RoleModel role) {
+        if (isFullScopeAllowed()) return true;
+        Set<RoleModel> roles = getScopeMappings();
+        if (roles.contains(role)) return true;
+
+        for (RoleModel mapping : roles) {
+            if (mapping.hasRole(role)) return true;
+        }
+        roles = getRoles();
+        if (roles.contains(role)) return true;
+
+        for (RoleModel mapping : roles) {
+            if (mapping.hasRole(role)) return true;
+        }
+        return false;
+    }
+
+    @Override
+    public Set<RoleModel> getClientScopeMappings(ClientModel client) {
+        Set<RoleModel> roleMappings = client.getScopeMappings();
+
+        Set<RoleModel> appRoles = new HashSet<RoleModel>();
+        for (RoleModel role : roleMappings) {
+            RoleContainerModel container = role.getContainer();
+            if (container instanceof RealmModel) {
+            } else {
+                ClientModel app = (ClientModel)container;
+                if (app.getId().equals(getId())) {
+                    appRoles.add(role);
+                }
+            }
+        }
+
+        return appRoles;
+    }
+
+
+
+
+    @Override
+    public List<String> getDefaultRoles() {
+        Collection<RoleEntity> entities = entity.getDefaultRoles();
+        List<String> roles = new ArrayList<String>();
+        if (entities == null) return roles;
+        for (RoleEntity entity : entities) {
+            roles.add(entity.getName());
+        }
+        return roles;
+    }
+
+    @Override
+    public void addDefaultRole(String name) {
+        RoleModel role = getRole(name);
+        if (role == null) {
+            role = addRole(name);
+        }
+        Collection<RoleEntity> entities = entity.getDefaultRoles();
+        for (RoleEntity entity : entities) {
+            if (entity.getId().equals(role.getId())) {
+                return;
+            }
+        }
+        RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em);
+        entities.add(roleEntity);
+        em.flush();
+    }
+
+    @Override
+    public void updateDefaultRoles(String[] defaultRoles) {
+        Collection<RoleEntity> entities = entity.getDefaultRoles();
+        Set<String> already = new HashSet<String>();
+        List<RoleEntity> remove = new ArrayList<RoleEntity>();
+        for (RoleEntity rel : entities) {
+            if (!contains(rel.getName(), defaultRoles)) {
+                remove.add(rel);
+            } else {
+                already.add(rel.getName());
+            }
+        }
+        for (RoleEntity entity : remove) {
+            entities.remove(entity);
+        }
+        em.flush();
+        for (String roleName : defaultRoles) {
+            if (!already.contains(roleName)) {
+                addDefaultRole(roleName);
+            }
+        }
+        em.flush();
+    }
+
+    @Override
+    public int getNodeReRegistrationTimeout() {
+        return entity.getNodeReRegistrationTimeout();
+    }
+
+    @Override
+    public void setNodeReRegistrationTimeout(int timeout) {
+        entity.setNodeReRegistrationTimeout(timeout);
+    }
+
+    @Override
+    public Map<String, Integer> getRegisteredNodes() {
+        return entity.getRegisteredNodes();
+    }
+
+    @Override
+    public void registerNode(String nodeHost, int registrationTime) {
+        Map<String, Integer> currentNodes = getRegisteredNodes();
+        currentNodes.put(nodeHost, registrationTime);
+        em.flush();
+    }
+
+    @Override
+    public void unregisterNode(String nodeHost) {
+        Map<String, Integer> currentNodes = getRegisteredNodes();
+        currentNodes.remove(nodeHost);
+        em.flush();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof ClientModel)) return false;
+
+        ClientModel that = (ClientModel) o;
+        return that.getId().equals(getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
+
+    public String toString() {
+        return getClientId();
+    }
+
 }
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java
index e3c8bfd..f8a25f1 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java
@@ -7,8 +7,6 @@ import javax.persistence.ElementCollection;
 import javax.persistence.Entity;
 import javax.persistence.FetchType;
 import javax.persistence.Id;
-import javax.persistence.Inheritance;
-import javax.persistence.InheritanceType;
 import javax.persistence.JoinColumn;
 import javax.persistence.JoinTable;
 import javax.persistence.ManyToOne;
@@ -28,14 +26,14 @@ import java.util.Set;
  * @version $Revision: 1 $
  */
 @Entity
-@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
-@Table(name="CLIENT", uniqueConstraints = {@UniqueConstraint(columnNames = {"REALM_ID", "NAME"})})
-public abstract class ClientEntity {
+@Table(name="CLIENT", uniqueConstraints = {@UniqueConstraint(columnNames = {"REALM_ID", "CLIENT_ID"})})
+public class ClientEntity {
+
     @Id
     @Column(name="ID", length = 36)
     private String id;
-    @Column(name = "NAME")
-    private String name;
+    @Column(name = "CLIENT_ID")
+    private String clientId;
     @Column(name="ENABLED")
     private boolean enabled;
     @Column(name="SECRET")
@@ -77,6 +75,40 @@ public abstract class ClientEntity {
     @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "client")
     Collection<ProtocolMapperEntity> protocolMappers = new ArrayList<ProtocolMapperEntity>();
 
+    @Column(name="SURROGATE_AUTH_REQUIRED")
+    private boolean surrogateAuthRequired;
+
+    @Column(name="BASE_URL")
+    private String baseUrl;
+
+    @Column(name="MANAGEMENT_URL")
+    private String managementUrl;
+
+    @Column(name="DIRECT_GRANTS_ONLY")
+    protected boolean directGrantsOnly;
+
+    @Column(name="BEARER_ONLY")
+    private boolean bearerOnly;
+
+    @Column(name="CONSENT_REQUIRED")
+    private boolean consentRequired;
+
+    @Column(name="NODE_REREG_TIMEOUT")
+    private int nodeReRegistrationTimeout;
+
+    @OneToMany(fetch = FetchType.EAGER, cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "application")
+    Collection<RoleEntity> roles = new ArrayList<RoleEntity>();
+
+    @OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true)
+    @JoinTable(name="APPLICATION_DEFAULT_ROLES", joinColumns = { @JoinColumn(name="APPLICATION_ID")}, inverseJoinColumns = { @JoinColumn(name="ROLE_ID")})
+    Collection<RoleEntity> defaultRoles = new ArrayList<RoleEntity>();
+
+    @ElementCollection
+    @MapKeyColumn(name="NAME")
+    @Column(name="VALUE")
+    @CollectionTable(name="APP_NODE_REGISTRATIONS", joinColumns={ @JoinColumn(name="APPLICATION_ID") })
+    Map<String, Integer> registeredNodes = new HashMap<String, Integer>();
+
     public RealmEntity getRealm() {
         return realm;
     }
@@ -101,12 +133,12 @@ public abstract class ClientEntity {
         this.enabled = enabled;
     }
 
-    public String getName() {
-        return name;
+    public String getClientId() {
+        return clientId;
     }
 
-    public void setName(String name) {
-        this.name = name;
+    public void setClientId(String clientId) {
+        this.clientId = clientId;
     }
 
     public Set<String> getWebOrigins() {
@@ -196,4 +228,84 @@ public abstract class ClientEntity {
     public void setProtocolMappers(Collection<ProtocolMapperEntity> protocolMappers) {
         this.protocolMappers = protocolMappers;
     }
+
+    public boolean isSurrogateAuthRequired() {
+        return surrogateAuthRequired;
+    }
+
+    public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
+        this.surrogateAuthRequired = surrogateAuthRequired;
+    }
+
+    public String getBaseUrl() {
+        return baseUrl;
+    }
+
+    public void setBaseUrl(String baseUrl) {
+        this.baseUrl = baseUrl;
+    }
+
+    public String getManagementUrl() {
+        return managementUrl;
+    }
+
+    public void setManagementUrl(String managementUrl) {
+        this.managementUrl = managementUrl;
+    }
+
+    public Collection<RoleEntity> getRoles() {
+        return roles;
+    }
+
+    public void setRoles(Collection<RoleEntity> roles) {
+        this.roles = roles;
+    }
+
+    public Collection<RoleEntity> getDefaultRoles() {
+        return defaultRoles;
+    }
+
+    public void setDefaultRoles(Collection<RoleEntity> defaultRoles) {
+        this.defaultRoles = defaultRoles;
+    }
+
+    public boolean isBearerOnly() {
+        return bearerOnly;
+    }
+
+    public void setBearerOnly(boolean bearerOnly) {
+        this.bearerOnly = bearerOnly;
+    }
+
+    public boolean isConsentRequired() {
+        return consentRequired;
+    }
+
+    public void setConsentRequired(boolean consentRequired) {
+        this.consentRequired = consentRequired;
+    }
+
+    public boolean isDirectGrantsOnly() {
+        return directGrantsOnly;
+    }
+
+    public void setDirectGrantsOnly(boolean directGrantsOnly) {
+        this.directGrantsOnly = directGrantsOnly;
+    }
+
+    public int getNodeReRegistrationTimeout() {
+        return nodeReRegistrationTimeout;
+    }
+
+    public void setNodeReRegistrationTimeout(int nodeReRegistrationTimeout) {
+        this.nodeReRegistrationTimeout = nodeReRegistrationTimeout;
+    }
+
+    public Map<String, Integer> getRegisteredNodes() {
+        return registeredNodes;
+    }
+
+    public void setRegisteredNodes(Map<String, Integer> registeredNodes) {
+        this.registeredNodes = registeredNodes;
+    }
 }
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ProtocolMapperEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ProtocolMapperEntity.java
index 7b2c323..ccce0d9 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ProtocolMapperEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ProtocolMapperEntity.java
@@ -9,8 +9,6 @@ import javax.persistence.Id;
 import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
 import javax.persistence.MapKeyColumn;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
 import javax.persistence.Table;
 import java.util.Map;
 
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
index a656f76..d39b62e 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
@@ -105,7 +105,7 @@ public class RealmEntity {
 
     @OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true)
     @JoinTable(name="REALM_APPLICATION", joinColumns={ @JoinColumn(name="REALM_ID") }, inverseJoinColumns={ @JoinColumn(name="APPLICATION_ID") })
-    Collection<ApplicationEntity> applications = new ArrayList<ApplicationEntity>();
+    Collection<ClientEntity> applications = new ArrayList<ClientEntity>();
 
     @OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
     Collection<RoleEntity> roles = new ArrayList<RoleEntity>();
@@ -137,7 +137,7 @@ public class RealmEntity {
 
     @OneToOne
     @JoinColumn(name="MASTER_ADMIN_APP")
-    protected ApplicationEntity masterAdminApp;
+    protected ClientEntity masterAdminApp;
 
     @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
     protected List<IdentityProviderEntity> identityProviders = new ArrayList<IdentityProviderEntity>();
@@ -318,11 +318,11 @@ public class RealmEntity {
         this.requiredCredentials = requiredCredentials;
     }
 
-    public Collection<ApplicationEntity> getApplications() {
+    public Collection<ClientEntity> getApplications() {
         return applications;
     }
 
-    public void setApplications(Collection<ApplicationEntity> applications) {
+    public void setApplications(Collection<ClientEntity> applications) {
         this.applications = applications;
     }
 
@@ -437,11 +437,11 @@ public class RealmEntity {
         this.enabledEventTypes = enabledEventTypes;
     }
     
-    public ApplicationEntity getMasterAdminApp() {
+    public ClientEntity getMasterAdminApp() {
         return masterAdminApp;
     }
 
-    public void setMasterAdminApp(ApplicationEntity masterAdminApp) {
+    public void setMasterAdminApp(ClientEntity masterAdminApp) {
         this.masterAdminApp = masterAdminApp;
     }
 
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RoleEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RoleEntity.java
index db40cea..ffbd711 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RoleEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RoleEntity.java
@@ -51,7 +51,7 @@ public class RoleEntity {
 
     @ManyToOne(fetch = FetchType.LAZY)
     @JoinColumn(name = "APPLICATION")
-    private ApplicationEntity application;
+    private ClientEntity application;
 
     // Hack to ensure that either name+application or name+realm are unique. Needed due to MS-SQL as it don't allow multiple NULL values in the column, which is part of constraint
     @Column(name="APP_REALM_CONSTRAINT", length = 36)
@@ -118,11 +118,11 @@ public class RoleEntity {
         this.appRealmConstraint = realm.getId();
     }
 
-    public ApplicationEntity getApplication() {
+    public ClientEntity getApplication() {
         return application;
     }
 
-    public void setApplication(ApplicationEntity application) {
+    public void setApplication(ClientEntity application) {
         this.application = application;
         if (application != null) {
             this.appRealmConstraint = application.getId();
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java
index 3091cc9..f887670 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java
@@ -1,13 +1,11 @@
 package org.keycloak.models.jpa;
 
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RealmProvider;
 import org.keycloak.models.RoleModel;
-import org.keycloak.models.jpa.entities.ApplicationEntity;
-import org.keycloak.models.jpa.entities.OAuthClientEntity;
+import org.keycloak.models.jpa.entities.ClientEntity;
 import org.keycloak.models.jpa.entities.RealmEntity;
 import org.keycloak.models.jpa.entities.RoleEntity;
 import org.keycloak.models.utils.KeycloakModelUtils;
@@ -93,12 +91,8 @@ public class JpaRealmProvider implements RealmProvider {
 
         RealmAdapter adapter = new RealmAdapter(session, em, realm);
         session.users().preRemove(adapter);
-        for (ApplicationEntity a : new LinkedList<ApplicationEntity>(realm.getApplications())) {
-            adapter.removeApplication(a.getId());
-        }
-
-        for (OAuthClientModel oauth : adapter.getOAuthClients()) {
-            adapter.removeOAuthClient(oauth.getId());
+        for (ClientEntity a : new LinkedList<>(realm.getApplications())) {
+            adapter.removeClient(a.getId());
         }
 
         em.remove(realm);
@@ -118,21 +112,12 @@ public class JpaRealmProvider implements RealmProvider {
     }
 
     @Override
-    public ApplicationModel getApplicationById(String id, RealmModel realm) {
-        ApplicationEntity app = em.find(ApplicationEntity.class, id);
+    public ClientModel getClientById(String id, RealmModel realm) {
+        ClientEntity app = em.find(ClientEntity.class, id);
 
         // Check if application belongs to this realm
         if (app == null || !realm.getId().equals(app.getRealm().getId())) return null;
-        return new ApplicationAdapter(realm, em, session, app);
-    }
-
-    @Override
-    public OAuthClientModel getOAuthClientById(String id, RealmModel realm) {
-        OAuthClientEntity client = em.find(OAuthClientEntity.class, id);
-
-        // Check if client belongs to this realm
-        if (client == null || !realm.getId().equals(client.getRealm().getId())) return null;
-        return new OAuthClientAdapter(realm, client, em);
+        return new ClientAdapter(realm, em, session, app);
     }
 
 }
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java
index 2b00c1c..07d3f6f 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java
@@ -1,6 +1,6 @@
 package org.keycloak.models.jpa;
 
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.CredentialValidationOutput;
 import org.keycloak.models.FederatedIdentityModel;
 import org.keycloak.models.KeycloakSession;
@@ -61,7 +61,7 @@ public class JpaUserProvider implements UserProvider {
                 userModel.grantRole(realm.getRole(r));
             }
 
-            for (ApplicationModel application : realm.getApplications()) {
+            for (ClientModel application : realm.getClients()) {
                 for (String r : application.getDefaultRoles()) {
                     userModel.grantRole(application.getRole(r));
                 }
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
index 1f45e48..4370165 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
@@ -1,1415 +1,1325 @@
-package org.keycloak.models.jpa;
-
-import org.keycloak.enums.SslRequired;
-import org.keycloak.models.ApplicationModel;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.IdentityProviderMapperModel;
-import org.keycloak.models.IdentityProviderModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.OAuthClientModel;
-import org.keycloak.models.PasswordPolicy;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RequiredCredentialModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserFederationProviderModel;
-import org.keycloak.models.jpa.entities.ApplicationEntity;
-import org.keycloak.models.jpa.entities.IdentityProviderEntity;
-import org.keycloak.models.jpa.entities.IdentityProviderMapperEntity;
-import org.keycloak.models.jpa.entities.OAuthClientEntity;
-import org.keycloak.models.jpa.entities.RealmAttributeEntity;
-import org.keycloak.models.jpa.entities.RealmEntity;
-import org.keycloak.models.jpa.entities.RequiredCredentialEntity;
-import org.keycloak.models.jpa.entities.RoleEntity;
-import org.keycloak.models.jpa.entities.UserFederationProviderEntity;
-import org.keycloak.models.utils.KeycloakModelUtils;
-
-import javax.persistence.EntityManager;
-import javax.persistence.TypedQuery;
-import java.security.Key;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @version $Revision: 1 $
- */
-public class RealmAdapter implements RealmModel {
-    protected RealmEntity realm;
-    protected EntityManager em;
-    protected volatile transient PublicKey publicKey;
-    protected volatile transient PrivateKey privateKey;
-    protected volatile transient X509Certificate certificate;
-    protected volatile transient Key codeSecretKey;
-    protected KeycloakSession session;
-    private PasswordPolicy passwordPolicy;
-
-    public RealmAdapter(KeycloakSession session, EntityManager em, RealmEntity realm) {
-        this.session = session;
-        this.em = em;
-        this.realm = realm;
-    }
-
-    public RealmEntity getEntity() {
-        return realm;
-    }
-
-    @Override
-    public String getId() {
-        return realm.getId();
-    }
-
-    @Override
-    public String getName() {
-        return realm.getName();
-    }
-
-    @Override
-    public void setName(String name) {
-        realm.setName(name);
-        em.flush();
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return realm.isEnabled();
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        realm.setEnabled(enabled);
-        em.flush();
-    }
-
-    @Override
-    public SslRequired getSslRequired() {
-        return realm.getSslRequired() != null ? SslRequired.valueOf(realm.getSslRequired()) : null;
-    }
-
-    @Override
-    public void setSslRequired(SslRequired sslRequired) {
-        realm.setSslRequired(sslRequired.name());
-        em.flush();
-    }
-
-    @Override
-    public boolean isPasswordCredentialGrantAllowed() {
-        return realm.isPasswordCredentialGrantAllowed();
-    }
-
-    @Override
-    public void setPasswordCredentialGrantAllowed(boolean passwordCredentialGrantAllowed) {
-        realm.setPasswordCredentialGrantAllowed(passwordCredentialGrantAllowed);
-        em.flush();
-    }
-
-    @Override
-    public boolean isRegistrationAllowed() {
-        return realm.isRegistrationAllowed();
-    }
-
-    @Override
-    public void setRegistrationAllowed(boolean registrationAllowed) {
-        realm.setRegistrationAllowed(registrationAllowed);
-        em.flush();
-    }
-
-    @Override
-    public boolean isRegistrationEmailAsUsername() {
-        return realm.isRegistrationEmailAsUsername();
-    }
-
-    @Override
-    public void setRegistrationEmailAsUsername(boolean registrationEmailAsUsername) {
-        realm.setRegistrationEmailAsUsername(registrationEmailAsUsername);
-        em.flush();
-    }
-
-    @Override
-    public boolean isRememberMe() {
-        return realm.isRememberMe();
-    }
-
-    @Override
-    public void setRememberMe(boolean rememberMe) {
-        realm.setRememberMe(rememberMe);
-        em.flush();
-    }
-
-    public void setAttribute(String name, String value) {
-        for (RealmAttributeEntity attr : realm.getAttributes()) {
-            if (attr.getName().equals(name)) {
-                attr.setValue(value);
-                return;
-            }
-        }
-        RealmAttributeEntity attr = new RealmAttributeEntity();
-        attr.setName(name);
-        attr.setValue(value);
-        attr.setRealm(realm);
-        em.persist(attr);
-        realm.getAttributes().add(attr);
-    }
-
-    public void setAttribute(String name, Boolean value) {
-        setAttribute(name, value.toString());
-    }
-
-    public void setAttribute(String name, Integer value) {
-        setAttribute(name, value.toString());
-    }
-
-    public void setAttribute(String name, Long value) {
-        setAttribute(name, value.toString());
-    }
-
-    public void removeAttribute(String name) {
-        Iterator<RealmAttributeEntity> it = realm.getAttributes().iterator();
-        while (it.hasNext()) {
-            RealmAttributeEntity attr = it.next();
-            if (attr.getName().equals(name)) {
-                it.remove();
-                em.remove(attr);
-            }
-        }
-    }
-
-    public String getAttribute(String name) {
-        for (RealmAttributeEntity attr : realm.getAttributes()) {
-            if (attr.getName().equals(name)) {
-                return attr.getValue();
-            }
-        }
-        return null;
-    }
-
-    public Integer getAttribute(String name, Integer defaultValue) {
-        String v = getAttribute(name);
-        return v != null ? Integer.parseInt(v) : defaultValue;
-
-    }
-
-    public Long getAttribute(String name, Long defaultValue) {
-        String v = getAttribute(name);
-        return v != null ? Long.parseLong(v) : defaultValue;
-
-    }
-
-    public Boolean getAttribute(String name, Boolean defaultValue) {
-        String v = getAttribute(name);
-        return v != null ? Boolean.parseBoolean(v) : defaultValue;
-
-    }
-
-    public Map<String, String> getAttributes() {
-        // should always return a copy
-        Map<String, String> result = new HashMap<String, String>();
-        for (RealmAttributeEntity attr : realm.getAttributes()) {
-            result.put(attr.getName(), attr.getValue());
-        }
-        return result;
-    }
-    @Override
-    public boolean isBruteForceProtected() {
-        return getAttribute("bruteForceProtected", false);
-    }
-
-    @Override
-    public void setBruteForceProtected(boolean value) {
-        setAttribute("bruteForceProtected", value);
-    }
-
-    @Override
-    public int getMaxFailureWaitSeconds() {
-        return getAttribute("maxFailureWaitSeconds", 0);
-    }
-
-    @Override
-    public void setMaxFailureWaitSeconds(int val) {
-        setAttribute("maxFailureWaitSeconds", val);
-    }
-
-    @Override
-    public int getWaitIncrementSeconds() {
-        return getAttribute("waitIncrementSeconds", 0);
-    }
-
-    @Override
-    public void setWaitIncrementSeconds(int val) {
-        setAttribute("waitIncrementSeconds", val);
-    }
-
-    @Override
-    public long getQuickLoginCheckMilliSeconds() {
-        return getAttribute("quickLoginCheckMilliSeconds", 0l);
-    }
-
-    @Override
-    public void setQuickLoginCheckMilliSeconds(long val) {
-        setAttribute("quickLoginCheckMilliSeconds", val);
-    }
-
-    @Override
-    public int getMinimumQuickLoginWaitSeconds() {
-        return getAttribute("minimumQuickLoginWaitSeconds", 0);
-    }
-
-    @Override
-    public void setMinimumQuickLoginWaitSeconds(int val) {
-        setAttribute("minimumQuickLoginWaitSeconds", val);
-    }
-
-    @Override
-    public int getMaxDeltaTimeSeconds() {
-        return getAttribute("maxDeltaTimeSeconds", 0);
-    }
-
-    @Override
-    public void setMaxDeltaTimeSeconds(int val) {
-        setAttribute("maxDeltaTimeSeconds", val);
-    }
-
-    @Override
-    public int getFailureFactor() {
-        return getAttribute("failureFactor", 0);
-    }
-
-    @Override
-    public void setFailureFactor(int failureFactor) {
-        setAttribute("failureFactor", failureFactor);
-    }
-
-    @Override
-    public boolean isVerifyEmail() {
-        return realm.isVerifyEmail();
-    }
-
-    @Override
-    public void setVerifyEmail(boolean verifyEmail) {
-        realm.setVerifyEmail(verifyEmail);
-        em.flush();
-    }
-
-    @Override
-    public boolean isResetPasswordAllowed() {
-        return realm.isResetPasswordAllowed();
-    }
-
-    @Override
-    public void setResetPasswordAllowed(boolean resetPasswordAllowed) {
-        realm.setResetPasswordAllowed(resetPasswordAllowed);
-        em.flush();
-    }
-
-    @Override
-    public int getNotBefore() {
-        return realm.getNotBefore();
-    }
-
-    @Override
-    public void setNotBefore(int notBefore) {
-        realm.setNotBefore(notBefore);
-    }
-
-    @Override
-    public int getAccessTokenLifespan() {
-        return realm.getAccessTokenLifespan();
-    }
-
-    @Override
-    public void setAccessTokenLifespan(int tokenLifespan) {
-        realm.setAccessTokenLifespan(tokenLifespan);
-        em.flush();
-    }
-
-    @Override
-    public int getSsoSessionIdleTimeout() {
-        return realm.getSsoSessionIdleTimeout();
-    }
-
-    @Override
-    public void setSsoSessionIdleTimeout(int seconds) {
-        realm.setSsoSessionIdleTimeout(seconds);
-    }
-
-    @Override
-    public int getSsoSessionMaxLifespan() {
-        return realm.getSsoSessionMaxLifespan();
-    }
-
-    @Override
-    public void setSsoSessionMaxLifespan(int seconds) {
-        realm.setSsoSessionMaxLifespan(seconds);
-    }
-
-    @Override
-    public int getAccessCodeLifespan() {
-        return realm.getAccessCodeLifespan();
-    }
-
-    @Override
-    public void setAccessCodeLifespan(int accessCodeLifespan) {
-        realm.setAccessCodeLifespan(accessCodeLifespan);
-        em.flush();
-    }
-
-    @Override
-    public int getAccessCodeLifespanUserAction() {
-        return realm.getAccessCodeLifespanUserAction();
-    }
-
-    @Override
-    public void setAccessCodeLifespanUserAction(int accessCodeLifespanUserAction) {
-        realm.setAccessCodeLifespanUserAction(accessCodeLifespanUserAction);
-        em.flush();
-    }
-
-    @Override
-    public int getAccessCodeLifespanLogin() {
-        return realm.getAccessCodeLifespanLogin();
-    }
-
-    @Override
-    public void setAccessCodeLifespanLogin(int accessCodeLifespanLogin) {
-        realm.setAccessCodeLifespanLogin(accessCodeLifespanLogin);
-        em.flush();
-    }
-
-    @Override
-    public String getPublicKeyPem() {
-        return realm.getPublicKeyPem();
-    }
-
-    @Override
-    public void setPublicKeyPem(String publicKeyPem) {
-        realm.setPublicKeyPem(publicKeyPem);
-        em.flush();
-    }
-
-    @Override
-    public X509Certificate getCertificate() {
-        if (certificate != null) return certificate;
-        certificate = KeycloakModelUtils.getCertificate(getCertificatePem());
-        return certificate;
-    }
-
-    @Override
-    public void setCertificate(X509Certificate certificate) {
-        this.certificate = certificate;
-        String certificatePem = KeycloakModelUtils.getPemFromCertificate(certificate);
-        setCertificatePem(certificatePem);
-
-    }
-
-    @Override
-    public String getCertificatePem() {
-        return realm.getCertificatePem();
-    }
-
-    @Override
-    public void setCertificatePem(String certificate) {
-        realm.setCertificatePem(certificate);
-
-    }
-
-    @Override
-    public String getPrivateKeyPem() {
-        return realm.getPrivateKeyPem();
-    }
-
-    @Override
-    public void setPrivateKeyPem(String privateKeyPem) {
-        realm.setPrivateKeyPem(privateKeyPem);
-        em.flush();
-    }
-
-    @Override
-    public PublicKey getPublicKey() {
-        if (publicKey != null) return publicKey;
-        publicKey = KeycloakModelUtils.getPublicKey(getPublicKeyPem());
-        return publicKey;
-    }
-
-    @Override
-    public void setPublicKey(PublicKey publicKey) {
-        this.publicKey = publicKey;
-        String publicKeyPem = KeycloakModelUtils.getPemFromKey(publicKey);
-        setPublicKeyPem(publicKeyPem);
-    }
-
-    @Override
-    public PrivateKey getPrivateKey() {
-        if (privateKey != null) return privateKey;
-        privateKey = KeycloakModelUtils.getPrivateKey(getPrivateKeyPem());
-        return privateKey;
-    }
-
-    @Override
-    public void setPrivateKey(PrivateKey privateKey) {
-        this.privateKey = privateKey;
-        String privateKeyPem = KeycloakModelUtils.getPemFromKey(privateKey);
-        setPrivateKeyPem(privateKeyPem);
-    }
-
-    @Override
-    public String getCodeSecret() {
-        return realm.getCodeSecret();
-    }
-
-    @Override
-    public Key getCodeSecretKey() {
-        if (codeSecretKey == null) {
-            codeSecretKey = KeycloakModelUtils.getSecretKey(getCodeSecret());
-        }
-        return codeSecretKey;
-    }
-
-    @Override
-    public void setCodeSecret(String codeSecret) {
-        realm.setCodeSecret(codeSecret);
-    }
-
-    protected RequiredCredentialModel initRequiredCredentialModel(String type) {
-        RequiredCredentialModel model = RequiredCredentialModel.BUILT_IN.get(type);
-        if (model == null) {
-            throw new RuntimeException("Unknown credential type " + type);
-        }
-        return model;
-    }
-
-    @Override
-    public void addRequiredCredential(String type) {
-        RequiredCredentialModel model = initRequiredCredentialModel(type);
-        addRequiredCredential(model);
-        em.flush();
-    }
-
-    public void addRequiredCredential(RequiredCredentialModel model) {
-        RequiredCredentialEntity entity = new RequiredCredentialEntity();
-        entity.setRealm(realm);
-        entity.setInput(model.isInput());
-        entity.setSecret(model.isSecret());
-        entity.setType(model.getType());
-        entity.setFormLabel(model.getFormLabel());
-        em.persist(entity);
-        realm.getRequiredCredentials().add(entity);
-        em.flush();
-    }
-
-    @Override
-    public void updateRequiredCredentials(Set<String> creds) {
-        Collection<RequiredCredentialEntity> relationships = realm.getRequiredCredentials();
-        if (relationships == null) relationships = new ArrayList<RequiredCredentialEntity>();
-
-        Set<String> already = new HashSet<String>();
-        List<RequiredCredentialEntity> remove = new ArrayList<RequiredCredentialEntity>();
-        for (RequiredCredentialEntity rel : relationships) {
-            if (!creds.contains(rel.getType())) {
-                remove.add(rel);
-            } else {
-                already.add(rel.getType());
-            }
-        }
-        for (RequiredCredentialEntity entity : remove) {
-            relationships.remove(entity);
-            em.remove(entity);
-        }
-        for (String cred : creds) {
-            if (!already.contains(cred)) {
-                addRequiredCredential(cred);
-            }
-        }
-        em.flush();
-    }
-
-
-    @Override
-    public List<RequiredCredentialModel> getRequiredCredentials() {
-        List<RequiredCredentialModel> requiredCredentialModels = new ArrayList<RequiredCredentialModel>();
-        Collection<RequiredCredentialEntity> entities = realm.getRequiredCredentials();
-        if (entities == null) return requiredCredentialModels;
-        for (RequiredCredentialEntity entity : entities) {
-            RequiredCredentialModel model = new RequiredCredentialModel();
-            model.setFormLabel(entity.getFormLabel());
-            model.setType(entity.getType());
-            model.setSecret(entity.isSecret());
-            model.setInput(entity.isInput());
-            requiredCredentialModels.add(model);
-        }
-        return requiredCredentialModels;  //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-
-    @Override
-    public List<String> getDefaultRoles() {
-        Collection<RoleEntity> entities = realm.getDefaultRoles();
-        List<String> roles = new ArrayList<String>();
-        if (entities == null) return roles;
-        for (RoleEntity entity : entities) {
-            roles.add(entity.getName());
-        }
-        return roles;
-    }
-
-    @Override
-    public void addDefaultRole(String name) {
-        RoleModel role = getRole(name);
-        if (role == null) {
-            role = addRole(name);
-        }
-        Collection<RoleEntity> entities = realm.getDefaultRoles();
-        for (RoleEntity entity : entities) {
-            if (entity.getId().equals(role.getId())) {
-                return;
-            }
-        }
-        RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em);
-        entities.add(roleEntity);
-        em.flush();
-    }
-
-    public static boolean contains(String str, String[] array) {
-        for (String s : array) {
-            if (str.equals(s)) return true;
-        }
-        return false;
-    }
-
-    @Override
-    public void updateDefaultRoles(String[] defaultRoles) {
-        Collection<RoleEntity> entities = realm.getDefaultRoles();
-        Set<String> already = new HashSet<String>();
-        List<RoleEntity> remove = new ArrayList<RoleEntity>();
-        for (RoleEntity rel : entities) {
-            if (!contains(rel.getName(), defaultRoles)) {
-                remove.add(rel);
-            } else {
-                already.add(rel.getName());
-            }
-        }
-        for (RoleEntity entity : remove) {
-            entities.remove(entity);
-        }
-        em.flush();
-        for (String roleName : defaultRoles) {
-            if (!already.contains(roleName)) {
-                addDefaultRole(roleName);
-            }
-        }
-        em.flush();
-    }
-
-    @Override
-    public ClientModel findClient(String clientId) {
-        ClientModel model = getApplicationByName(clientId);
-        if (model != null) return model;
-        return getOAuthClient(clientId);
-    }
-
-    @Override
-    public ClientModel findClientById(String id) {
-        ClientModel model = getApplicationById(id);
-        if (model != null) return model;
-        return getOAuthClientById(id);
-    }
-
-    @Override
-    public Map<String, ApplicationModel> getApplicationNameMap() {
-        Map<String, ApplicationModel> map = new HashMap<String, ApplicationModel>();
-        for (ApplicationModel app : getApplications()) {
-            map.put(app.getName(), app);
-        }
-        return map;  //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public List<ApplicationModel> getApplications() {
-        List<ApplicationModel> list = new ArrayList<ApplicationModel>();
-        if (realm.getApplications() == null) return list;
-        for (ApplicationEntity entity : realm.getApplications()) {
-            list.add(new ApplicationAdapter(this, em, session, entity));
-        }
-        return list;
-    }
-
-    @Override
-    public ApplicationModel addApplication(String name) {
-        return this.addApplication(KeycloakModelUtils.generateId(), name);
-    }
-
-    @Override
-    public ApplicationModel addApplication(String id, String name) {
-        ApplicationEntity applicationData = new ApplicationEntity();
-        applicationData.setId(id);
-        applicationData.setName(name);
-        applicationData.setEnabled(true);
-        applicationData.setRealm(realm);
-        realm.getApplications().add(applicationData);
-        em.persist(applicationData);
-        em.flush();
-        final ApplicationModel resource = new ApplicationAdapter(this, em, session, applicationData);
-        em.flush();
-        session.getKeycloakSessionFactory().publish(new ApplicationCreationEvent() {
-            @Override
-            public ApplicationModel getCreatedApplication() {
-                return resource;
-            }
-
-            @Override
-            public ClientModel getCreatedClient() {
-                return resource;
-            }
-        });
-        return resource;
-    }
-
-    @Override
-    public boolean removeApplication(String id) {
-        if (id == null) return false;
-        ApplicationModel application = getApplicationById(id);
-        if (application == null) return false;
-
-        for (RoleModel role : application.getRoles()) {
-            application.removeRole(role);
-        }
-
-        ApplicationEntity applicationEntity = null;
-        Iterator<ApplicationEntity> it = realm.getApplications().iterator();
-        while (it.hasNext()) {
-            ApplicationEntity ae = it.next();
-            if (ae.getId().equals(id)) {
-                applicationEntity = ae;
-                it.remove();
-                break;
-            }
-        }
-        for (ApplicationEntity a : realm.getApplications()) {
-            if (a.getId().equals(id)) {
-                applicationEntity = a;
-            }
-        }
-        if (application == null) {
-            return false;
-        }
-        em.remove(applicationEntity);
-        em.createNamedQuery("deleteScopeMappingByClient").setParameter("client", applicationEntity).executeUpdate();
-        em.flush();
-
-        return true;
-    }
-
-    @Override
-    public ApplicationModel getApplicationById(String id) {
-        return session.realms().getApplicationById(id, this);
-    }
-
-    @Override
-    public ApplicationModel getApplicationByName(String name) {
-        return getApplicationNameMap().get(name);
-    }
-
-    @Override
-    public OAuthClientModel addOAuthClient(String name) {
-        return this.addOAuthClient(KeycloakModelUtils.generateId(), name);
-    }
-
-    @Override
-    public OAuthClientModel addOAuthClient(String id, String name) {
-        OAuthClientEntity data = new OAuthClientEntity();
-        data.setId(id);
-        data.setEnabled(true);
-        data.setName(name);
-        data.setRealm(realm);
-        em.persist(data);
-        em.flush();
-        final OAuthClientModel model = new OAuthClientAdapter(this, data, em);
-        em.flush();
-        session.getKeycloakSessionFactory().publish(new OAuthClientCreationEvent() {
-            @Override
-            public OAuthClientModel getCreatedOAuthClient() {
-                return model;
-            }
-
-            @Override
-            public ClientModel getCreatedClient() {
-                return model;
-            }
-        });
-        return model;
-    }
-
-    @Override
-    public boolean removeOAuthClient(String id) {
-        OAuthClientModel oauth = getOAuthClientById(id);
-        if (oauth == null) return false;
-        OAuthClientEntity client = em.getReference(OAuthClientEntity.class, oauth.getId());
-        em.createNamedQuery("deleteScopeMappingByClient").setParameter("client", client).executeUpdate();
-        em.remove(client);
-        return true;
-    }
-
-
-    @Override
-    public OAuthClientModel getOAuthClient(String name) {
-        TypedQuery<OAuthClientEntity> query = em.createNamedQuery("findOAuthClientByName", OAuthClientEntity.class);
-        query.setParameter("name", name);
-        query.setParameter("realm", realm);
-        List<OAuthClientEntity> entities = query.getResultList();
-        if (entities.size() == 0) return null;
-        return new OAuthClientAdapter(this, entities.get(0), em);
-    }
-
-    @Override
-    public OAuthClientModel getOAuthClientById(String id) {
-        return session.realms().getOAuthClientById(id, this);
-    }
-
-
-    @Override
-    public List<OAuthClientModel> getOAuthClients() {
-        TypedQuery<OAuthClientEntity> query = em.createNamedQuery("findOAuthClientByRealm", OAuthClientEntity.class);
-        query.setParameter("realm", realm);
-        List<OAuthClientEntity> entities = query.getResultList();
-        List<OAuthClientModel> list = new ArrayList<OAuthClientModel>();
-        for (OAuthClientEntity entity : entities) list.add(new OAuthClientAdapter(this, entity, em));
-        return list;
-    }
-
-    private static final String BROWSER_HEADER_PREFIX = "_browser_header.";
-
-    @Override
-    public Map<String, String> getBrowserSecurityHeaders() {
-        Map<String, String> attributes = getAttributes();
-        Map<String, String> headers = new HashMap<String, String>();
-        for (Map.Entry<String, String> entry : attributes.entrySet()) {
-            if (entry.getKey().startsWith(BROWSER_HEADER_PREFIX)) {
-                headers.put(entry.getKey().substring(BROWSER_HEADER_PREFIX.length()), entry.getValue());
-            }
-        }
-        return headers;
-    }
-
-    @Override
-    public void setBrowserSecurityHeaders(Map<String, String> headers) {
-        for (Map.Entry<String, String> entry : headers.entrySet()) {
-            setAttribute(BROWSER_HEADER_PREFIX + entry.getKey(), entry.getValue());
-        }
-    }
-
-    @Override
-    public Map<String, String> getSmtpConfig() {
-        return realm.getSmtpConfig();
-    }
-
-    @Override
-    public void setSmtpConfig(Map<String, String> smtpConfig) {
-        realm.setSmtpConfig(smtpConfig);
-        em.flush();
-    }
-
-    @Override
-    public List<UserFederationProviderModel> getUserFederationProviders() {
-        List<UserFederationProviderEntity> entities = realm.getUserFederationProviders();
-        List<UserFederationProviderEntity> copy = new ArrayList<UserFederationProviderEntity>();
-        for (UserFederationProviderEntity entity : entities) {
-            copy.add(entity);
-
-        }
-        Collections.sort(copy, new Comparator<UserFederationProviderEntity>() {
-
-            @Override
-            public int compare(UserFederationProviderEntity o1, UserFederationProviderEntity o2) {
-                return o1.getPriority() - o2.getPriority();
-            }
-
-        });
-        List<UserFederationProviderModel> result = new ArrayList<UserFederationProviderModel>();
-        for (UserFederationProviderEntity entity : copy) {
-            result.add(new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(),
-                    entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync()));
-        }
-
-        return result;
-    }
-
-    @Override
-    public UserFederationProviderModel addUserFederationProvider(String providerName, Map<String, String> config, int priority, String displayName, int fullSyncPeriod, int changedSyncPeriod, int lastSync) {
-        String id = KeycloakModelUtils.generateId();
-        UserFederationProviderEntity entity = new UserFederationProviderEntity();
-        entity.setId(id);
-        entity.setRealm(realm);
-        entity.setProviderName(providerName);
-        entity.setConfig(config);
-        entity.setPriority(priority);
-        if (displayName == null) {
-            displayName = id;
-        }
-        entity.setDisplayName(displayName);
-        entity.setFullSyncPeriod(fullSyncPeriod);
-        entity.setChangedSyncPeriod(changedSyncPeriod);
-        entity.setLastSync(lastSync);
-        em.persist(entity);
-        realm.getUserFederationProviders().add(entity);
-        em.flush();
-        return new UserFederationProviderModel(entity.getId(), providerName, config, priority, displayName, fullSyncPeriod, changedSyncPeriod, lastSync);
-    }
-
-    @Override
-    public void removeUserFederationProvider(UserFederationProviderModel provider) {
-        Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
-        while (it.hasNext()) {
-            UserFederationProviderEntity entity = it.next();
-            if (entity.getId().equals(provider.getId())) {
-                session.users().preRemove(this, provider);
-                it.remove();
-                em.remove(entity);
-                return;
-            }
-        }
-    }
-    @Override
-    public void updateUserFederationProvider(UserFederationProviderModel model) {
-        Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
-        while (it.hasNext()) {
-            UserFederationProviderEntity entity = it.next();
-            if (entity.getId().equals(model.getId())) {
-                String displayName = model.getDisplayName();
-                if (displayName != null) {
-                    entity.setDisplayName(model.getDisplayName());
-                }
-                entity.setConfig(model.getConfig());
-                entity.setPriority(model.getPriority());
-                entity.setProviderName(model.getProviderName());
-                entity.setPriority(model.getPriority());
-                entity.setFullSyncPeriod(model.getFullSyncPeriod());
-                entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
-                entity.setLastSync(model.getLastSync());
-                break;
-            }
-        }
-    }
-
-    @Override
-    public void setUserFederationProviders(List<UserFederationProviderModel> providers) {
-
-        Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
-        while (it.hasNext()) {
-            UserFederationProviderEntity entity = it.next();
-            boolean found = false;
-            for (UserFederationProviderModel model : providers) {
-                if (entity.getId().equals(model.getId())) {
-                    entity.setConfig(model.getConfig());
-                    entity.setPriority(model.getPriority());
-                    entity.setProviderName(model.getProviderName());
-                    entity.setPriority(model.getPriority());
-                    String displayName = model.getDisplayName();
-                    if (displayName != null) {
-                        entity.setDisplayName(model.getDisplayName());
-                    }
-                    entity.setFullSyncPeriod(model.getFullSyncPeriod());
-                    entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
-                    entity.setLastSync(model.getLastSync());
-                    found = true;
-                    break;
-                }
-
-            }
-            if (found) continue;
-            session.users().preRemove(this, new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(),
-                    entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync()));
-            it.remove();
-            em.remove(entity);
-        }
-
-        List<UserFederationProviderModel> add = new LinkedList<UserFederationProviderModel>();
-        for (UserFederationProviderModel model : providers) {
-            boolean found = false;
-            for (UserFederationProviderEntity entity : realm.getUserFederationProviders()) {
-                if (entity.getId().equals(model.getId())) {
-                    found = true;
-                    break;
-                }
-            }
-            if (!found) add.add(model);
-        }
-
-        for (UserFederationProviderModel model : add) {
-            UserFederationProviderEntity entity = new UserFederationProviderEntity();
-            if (model.getId() != null) entity.setId(model.getId());
-            else entity.setId(KeycloakModelUtils.generateId());
-            entity.setConfig(model.getConfig());
-            entity.setPriority(model.getPriority());
-            entity.setProviderName(model.getProviderName());
-            entity.setPriority(model.getPriority());
-            String displayName = model.getDisplayName();
-            if (displayName == null) {
-                displayName = entity.getId();
-            }
-            entity.setDisplayName(displayName);
-            entity.setFullSyncPeriod(model.getFullSyncPeriod());
-            entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
-            entity.setLastSync(model.getLastSync());
-            em.persist(entity);
-            realm.getUserFederationProviders().add(entity);
-
-        }
-    }
-
-    @Override
-    public RoleModel getRole(String name) {
-        TypedQuery<RoleEntity> query = em.createNamedQuery("getRealmRoleByName", RoleEntity.class);
-        query.setParameter("name", name);
-        query.setParameter("realm", realm);
-        List<RoleEntity> roles = query.getResultList();
-        if (roles.size() == 0) return null;
-        return new RoleAdapter(this, em, roles.get(0));
-    }
-
-    @Override
-    public RoleModel addRole(String name) {
-        return this.addRole(KeycloakModelUtils.generateId(), name);
-    }
-
-    @Override
-    public RoleModel addRole(String id, String name) {
-        RoleEntity entity = new RoleEntity();
-        entity.setId(id);
-        entity.setName(name);
-        entity.setRealm(realm);
-        entity.setRealmId(realm.getId());
-        realm.getRoles().add(entity);
-        em.persist(entity);
-        em.flush();
-        return new RoleAdapter(this, em, entity);
-    }
-
-    @Override
-    public boolean removeRole(RoleModel role) {
-        if (role == null) {
-            return false;
-        }
-        if (!role.getContainer().equals(this)) return false;
-        session.users().preRemove(this, role);
-        RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em);
-        realm.getRoles().remove(roleEntity);
-        realm.getDefaultRoles().remove(roleEntity);
-
-        em.createNativeQuery("delete from COMPOSITE_ROLE where CHILD_ROLE = :role").setParameter("role", roleEntity).executeUpdate();
-        em.createNamedQuery("deleteScopeMappingByRole").setParameter("role", roleEntity).executeUpdate();
-
-        em.remove(roleEntity);
-
-        return true;
-    }
-
-    @Override
-    public Set<RoleModel> getRoles() {
-        Set<RoleModel> list = new HashSet<RoleModel>();
-        Collection<RoleEntity> roles = realm.getRoles();
-        if (roles == null) return list;
-        for (RoleEntity entity : roles) {
-            list.add(new RoleAdapter(this, em, entity));
-        }
-        return list;
-    }
-
-    @Override
-    public RoleModel getRoleById(String id) {
-        return session.realms().getRoleById(id, this);
-    }
-
-    @Override
-    public boolean removeRoleById(String id) {
-        RoleModel role = getRoleById(id);
-        if (role == null) return false;
-        return role.getContainer().removeRole(role);
-    }
-
-    @Override
-    public PasswordPolicy getPasswordPolicy() {
-        if (passwordPolicy == null) {
-            passwordPolicy = new PasswordPolicy(realm.getPasswordPolicy());
-        }
-        return passwordPolicy;
-    }
-
-    @Override
-    public void setPasswordPolicy(PasswordPolicy policy) {
-        this.passwordPolicy = policy;
-        realm.setPasswordPolicy(policy.toString());
-        em.flush();
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || !(o instanceof RealmModel)) return false;
-
-        RealmModel that = (RealmModel) o;
-        return that.getId().equals(getId());
-    }
-
-    @Override
-    public int hashCode() {
-        return getId().hashCode();
-    }
-
-    @Override
-    public String getLoginTheme() {
-        return realm.getLoginTheme();
-    }
-
-    @Override
-    public void setLoginTheme(String name) {
-        realm.setLoginTheme(name);
-        em.flush();
-    }
-
-    @Override
-    public String getAccountTheme() {
-        return realm.getAccountTheme();
-    }
-
-    @Override
-    public void setAccountTheme(String name) {
-        realm.setAccountTheme(name);
-        em.flush();
-    }
-
-    @Override
-    public String getAdminTheme() {
-        return realm.getAdminTheme();
-    }
-
-    @Override
-    public void setAdminTheme(String name) {
-        realm.setAdminTheme(name);
-        em.flush();
-    }
-
-    @Override
-    public String getEmailTheme() {
-        return realm.getEmailTheme();
-    }
-
-    @Override
-    public void setEmailTheme(String name) {
-        realm.setEmailTheme(name);
-        em.flush();
-    }
-
-    @Override
-    public boolean isEventsEnabled() {
-        return realm.isEventsEnabled();
-    }
-
-    @Override
-    public void setEventsEnabled(boolean enabled) {
-        realm.setEventsEnabled(enabled);
-        em.flush();
-    }
-
-    @Override
-    public long getEventsExpiration() {
-        return realm.getEventsExpiration();
-    }
-
-    @Override
-    public void setEventsExpiration(long expiration) {
-        realm.setEventsExpiration(expiration);
-        em.flush();
-    }
-
-    @Override
-    public Set<String> getEventsListeners() {
-        return realm.getEventsListeners();
-    }
-
-    @Override
-    public void setEventsListeners(Set<String> listeners) {
-        realm.setEventsListeners(listeners);
-        em.flush();
-    }
-    
-    @Override
-    public Set<String> getEnabledEventTypes() {
-        return realm.getEnabledEventTypes();
-    }
-
-    @Override
-    public void setEnabledEventTypes(Set<String> enabledEventTypes) {
-        realm.setEnabledEventTypes(enabledEventTypes);
-        em.flush();
-    }
-
-    @Override
-    public ApplicationModel getMasterAdminApp() {
-        return new ApplicationAdapter(this, em, session, realm.getMasterAdminApp());
-    }
-
-    @Override
-    public void setMasterAdminApp(ApplicationModel app) {
-        ApplicationEntity appEntity = app!=null ? em.getReference(ApplicationEntity.class, app.getId()) : null;
-        realm.setMasterAdminApp(appEntity);
-        em.flush();
-    }
-
-    @Override
-    public List<IdentityProviderModel> getIdentityProviders() {
-        List<IdentityProviderModel> identityProviders = new ArrayList<IdentityProviderModel>();
-
-        for (IdentityProviderEntity entity: realm.getIdentityProviders()) {
-            IdentityProviderModel identityProviderModel = new IdentityProviderModel();
-
-            identityProviderModel.setProviderId(entity.getProviderId());
-            identityProviderModel.setAlias(entity.getAlias());
-            identityProviderModel.setInternalId(entity.getInternalId());
-            identityProviderModel.setConfig(entity.getConfig());
-            identityProviderModel.setEnabled(entity.isEnabled());
-            identityProviderModel.setUpdateProfileFirstLogin(entity.isUpdateProfileFirstLogin());
-            identityProviderModel.setAuthenticateByDefault(entity.isAuthenticateByDefault());
-            identityProviderModel.setStoreToken(entity.isStoreToken());
-
-            identityProviders.add(identityProviderModel);
-        }
-
-        return identityProviders;
-    }
-
-    @Override
-    public IdentityProviderModel getIdentityProviderByAlias(String alias) {
-        for (IdentityProviderModel identityProviderModel : getIdentityProviders()) {
-            if (identityProviderModel.getAlias().equals(alias)) {
-                return identityProviderModel;
-            }
-        }
-
-        return null;
-    }
-
-    @Override
-    public void addIdentityProvider(IdentityProviderModel identityProvider) {
-        IdentityProviderEntity entity = new IdentityProviderEntity();
-
-        entity.setInternalId(KeycloakModelUtils.generateId());
-        entity.setAlias(identityProvider.getAlias());
-        entity.setProviderId(identityProvider.getProviderId());
-        entity.setEnabled(identityProvider.isEnabled());
-        entity.setStoreToken(identityProvider.isStoreToken());
-        entity.setUpdateProfileFirstLogin(identityProvider.isUpdateProfileFirstLogin());
-        entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
-        entity.setConfig(identityProvider.getConfig());
-
-        realm.addIdentityProvider(entity);
-
-        em.persist(entity);
-        em.flush();
-    }
-
-    @Override
-    public void removeIdentityProviderByAlias(String alias) {
-        for (IdentityProviderEntity entity : realm.getIdentityProviders()) {
-            if (entity.getAlias().equals(alias)) {
-                em.remove(entity);
-                em.flush();
-            }
-        }
-    }
-
-    @Override
-    public void updateIdentityProvider(IdentityProviderModel identityProvider) {
-        for (IdentityProviderEntity entity : this.realm.getIdentityProviders()) {
-            if (entity.getInternalId().equals(identityProvider.getInternalId())) {
-                entity.setAlias(identityProvider.getAlias());
-                entity.setEnabled(identityProvider.isEnabled());
-                entity.setUpdateProfileFirstLogin(identityProvider.isUpdateProfileFirstLogin());
-                entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
-                entity.setStoreToken(identityProvider.isStoreToken());
-                entity.setConfig(identityProvider.getConfig());
-            }
-        }
-
-        em.flush();
-    }
-
-    @Override
-    public boolean isIdentityFederationEnabled() {
-        return !this.realm.getIdentityProviders().isEmpty();
-    }
-
-    @Override
-    public boolean isInternationalizationEnabled() {
-        return realm.isInternationalizationEnabled();
-    }
-
-    @Override
-    public void setInternationalizationEnabled(boolean enabled) {
-        realm.setInternationalizationEnabled(enabled);
-        em.flush();
-    }
-
-    @Override
-    public Set<String> getSupportedLocales() {
-        return realm.getSupportedLocales();
-    }
-
-    @Override
-    public void setSupportedLocales(Set<String> locales) {
-        realm.setSupportedLocales(locales);
-        em.flush();
-    }
-
-    @Override
-    public String getDefaultLocale() {
-        return realm.getDefaultLocale();
-    }
-
-    @Override
-    public void setDefaultLocale(String locale) {
-        realm.setDefaultLocale(locale);
-        em.flush();
-    }
-
-    @Override
-    public Set<IdentityProviderMapperModel> getIdentityProviderMappers() {
-        Set<IdentityProviderMapperModel> mappings = new HashSet<IdentityProviderMapperModel>();
-        for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) {
-            IdentityProviderMapperModel mapping = new IdentityProviderMapperModel();
-            mapping.setId(entity.getId());
-            mapping.setName(entity.getName());
-            mapping.setIdentityProviderAlias(entity.getIdentityProviderAlias());
-            mapping.setIdentityProviderMapper(entity.getIdentityProviderMapper());
-            Map<String, String> config = new HashMap<String, String>();
-            if (entity.getConfig() != null) {
-                config.putAll(entity.getConfig());
-            }
-            mapping.setConfig(config);
-            mappings.add(mapping);
-        }
-        return mappings;
-    }
-
-    @Override
-    public Set<IdentityProviderMapperModel> getIdentityProviderMappersByAlias(String brokerAlias) {
-        Set<IdentityProviderMapperModel> mappings = new HashSet<IdentityProviderMapperModel>();
-        for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) {
-            if (!entity.getIdentityProviderAlias().equals(brokerAlias)) {
-                continue;
-            }
-            IdentityProviderMapperModel mapping = new IdentityProviderMapperModel();
-            mapping.setId(entity.getId());
-            mapping.setName(entity.getName());
-            mapping.setIdentityProviderAlias(entity.getIdentityProviderAlias());
-            mapping.setIdentityProviderMapper(entity.getIdentityProviderMapper());
-            Map<String, String> config = new HashMap<String, String>();
-            if (entity.getConfig() != null) {
-                config.putAll(entity.getConfig());
-            }
-            mapping.setConfig(config);
-            mappings.add(mapping);
-        }
-        return mappings;
-    }
-
-    @Override
-    public IdentityProviderMapperModel addIdentityProviderMapper(IdentityProviderMapperModel model) {
-        if (getIdentityProviderMapperByName(model.getIdentityProviderAlias(), model.getIdentityProviderMapper()) != null) {
-            throw new RuntimeException("protocol mapper name must be unique per protocol");
-        }
-        String id = KeycloakModelUtils.generateId();
-        IdentityProviderMapperEntity entity = new IdentityProviderMapperEntity();
-        entity.setId(id);
-        entity.setName(model.getName());
-        entity.setIdentityProviderAlias(model.getIdentityProviderAlias());
-        entity.setIdentityProviderMapper(model.getIdentityProviderMapper());
-        entity.setRealm(this.realm);
-        entity.setConfig(model.getConfig());
-
-        em.persist(entity);
-        this.realm.getIdentityProviderMappers().add(entity);
-        return entityToModel(entity);
-    }
-
-    protected IdentityProviderMapperEntity getIdentityProviderMapperEntity(String id) {
-        for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) {
-            if (entity.getId().equals(id)) {
-                return entity;
-            }
-        }
-        return null;
-
-    }
-
-    protected IdentityProviderMapperEntity getIdentityProviderMapperEntityByName(String alias, String name) {
-        for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) {
-            if (entity.getIdentityProviderAlias().equals(alias) && entity.getName().equals(name)) {
-                return entity;
-            }
-        }
-        return null;
-
-    }
-
-    @Override
-    public void removeIdentityProviderMapper(IdentityProviderMapperModel mapping) {
-        IdentityProviderMapperEntity toDelete = getIdentityProviderMapperEntity(mapping.getId());
-        if (toDelete != null) {
-            this.realm.getIdentityProviderMappers().remove(toDelete);
-            em.remove(toDelete);
-        }
-
-    }
-
-    @Override
-    public void updateIdentityProviderMapper(IdentityProviderMapperModel mapping) {
-        IdentityProviderMapperEntity entity = getIdentityProviderMapperEntity(mapping.getId());
-        entity.setIdentityProviderAlias(mapping.getIdentityProviderAlias());
-        entity.setIdentityProviderMapper(mapping.getIdentityProviderMapper());
-        if (entity.getConfig() == null) {
-            entity.setConfig(mapping.getConfig());
-        } else {
-            entity.getConfig().clear();
-            entity.getConfig().putAll(mapping.getConfig());
-        }
-        em.flush();
-
-    }
-
-    @Override
-    public IdentityProviderMapperModel getIdentityProviderMapperById(String id) {
-        IdentityProviderMapperEntity entity = getIdentityProviderMapperEntity(id);
-        if (entity == null) return null;
-        return entityToModel(entity);
-    }
-
-    @Override
-    public IdentityProviderMapperModel getIdentityProviderMapperByName(String alias, String name) {
-        IdentityProviderMapperEntity entity = getIdentityProviderMapperEntityByName(alias, name);
-        if (entity == null) return null;
-        return entityToModel(entity);
-    }
-
-    protected IdentityProviderMapperModel entityToModel(IdentityProviderMapperEntity entity) {
-        IdentityProviderMapperModel mapping = new IdentityProviderMapperModel();
-        mapping.setId(entity.getId());
-        mapping.setName(entity.getName());
-        mapping.setIdentityProviderAlias(entity.getIdentityProviderAlias());
-        mapping.setIdentityProviderMapper(entity.getIdentityProviderMapper());
-        Map<String, String> config = new HashMap<String, String>();
-        if (entity.getConfig() != null) config.putAll(entity.getConfig());
-        mapping.setConfig(config);
-        return mapping;
-    }
+package org.keycloak.models.jpa;
+
+import org.keycloak.enums.SslRequired;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.IdentityProviderMapperModel;
+import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.PasswordPolicy;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RequiredCredentialModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.models.jpa.entities.ClientEntity;
+import org.keycloak.models.jpa.entities.IdentityProviderEntity;
+import org.keycloak.models.jpa.entities.IdentityProviderMapperEntity;
+import org.keycloak.models.jpa.entities.RealmAttributeEntity;
+import org.keycloak.models.jpa.entities.RealmEntity;
+import org.keycloak.models.jpa.entities.RequiredCredentialEntity;
+import org.keycloak.models.jpa.entities.RoleEntity;
+import org.keycloak.models.jpa.entities.UserFederationProviderEntity;
+import org.keycloak.models.utils.KeycloakModelUtils;
+
+import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+import java.security.Key;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RealmAdapter implements RealmModel {
+    protected RealmEntity realm;
+    protected EntityManager em;
+    protected volatile transient PublicKey publicKey;
+    protected volatile transient PrivateKey privateKey;
+    protected volatile transient X509Certificate certificate;
+    protected volatile transient Key codeSecretKey;
+    protected KeycloakSession session;
+    private PasswordPolicy passwordPolicy;
+
+    public RealmAdapter(KeycloakSession session, EntityManager em, RealmEntity realm) {
+        this.session = session;
+        this.em = em;
+        this.realm = realm;
+    }
+
+    public RealmEntity getEntity() {
+        return realm;
+    }
+
+    @Override
+    public String getId() {
+        return realm.getId();
+    }
+
+    @Override
+    public String getName() {
+        return realm.getName();
+    }
+
+    @Override
+    public void setName(String name) {
+        realm.setName(name);
+        em.flush();
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return realm.isEnabled();
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        realm.setEnabled(enabled);
+        em.flush();
+    }
+
+    @Override
+    public SslRequired getSslRequired() {
+        return realm.getSslRequired() != null ? SslRequired.valueOf(realm.getSslRequired()) : null;
+    }
+
+    @Override
+    public void setSslRequired(SslRequired sslRequired) {
+        realm.setSslRequired(sslRequired.name());
+        em.flush();
+    }
+
+    @Override
+    public boolean isPasswordCredentialGrantAllowed() {
+        return realm.isPasswordCredentialGrantAllowed();
+    }
+
+    @Override
+    public void setPasswordCredentialGrantAllowed(boolean passwordCredentialGrantAllowed) {
+        realm.setPasswordCredentialGrantAllowed(passwordCredentialGrantAllowed);
+        em.flush();
+    }
+
+    @Override
+    public boolean isRegistrationAllowed() {
+        return realm.isRegistrationAllowed();
+    }
+
+    @Override
+    public void setRegistrationAllowed(boolean registrationAllowed) {
+        realm.setRegistrationAllowed(registrationAllowed);
+        em.flush();
+    }
+
+    @Override
+    public boolean isRegistrationEmailAsUsername() {
+        return realm.isRegistrationEmailAsUsername();
+    }
+
+    @Override
+    public void setRegistrationEmailAsUsername(boolean registrationEmailAsUsername) {
+        realm.setRegistrationEmailAsUsername(registrationEmailAsUsername);
+        em.flush();
+    }
+
+    @Override
+    public boolean isRememberMe() {
+        return realm.isRememberMe();
+    }
+
+    @Override
+    public void setRememberMe(boolean rememberMe) {
+        realm.setRememberMe(rememberMe);
+        em.flush();
+    }
+
+    public void setAttribute(String name, String value) {
+        for (RealmAttributeEntity attr : realm.getAttributes()) {
+            if (attr.getName().equals(name)) {
+                attr.setValue(value);
+                return;
+            }
+        }
+        RealmAttributeEntity attr = new RealmAttributeEntity();
+        attr.setName(name);
+        attr.setValue(value);
+        attr.setRealm(realm);
+        em.persist(attr);
+        realm.getAttributes().add(attr);
+    }
+
+    public void setAttribute(String name, Boolean value) {
+        setAttribute(name, value.toString());
+    }
+
+    public void setAttribute(String name, Integer value) {
+        setAttribute(name, value.toString());
+    }
+
+    public void setAttribute(String name, Long value) {
+        setAttribute(name, value.toString());
+    }
+
+    public void removeAttribute(String name) {
+        Iterator<RealmAttributeEntity> it = realm.getAttributes().iterator();
+        while (it.hasNext()) {
+            RealmAttributeEntity attr = it.next();
+            if (attr.getName().equals(name)) {
+                it.remove();
+                em.remove(attr);
+            }
+        }
+    }
+
+    public String getAttribute(String name) {
+        for (RealmAttributeEntity attr : realm.getAttributes()) {
+            if (attr.getName().equals(name)) {
+                return attr.getValue();
+            }
+        }
+        return null;
+    }
+
+    public Integer getAttribute(String name, Integer defaultValue) {
+        String v = getAttribute(name);
+        return v != null ? Integer.parseInt(v) : defaultValue;
+
+    }
+
+    public Long getAttribute(String name, Long defaultValue) {
+        String v = getAttribute(name);
+        return v != null ? Long.parseLong(v) : defaultValue;
+
+    }
+
+    public Boolean getAttribute(String name, Boolean defaultValue) {
+        String v = getAttribute(name);
+        return v != null ? Boolean.parseBoolean(v) : defaultValue;
+
+    }
+
+    public Map<String, String> getAttributes() {
+        // should always return a copy
+        Map<String, String> result = new HashMap<String, String>();
+        for (RealmAttributeEntity attr : realm.getAttributes()) {
+            result.put(attr.getName(), attr.getValue());
+        }
+        return result;
+    }
+    @Override
+    public boolean isBruteForceProtected() {
+        return getAttribute("bruteForceProtected", false);
+    }
+
+    @Override
+    public void setBruteForceProtected(boolean value) {
+        setAttribute("bruteForceProtected", value);
+    }
+
+    @Override
+    public int getMaxFailureWaitSeconds() {
+        return getAttribute("maxFailureWaitSeconds", 0);
+    }
+
+    @Override
+    public void setMaxFailureWaitSeconds(int val) {
+        setAttribute("maxFailureWaitSeconds", val);
+    }
+
+    @Override
+    public int getWaitIncrementSeconds() {
+        return getAttribute("waitIncrementSeconds", 0);
+    }
+
+    @Override
+    public void setWaitIncrementSeconds(int val) {
+        setAttribute("waitIncrementSeconds", val);
+    }
+
+    @Override
+    public long getQuickLoginCheckMilliSeconds() {
+        return getAttribute("quickLoginCheckMilliSeconds", 0l);
+    }
+
+    @Override
+    public void setQuickLoginCheckMilliSeconds(long val) {
+        setAttribute("quickLoginCheckMilliSeconds", val);
+    }
+
+    @Override
+    public int getMinimumQuickLoginWaitSeconds() {
+        return getAttribute("minimumQuickLoginWaitSeconds", 0);
+    }
+
+    @Override
+    public void setMinimumQuickLoginWaitSeconds(int val) {
+        setAttribute("minimumQuickLoginWaitSeconds", val);
+    }
+
+    @Override
+    public int getMaxDeltaTimeSeconds() {
+        return getAttribute("maxDeltaTimeSeconds", 0);
+    }
+
+    @Override
+    public void setMaxDeltaTimeSeconds(int val) {
+        setAttribute("maxDeltaTimeSeconds", val);
+    }
+
+    @Override
+    public int getFailureFactor() {
+        return getAttribute("failureFactor", 0);
+    }
+
+    @Override
+    public void setFailureFactor(int failureFactor) {
+        setAttribute("failureFactor", failureFactor);
+    }
+
+    @Override
+    public boolean isVerifyEmail() {
+        return realm.isVerifyEmail();
+    }
+
+    @Override
+    public void setVerifyEmail(boolean verifyEmail) {
+        realm.setVerifyEmail(verifyEmail);
+        em.flush();
+    }
+
+    @Override
+    public boolean isResetPasswordAllowed() {
+        return realm.isResetPasswordAllowed();
+    }
+
+    @Override
+    public void setResetPasswordAllowed(boolean resetPasswordAllowed) {
+        realm.setResetPasswordAllowed(resetPasswordAllowed);
+        em.flush();
+    }
+
+    @Override
+    public int getNotBefore() {
+        return realm.getNotBefore();
+    }
+
+    @Override
+    public void setNotBefore(int notBefore) {
+        realm.setNotBefore(notBefore);
+    }
+
+    @Override
+    public int getAccessTokenLifespan() {
+        return realm.getAccessTokenLifespan();
+    }
+
+    @Override
+    public void setAccessTokenLifespan(int tokenLifespan) {
+        realm.setAccessTokenLifespan(tokenLifespan);
+        em.flush();
+    }
+
+    @Override
+    public int getSsoSessionIdleTimeout() {
+        return realm.getSsoSessionIdleTimeout();
+    }
+
+    @Override
+    public void setSsoSessionIdleTimeout(int seconds) {
+        realm.setSsoSessionIdleTimeout(seconds);
+    }
+
+    @Override
+    public int getSsoSessionMaxLifespan() {
+        return realm.getSsoSessionMaxLifespan();
+    }
+
+    @Override
+    public void setSsoSessionMaxLifespan(int seconds) {
+        realm.setSsoSessionMaxLifespan(seconds);
+    }
+
+    @Override
+    public int getAccessCodeLifespan() {
+        return realm.getAccessCodeLifespan();
+    }
+
+    @Override
+    public void setAccessCodeLifespan(int accessCodeLifespan) {
+        realm.setAccessCodeLifespan(accessCodeLifespan);
+        em.flush();
+    }
+
+    @Override
+    public int getAccessCodeLifespanUserAction() {
+        return realm.getAccessCodeLifespanUserAction();
+    }
+
+    @Override
+    public void setAccessCodeLifespanUserAction(int accessCodeLifespanUserAction) {
+        realm.setAccessCodeLifespanUserAction(accessCodeLifespanUserAction);
+        em.flush();
+    }
+
+    @Override
+    public int getAccessCodeLifespanLogin() {
+        return realm.getAccessCodeLifespanLogin();
+    }
+
+    @Override
+    public void setAccessCodeLifespanLogin(int accessCodeLifespanLogin) {
+        realm.setAccessCodeLifespanLogin(accessCodeLifespanLogin);
+        em.flush();
+    }
+
+    @Override
+    public String getPublicKeyPem() {
+        return realm.getPublicKeyPem();
+    }
+
+    @Override
+    public void setPublicKeyPem(String publicKeyPem) {
+        realm.setPublicKeyPem(publicKeyPem);
+        em.flush();
+    }
+
+    @Override
+    public X509Certificate getCertificate() {
+        if (certificate != null) return certificate;
+        certificate = KeycloakModelUtils.getCertificate(getCertificatePem());
+        return certificate;
+    }
+
+    @Override
+    public void setCertificate(X509Certificate certificate) {
+        this.certificate = certificate;
+        String certificatePem = KeycloakModelUtils.getPemFromCertificate(certificate);
+        setCertificatePem(certificatePem);
+
+    }
+
+    @Override
+    public String getCertificatePem() {
+        return realm.getCertificatePem();
+    }
+
+    @Override
+    public void setCertificatePem(String certificate) {
+        realm.setCertificatePem(certificate);
+
+    }
+
+    @Override
+    public String getPrivateKeyPem() {
+        return realm.getPrivateKeyPem();
+    }
+
+    @Override
+    public void setPrivateKeyPem(String privateKeyPem) {
+        realm.setPrivateKeyPem(privateKeyPem);
+        em.flush();
+    }
+
+    @Override
+    public PublicKey getPublicKey() {
+        if (publicKey != null) return publicKey;
+        publicKey = KeycloakModelUtils.getPublicKey(getPublicKeyPem());
+        return publicKey;
+    }
+
+    @Override
+    public void setPublicKey(PublicKey publicKey) {
+        this.publicKey = publicKey;
+        String publicKeyPem = KeycloakModelUtils.getPemFromKey(publicKey);
+        setPublicKeyPem(publicKeyPem);
+    }
+
+    @Override
+    public PrivateKey getPrivateKey() {
+        if (privateKey != null) return privateKey;
+        privateKey = KeycloakModelUtils.getPrivateKey(getPrivateKeyPem());
+        return privateKey;
+    }
+
+    @Override
+    public void setPrivateKey(PrivateKey privateKey) {
+        this.privateKey = privateKey;
+        String privateKeyPem = KeycloakModelUtils.getPemFromKey(privateKey);
+        setPrivateKeyPem(privateKeyPem);
+    }
+
+    @Override
+    public String getCodeSecret() {
+        return realm.getCodeSecret();
+    }
+
+    @Override
+    public Key getCodeSecretKey() {
+        if (codeSecretKey == null) {
+            codeSecretKey = KeycloakModelUtils.getSecretKey(getCodeSecret());
+        }
+        return codeSecretKey;
+    }
+
+    @Override
+    public void setCodeSecret(String codeSecret) {
+        realm.setCodeSecret(codeSecret);
+    }
+
+    protected RequiredCredentialModel initRequiredCredentialModel(String type) {
+        RequiredCredentialModel model = RequiredCredentialModel.BUILT_IN.get(type);
+        if (model == null) {
+            throw new RuntimeException("Unknown credential type " + type);
+        }
+        return model;
+    }
+
+    @Override
+    public void addRequiredCredential(String type) {
+        RequiredCredentialModel model = initRequiredCredentialModel(type);
+        addRequiredCredential(model);
+        em.flush();
+    }
+
+    public void addRequiredCredential(RequiredCredentialModel model) {
+        RequiredCredentialEntity entity = new RequiredCredentialEntity();
+        entity.setRealm(realm);
+        entity.setInput(model.isInput());
+        entity.setSecret(model.isSecret());
+        entity.setType(model.getType());
+        entity.setFormLabel(model.getFormLabel());
+        em.persist(entity);
+        realm.getRequiredCredentials().add(entity);
+        em.flush();
+    }
+
+    @Override
+    public void updateRequiredCredentials(Set<String> creds) {
+        Collection<RequiredCredentialEntity> relationships = realm.getRequiredCredentials();
+        if (relationships == null) relationships = new ArrayList<RequiredCredentialEntity>();
+
+        Set<String> already = new HashSet<String>();
+        List<RequiredCredentialEntity> remove = new ArrayList<RequiredCredentialEntity>();
+        for (RequiredCredentialEntity rel : relationships) {
+            if (!creds.contains(rel.getType())) {
+                remove.add(rel);
+            } else {
+                already.add(rel.getType());
+            }
+        }
+        for (RequiredCredentialEntity entity : remove) {
+            relationships.remove(entity);
+            em.remove(entity);
+        }
+        for (String cred : creds) {
+            if (!already.contains(cred)) {
+                addRequiredCredential(cred);
+            }
+        }
+        em.flush();
+    }
+
+
+    @Override
+    public List<RequiredCredentialModel> getRequiredCredentials() {
+        List<RequiredCredentialModel> requiredCredentialModels = new ArrayList<RequiredCredentialModel>();
+        Collection<RequiredCredentialEntity> entities = realm.getRequiredCredentials();
+        if (entities == null) return requiredCredentialModels;
+        for (RequiredCredentialEntity entity : entities) {
+            RequiredCredentialModel model = new RequiredCredentialModel();
+            model.setFormLabel(entity.getFormLabel());
+            model.setType(entity.getType());
+            model.setSecret(entity.isSecret());
+            model.setInput(entity.isInput());
+            requiredCredentialModels.add(model);
+        }
+        return requiredCredentialModels;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+
+    @Override
+    public List<String> getDefaultRoles() {
+        Collection<RoleEntity> entities = realm.getDefaultRoles();
+        List<String> roles = new ArrayList<String>();
+        if (entities == null) return roles;
+        for (RoleEntity entity : entities) {
+            roles.add(entity.getName());
+        }
+        return roles;
+    }
+
+    @Override
+    public void addDefaultRole(String name) {
+        RoleModel role = getRole(name);
+        if (role == null) {
+            role = addRole(name);
+        }
+        Collection<RoleEntity> entities = realm.getDefaultRoles();
+        for (RoleEntity entity : entities) {
+            if (entity.getId().equals(role.getId())) {
+                return;
+            }
+        }
+        RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em);
+        entities.add(roleEntity);
+        em.flush();
+    }
+
+    public static boolean contains(String str, String[] array) {
+        for (String s : array) {
+            if (str.equals(s)) return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void updateDefaultRoles(String[] defaultRoles) {
+        Collection<RoleEntity> entities = realm.getDefaultRoles();
+        Set<String> already = new HashSet<String>();
+        List<RoleEntity> remove = new ArrayList<RoleEntity>();
+        for (RoleEntity rel : entities) {
+            if (!contains(rel.getName(), defaultRoles)) {
+                remove.add(rel);
+            } else {
+                already.add(rel.getName());
+            }
+        }
+        for (RoleEntity entity : remove) {
+            entities.remove(entity);
+        }
+        em.flush();
+        for (String roleName : defaultRoles) {
+            if (!already.contains(roleName)) {
+                addDefaultRole(roleName);
+            }
+        }
+        em.flush();
+    }
+
+    @Override
+    public Map<String, ClientModel> getClientNameMap() {
+        Map<String, ClientModel> map = new HashMap<String, ClientModel>();
+        for (ClientModel app : getClients()) {
+            map.put(app.getClientId(), app);
+        }
+        return map;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public List<ClientModel> getClients() {
+        List<ClientModel> list = new ArrayList<ClientModel>();
+        if (realm.getApplications() == null) return list;
+        for (ClientEntity entity : realm.getApplications()) {
+            list.add(new ClientAdapter(this, em, session, entity));
+        }
+        return list;
+    }
+
+    @Override
+    public ClientModel addClient(String name) {
+        return this.addClient(KeycloakModelUtils.generateId(), name);
+    }
+
+    @Override
+    public ClientModel addClient(String id, String clientId) {
+        ClientEntity applicationData = new ClientEntity();
+        applicationData.setId(id);
+        applicationData.setClientId(clientId);
+        applicationData.setEnabled(true);
+        applicationData.setRealm(realm);
+        realm.getApplications().add(applicationData);
+        em.persist(applicationData);
+        em.flush();
+        final ClientModel resource = new ClientAdapter(this, em, session, applicationData);
+        em.flush();
+        session.getKeycloakSessionFactory().publish(new ClientCreationEvent() {
+            @Override
+            public ClientModel getCreatedClient() {
+                return resource;
+            }
+        });
+        return resource;
+    }
+
+    @Override
+    public boolean removeClient(String id) {
+        if (id == null) return false;
+        ClientModel application = getClientById(id);
+        if (application == null) return false;
+
+        for (RoleModel role : application.getRoles()) {
+            application.removeRole(role);
+        }
+
+        ClientEntity clientEntity = null;
+        Iterator<ClientEntity> it = realm.getApplications().iterator();
+        while (it.hasNext()) {
+            ClientEntity ae = it.next();
+            if (ae.getId().equals(id)) {
+                clientEntity = ae;
+                it.remove();
+                break;
+            }
+        }
+        for (ClientEntity a : realm.getApplications()) {
+            if (a.getId().equals(id)) {
+                clientEntity = a;
+            }
+        }
+        if (application == null) {
+            return false;
+        }
+        em.remove(clientEntity);
+        em.createNamedQuery("deleteScopeMappingByClient").setParameter("client", clientEntity).executeUpdate();
+        em.flush();
+
+        return true;
+    }
+
+    @Override
+    public ClientModel getClientById(String id) {
+        return session.realms().getClientById(id, this);
+    }
+
+    @Override
+    public ClientModel getClientByClientId(String clientId) {
+        return getClientNameMap().get(clientId);
+    }
+
+    private static final String BROWSER_HEADER_PREFIX = "_browser_header.";
+
+    @Override
+    public Map<String, String> getBrowserSecurityHeaders() {
+        Map<String, String> attributes = getAttributes();
+        Map<String, String> headers = new HashMap<String, String>();
+        for (Map.Entry<String, String> entry : attributes.entrySet()) {
+            if (entry.getKey().startsWith(BROWSER_HEADER_PREFIX)) {
+                headers.put(entry.getKey().substring(BROWSER_HEADER_PREFIX.length()), entry.getValue());
+            }
+        }
+        return headers;
+    }
+
+    @Override
+    public void setBrowserSecurityHeaders(Map<String, String> headers) {
+        for (Map.Entry<String, String> entry : headers.entrySet()) {
+            setAttribute(BROWSER_HEADER_PREFIX + entry.getKey(), entry.getValue());
+        }
+    }
+
+    @Override
+    public Map<String, String> getSmtpConfig() {
+        return realm.getSmtpConfig();
+    }
+
+    @Override
+    public void setSmtpConfig(Map<String, String> smtpConfig) {
+        realm.setSmtpConfig(smtpConfig);
+        em.flush();
+    }
+
+    @Override
+    public List<UserFederationProviderModel> getUserFederationProviders() {
+        List<UserFederationProviderEntity> entities = realm.getUserFederationProviders();
+        List<UserFederationProviderEntity> copy = new ArrayList<UserFederationProviderEntity>();
+        for (UserFederationProviderEntity entity : entities) {
+            copy.add(entity);
+
+        }
+        Collections.sort(copy, new Comparator<UserFederationProviderEntity>() {
+
+            @Override
+            public int compare(UserFederationProviderEntity o1, UserFederationProviderEntity o2) {
+                return o1.getPriority() - o2.getPriority();
+            }
+
+        });
+        List<UserFederationProviderModel> result = new ArrayList<UserFederationProviderModel>();
+        for (UserFederationProviderEntity entity : copy) {
+            result.add(new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(),
+                    entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync()));
+        }
+
+        return result;
+    }
+
+    @Override
+    public UserFederationProviderModel addUserFederationProvider(String providerName, Map<String, String> config, int priority, String displayName, int fullSyncPeriod, int changedSyncPeriod, int lastSync) {
+        String id = KeycloakModelUtils.generateId();
+        UserFederationProviderEntity entity = new UserFederationProviderEntity();
+        entity.setId(id);
+        entity.setRealm(realm);
+        entity.setProviderName(providerName);
+        entity.setConfig(config);
+        entity.setPriority(priority);
+        if (displayName == null) {
+            displayName = id;
+        }
+        entity.setDisplayName(displayName);
+        entity.setFullSyncPeriod(fullSyncPeriod);
+        entity.setChangedSyncPeriod(changedSyncPeriod);
+        entity.setLastSync(lastSync);
+        em.persist(entity);
+        realm.getUserFederationProviders().add(entity);
+        em.flush();
+        return new UserFederationProviderModel(entity.getId(), providerName, config, priority, displayName, fullSyncPeriod, changedSyncPeriod, lastSync);
+    }
+
+    @Override
+    public void removeUserFederationProvider(UserFederationProviderModel provider) {
+        Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
+        while (it.hasNext()) {
+            UserFederationProviderEntity entity = it.next();
+            if (entity.getId().equals(provider.getId())) {
+                session.users().preRemove(this, provider);
+                it.remove();
+                em.remove(entity);
+                return;
+            }
+        }
+    }
+    @Override
+    public void updateUserFederationProvider(UserFederationProviderModel model) {
+        Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
+        while (it.hasNext()) {
+            UserFederationProviderEntity entity = it.next();
+            if (entity.getId().equals(model.getId())) {
+                String displayName = model.getDisplayName();
+                if (displayName != null) {
+                    entity.setDisplayName(model.getDisplayName());
+                }
+                entity.setConfig(model.getConfig());
+                entity.setPriority(model.getPriority());
+                entity.setProviderName(model.getProviderName());
+                entity.setPriority(model.getPriority());
+                entity.setFullSyncPeriod(model.getFullSyncPeriod());
+                entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
+                entity.setLastSync(model.getLastSync());
+                break;
+            }
+        }
+    }
+
+    @Override
+    public void setUserFederationProviders(List<UserFederationProviderModel> providers) {
+
+        Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
+        while (it.hasNext()) {
+            UserFederationProviderEntity entity = it.next();
+            boolean found = false;
+            for (UserFederationProviderModel model : providers) {
+                if (entity.getId().equals(model.getId())) {
+                    entity.setConfig(model.getConfig());
+                    entity.setPriority(model.getPriority());
+                    entity.setProviderName(model.getProviderName());
+                    entity.setPriority(model.getPriority());
+                    String displayName = model.getDisplayName();
+                    if (displayName != null) {
+                        entity.setDisplayName(model.getDisplayName());
+                    }
+                    entity.setFullSyncPeriod(model.getFullSyncPeriod());
+                    entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
+                    entity.setLastSync(model.getLastSync());
+                    found = true;
+                    break;
+                }
+
+            }
+            if (found) continue;
+            session.users().preRemove(this, new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName(),
+                    entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity.getLastSync()));
+            it.remove();
+            em.remove(entity);
+        }
+
+        List<UserFederationProviderModel> add = new LinkedList<UserFederationProviderModel>();
+        for (UserFederationProviderModel model : providers) {
+            boolean found = false;
+            for (UserFederationProviderEntity entity : realm.getUserFederationProviders()) {
+                if (entity.getId().equals(model.getId())) {
+                    found = true;
+                    break;
+                }
+            }
+            if (!found) add.add(model);
+        }
+
+        for (UserFederationProviderModel model : add) {
+            UserFederationProviderEntity entity = new UserFederationProviderEntity();
+            if (model.getId() != null) entity.setId(model.getId());
+            else entity.setId(KeycloakModelUtils.generateId());
+            entity.setConfig(model.getConfig());
+            entity.setPriority(model.getPriority());
+            entity.setProviderName(model.getProviderName());
+            entity.setPriority(model.getPriority());
+            String displayName = model.getDisplayName();
+            if (displayName == null) {
+                displayName = entity.getId();
+            }
+            entity.setDisplayName(displayName);
+            entity.setFullSyncPeriod(model.getFullSyncPeriod());
+            entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
+            entity.setLastSync(model.getLastSync());
+            em.persist(entity);
+            realm.getUserFederationProviders().add(entity);
+
+        }
+    }
+
+    @Override
+    public RoleModel getRole(String name) {
+        TypedQuery<RoleEntity> query = em.createNamedQuery("getRealmRoleByName", RoleEntity.class);
+        query.setParameter("name", name);
+        query.setParameter("realm", realm);
+        List<RoleEntity> roles = query.getResultList();
+        if (roles.size() == 0) return null;
+        return new RoleAdapter(this, em, roles.get(0));
+    }
+
+    @Override
+    public RoleModel addRole(String name) {
+        return this.addRole(KeycloakModelUtils.generateId(), name);
+    }
+
+    @Override
+    public RoleModel addRole(String id, String name) {
+        RoleEntity entity = new RoleEntity();
+        entity.setId(id);
+        entity.setName(name);
+        entity.setRealm(realm);
+        entity.setRealmId(realm.getId());
+        realm.getRoles().add(entity);
+        em.persist(entity);
+        em.flush();
+        return new RoleAdapter(this, em, entity);
+    }
+
+    @Override
+    public boolean removeRole(RoleModel role) {
+        if (role == null) {
+            return false;
+        }
+        if (!role.getContainer().equals(this)) return false;
+        session.users().preRemove(this, role);
+        RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em);
+        realm.getRoles().remove(roleEntity);
+        realm.getDefaultRoles().remove(roleEntity);
+
+        em.createNativeQuery("delete from COMPOSITE_ROLE where CHILD_ROLE = :role").setParameter("role", roleEntity).executeUpdate();
+        em.createNamedQuery("deleteScopeMappingByRole").setParameter("role", roleEntity).executeUpdate();
+
+        em.remove(roleEntity);
+
+        return true;
+    }
+
+    @Override
+    public Set<RoleModel> getRoles() {
+        Set<RoleModel> list = new HashSet<RoleModel>();
+        Collection<RoleEntity> roles = realm.getRoles();
+        if (roles == null) return list;
+        for (RoleEntity entity : roles) {
+            list.add(new RoleAdapter(this, em, entity));
+        }
+        return list;
+    }
+
+    @Override
+    public RoleModel getRoleById(String id) {
+        return session.realms().getRoleById(id, this);
+    }
+
+    @Override
+    public boolean removeRoleById(String id) {
+        RoleModel role = getRoleById(id);
+        if (role == null) return false;
+        return role.getContainer().removeRole(role);
+    }
+
+    @Override
+    public PasswordPolicy getPasswordPolicy() {
+        if (passwordPolicy == null) {
+            passwordPolicy = new PasswordPolicy(realm.getPasswordPolicy());
+        }
+        return passwordPolicy;
+    }
+
+    @Override
+    public void setPasswordPolicy(PasswordPolicy policy) {
+        this.passwordPolicy = policy;
+        realm.setPasswordPolicy(policy.toString());
+        em.flush();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof RealmModel)) return false;
+
+        RealmModel that = (RealmModel) o;
+        return that.getId().equals(getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
+
+    @Override
+    public String getLoginTheme() {
+        return realm.getLoginTheme();
+    }
+
+    @Override
+    public void setLoginTheme(String name) {
+        realm.setLoginTheme(name);
+        em.flush();
+    }
+
+    @Override
+    public String getAccountTheme() {
+        return realm.getAccountTheme();
+    }
+
+    @Override
+    public void setAccountTheme(String name) {
+        realm.setAccountTheme(name);
+        em.flush();
+    }
+
+    @Override
+    public String getAdminTheme() {
+        return realm.getAdminTheme();
+    }
+
+    @Override
+    public void setAdminTheme(String name) {
+        realm.setAdminTheme(name);
+        em.flush();
+    }
+
+    @Override
+    public String getEmailTheme() {
+        return realm.getEmailTheme();
+    }
+
+    @Override
+    public void setEmailTheme(String name) {
+        realm.setEmailTheme(name);
+        em.flush();
+    }
+
+    @Override
+    public boolean isEventsEnabled() {
+        return realm.isEventsEnabled();
+    }
+
+    @Override
+    public void setEventsEnabled(boolean enabled) {
+        realm.setEventsEnabled(enabled);
+        em.flush();
+    }
+
+    @Override
+    public long getEventsExpiration() {
+        return realm.getEventsExpiration();
+    }
+
+    @Override
+    public void setEventsExpiration(long expiration) {
+        realm.setEventsExpiration(expiration);
+        em.flush();
+    }
+
+    @Override
+    public Set<String> getEventsListeners() {
+        return realm.getEventsListeners();
+    }
+
+    @Override
+    public void setEventsListeners(Set<String> listeners) {
+        realm.setEventsListeners(listeners);
+        em.flush();
+    }
+    
+    @Override
+    public Set<String> getEnabledEventTypes() {
+        return realm.getEnabledEventTypes();
+    }
+
+    @Override
+    public void setEnabledEventTypes(Set<String> enabledEventTypes) {
+        realm.setEnabledEventTypes(enabledEventTypes);
+        em.flush();
+    }
+
+    @Override
+    public ClientModel getMasterAdminClient() {
+        return new ClientAdapter(this, em, session, realm.getMasterAdminApp());
+    }
+
+    @Override
+    public void setMasterAdminClient(ClientModel client) {
+        ClientEntity appEntity = client !=null ? em.getReference(ClientEntity.class, client.getId()) : null;
+        realm.setMasterAdminApp(appEntity);
+        em.flush();
+    }
+
+    @Override
+    public List<IdentityProviderModel> getIdentityProviders() {
+        List<IdentityProviderModel> identityProviders = new ArrayList<IdentityProviderModel>();
+
+        for (IdentityProviderEntity entity: realm.getIdentityProviders()) {
+            IdentityProviderModel identityProviderModel = new IdentityProviderModel();
+
+            identityProviderModel.setProviderId(entity.getProviderId());
+            identityProviderModel.setAlias(entity.getAlias());
+            identityProviderModel.setInternalId(entity.getInternalId());
+            identityProviderModel.setConfig(entity.getConfig());
+            identityProviderModel.setEnabled(entity.isEnabled());
+            identityProviderModel.setUpdateProfileFirstLogin(entity.isUpdateProfileFirstLogin());
+            identityProviderModel.setAuthenticateByDefault(entity.isAuthenticateByDefault());
+            identityProviderModel.setStoreToken(entity.isStoreToken());
+
+            identityProviders.add(identityProviderModel);
+        }
+
+        return identityProviders;
+    }
+
+    @Override
+    public IdentityProviderModel getIdentityProviderByAlias(String alias) {
+        for (IdentityProviderModel identityProviderModel : getIdentityProviders()) {
+            if (identityProviderModel.getAlias().equals(alias)) {
+                return identityProviderModel;
+            }
+        }
+
+        return null;
+    }
+
+    @Override
+    public void addIdentityProvider(IdentityProviderModel identityProvider) {
+        IdentityProviderEntity entity = new IdentityProviderEntity();
+
+        entity.setInternalId(KeycloakModelUtils.generateId());
+        entity.setAlias(identityProvider.getAlias());
+        entity.setProviderId(identityProvider.getProviderId());
+        entity.setEnabled(identityProvider.isEnabled());
+        entity.setStoreToken(identityProvider.isStoreToken());
+        entity.setUpdateProfileFirstLogin(identityProvider.isUpdateProfileFirstLogin());
+        entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
+        entity.setConfig(identityProvider.getConfig());
+
+        realm.addIdentityProvider(entity);
+
+        em.persist(entity);
+        em.flush();
+    }
+
+    @Override
+    public void removeIdentityProviderByAlias(String alias) {
+        for (IdentityProviderEntity entity : realm.getIdentityProviders()) {
+            if (entity.getAlias().equals(alias)) {
+                em.remove(entity);
+                em.flush();
+            }
+        }
+    }
+
+    @Override
+    public void updateIdentityProvider(IdentityProviderModel identityProvider) {
+        for (IdentityProviderEntity entity : this.realm.getIdentityProviders()) {
+            if (entity.getInternalId().equals(identityProvider.getInternalId())) {
+                entity.setAlias(identityProvider.getAlias());
+                entity.setEnabled(identityProvider.isEnabled());
+                entity.setUpdateProfileFirstLogin(identityProvider.isUpdateProfileFirstLogin());
+                entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
+                entity.setStoreToken(identityProvider.isStoreToken());
+                entity.setConfig(identityProvider.getConfig());
+            }
+        }
+
+        em.flush();
+    }
+
+    @Override
+    public boolean isIdentityFederationEnabled() {
+        return !this.realm.getIdentityProviders().isEmpty();
+    }
+
+    @Override
+    public boolean isInternationalizationEnabled() {
+        return realm.isInternationalizationEnabled();
+    }
+
+    @Override
+    public void setInternationalizationEnabled(boolean enabled) {
+        realm.setInternationalizationEnabled(enabled);
+        em.flush();
+    }
+
+    @Override
+    public Set<String> getSupportedLocales() {
+        return realm.getSupportedLocales();
+    }
+
+    @Override
+    public void setSupportedLocales(Set<String> locales) {
+        realm.setSupportedLocales(locales);
+        em.flush();
+    }
+
+    @Override
+    public String getDefaultLocale() {
+        return realm.getDefaultLocale();
+    }
+
+    @Override
+    public void setDefaultLocale(String locale) {
+        realm.setDefaultLocale(locale);
+        em.flush();
+    }
+
+    @Override
+    public Set<IdentityProviderMapperModel> getIdentityProviderMappers() {
+        Set<IdentityProviderMapperModel> mappings = new HashSet<IdentityProviderMapperModel>();
+        for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) {
+            IdentityProviderMapperModel mapping = new IdentityProviderMapperModel();
+            mapping.setId(entity.getId());
+            mapping.setName(entity.getName());
+            mapping.setIdentityProviderAlias(entity.getIdentityProviderAlias());
+            mapping.setIdentityProviderMapper(entity.getIdentityProviderMapper());
+            Map<String, String> config = new HashMap<String, String>();
+            if (entity.getConfig() != null) {
+                config.putAll(entity.getConfig());
+            }
+            mapping.setConfig(config);
+            mappings.add(mapping);
+        }
+        return mappings;
+    }
+
+    @Override
+    public Set<IdentityProviderMapperModel> getIdentityProviderMappersByAlias(String brokerAlias) {
+        Set<IdentityProviderMapperModel> mappings = new HashSet<IdentityProviderMapperModel>();
+        for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) {
+            if (!entity.getIdentityProviderAlias().equals(brokerAlias)) {
+                continue;
+            }
+            IdentityProviderMapperModel mapping = new IdentityProviderMapperModel();
+            mapping.setId(entity.getId());
+            mapping.setName(entity.getName());
+            mapping.setIdentityProviderAlias(entity.getIdentityProviderAlias());
+            mapping.setIdentityProviderMapper(entity.getIdentityProviderMapper());
+            Map<String, String> config = new HashMap<String, String>();
+            if (entity.getConfig() != null) {
+                config.putAll(entity.getConfig());
+            }
+            mapping.setConfig(config);
+            mappings.add(mapping);
+        }
+        return mappings;
+    }
+
+    @Override
+    public IdentityProviderMapperModel addIdentityProviderMapper(IdentityProviderMapperModel model) {
+        if (getIdentityProviderMapperByName(model.getIdentityProviderAlias(), model.getIdentityProviderMapper()) != null) {
+            throw new RuntimeException("protocol mapper name must be unique per protocol");
+        }
+        String id = KeycloakModelUtils.generateId();
+        IdentityProviderMapperEntity entity = new IdentityProviderMapperEntity();
+        entity.setId(id);
+        entity.setName(model.getName());
+        entity.setIdentityProviderAlias(model.getIdentityProviderAlias());
+        entity.setIdentityProviderMapper(model.getIdentityProviderMapper());
+        entity.setRealm(this.realm);
+        entity.setConfig(model.getConfig());
+
+        em.persist(entity);
+        this.realm.getIdentityProviderMappers().add(entity);
+        return entityToModel(entity);
+    }
+
+    protected IdentityProviderMapperEntity getIdentityProviderMapperEntity(String id) {
+        for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) {
+            if (entity.getId().equals(id)) {
+                return entity;
+            }
+        }
+        return null;
+
+    }
+
+    protected IdentityProviderMapperEntity getIdentityProviderMapperEntityByName(String alias, String name) {
+        for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) {
+            if (entity.getIdentityProviderAlias().equals(alias) && entity.getName().equals(name)) {
+                return entity;
+            }
+        }
+        return null;
+
+    }
+
+    @Override
+    public void removeIdentityProviderMapper(IdentityProviderMapperModel mapping) {
+        IdentityProviderMapperEntity toDelete = getIdentityProviderMapperEntity(mapping.getId());
+        if (toDelete != null) {
+            this.realm.getIdentityProviderMappers().remove(toDelete);
+            em.remove(toDelete);
+        }
+
+    }
+
+    @Override
+    public void updateIdentityProviderMapper(IdentityProviderMapperModel mapping) {
+        IdentityProviderMapperEntity entity = getIdentityProviderMapperEntity(mapping.getId());
+        entity.setIdentityProviderAlias(mapping.getIdentityProviderAlias());
+        entity.setIdentityProviderMapper(mapping.getIdentityProviderMapper());
+        if (entity.getConfig() == null) {
+            entity.setConfig(mapping.getConfig());
+        } else {
+            entity.getConfig().clear();
+            entity.getConfig().putAll(mapping.getConfig());
+        }
+        em.flush();
+
+    }
+
+    @Override
+    public IdentityProviderMapperModel getIdentityProviderMapperById(String id) {
+        IdentityProviderMapperEntity entity = getIdentityProviderMapperEntity(id);
+        if (entity == null) return null;
+        return entityToModel(entity);
+    }
+
+    @Override
+    public IdentityProviderMapperModel getIdentityProviderMapperByName(String alias, String name) {
+        IdentityProviderMapperEntity entity = getIdentityProviderMapperEntityByName(alias, name);
+        if (entity == null) return null;
+        return entityToModel(entity);
+    }
+
+    protected IdentityProviderMapperModel entityToModel(IdentityProviderMapperEntity entity) {
+        IdentityProviderMapperModel mapping = new IdentityProviderMapperModel();
+        mapping.setId(entity.getId());
+        mapping.setName(entity.getName());
+        mapping.setIdentityProviderAlias(entity.getIdentityProviderAlias());
+        mapping.setIdentityProviderMapper(entity.getIdentityProviderMapper());
+        Map<String, String> config = new HashMap<String, String>();
+        if (entity.getConfig() != null) config.putAll(entity.getConfig());
+        mapping.setConfig(config);
+        return mapping;
+    }
 }
\ No newline at end of file
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java
index 28a1f47..1687855 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java
@@ -105,7 +105,7 @@ public class RoleAdapter implements RoleModel {
     @Override
     public RoleContainerModel getContainer() {
         if (role.isApplicationRole()) {
-            return realm.getApplicationById(role.getApplication().getId());
+            return realm.getClientById(role.getApplication().getId());
 
         } else {
             return realm;
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java
index 5ef06fa..a51d0de 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java
@@ -1,6 +1,6 @@
 package org.keycloak.models.jpa;
 
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.PasswordPolicy;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleContainerModel;
@@ -363,14 +363,14 @@ public class UserAdapter implements UserModel {
     }
 
     @Override
-    public Set<RoleModel> getApplicationRoleMappings(ApplicationModel app) {
+    public Set<RoleModel> getClientRoleMappings(ClientModel app) {
         Set<RoleModel> roleMappings = getRoleMappings();
 
         Set<RoleModel> roles = new HashSet<RoleModel>();
         for (RoleModel role : roleMappings) {
             RoleContainerModel container = role.getContainer();
-            if (container instanceof ApplicationModel) {
-                ApplicationModel appModel = (ApplicationModel)container;
+            if (container instanceof ClientModel) {
+                ClientModel appModel = (ClientModel)container;
                 if (appModel.getId().equals(app.getId())) {
                    roles.add(role);
                 }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java
index 38c40f8..803cedf 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java
@@ -1,445 +1,672 @@
-package org.keycloak.models.mongo.keycloak.adapters;
-
-import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
-import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
-import org.keycloak.models.ClientIdentityProviderMappingModel;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolMapperModel;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RealmProvider;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.entities.ClientEntity;
-import org.keycloak.models.entities.ClientIdentityProviderMappingEntity;
-import org.keycloak.models.entities.ProtocolMapperEntity;
-import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
-import org.keycloak.models.mongo.utils.MongoModelUtils;
-import org.keycloak.models.utils.KeycloakModelUtils;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
- */
-public abstract class ClientAdapter<T extends MongoIdentifiableEntity> extends AbstractMongoAdapter<T> implements ClientModel {
-
-    protected final T clientEntity;
-    private final RealmModel realm;
-    protected  KeycloakSession session;
-
-    public ClientAdapter(KeycloakSession session, RealmModel realm, T clientEntity, MongoStoreInvocationContext invContext) {
-        super(invContext);
-        this.clientEntity = clientEntity;
-        this.realm = realm;
-        this.session = session;
-    }
-
-    @Override
-    public T getMongoEntity() {
-        return clientEntity;
-    }
-
-    // ClientEntity doesn't extend MongoIdentifiableEntity
-    public ClientEntity getMongoEntityAsClient() {
-        return (ClientEntity)getMongoEntity();
-    }
-
-    @Override
-    public String getId() {
-        return getMongoEntity().getId();
-    }
-
-    @Override
-    public String getClientId() {
-        return getMongoEntityAsClient().getName();
-    }
-
-    @Override
-    public Set<String> getWebOrigins() {
-        Set<String> result = new HashSet<String>();
-        if (getMongoEntityAsClient().getWebOrigins() != null) {
-            result.addAll(getMongoEntityAsClient().getWebOrigins());
-        }
-        return result;
-    }
-
-    @Override
-    public void setWebOrigins(Set<String> webOrigins) {
-        List<String> result = new ArrayList<String>();
-        result.addAll(webOrigins);
-        getMongoEntityAsClient().setWebOrigins(result);
-        updateMongoEntity();
-    }
-
-    @Override
-    public void addWebOrigin(String webOrigin) {
-        getMongoStore().pushItemToList(clientEntity, "webOrigins", webOrigin, true, invocationContext);
-    }
-
-    @Override
-    public void removeWebOrigin(String webOrigin) {
-        getMongoStore().pullItemFromList(clientEntity, "webOrigins", webOrigin, invocationContext);
-    }
-
-    @Override
-    public Set<String> getRedirectUris() {
-        Set<String> result = new HashSet<String>();
-        if (getMongoEntityAsClient().getRedirectUris() != null) {
-            result.addAll(getMongoEntityAsClient().getRedirectUris());
-        }
-        return result;
-    }
-
-    @Override
-    public void setRedirectUris(Set<String> redirectUris) {
-        List<String> result = new ArrayList<String>();
-        result.addAll(redirectUris);
-        getMongoEntityAsClient().setRedirectUris(result);
-        updateMongoEntity();
-    }
-
-    @Override
-    public void addRedirectUri(String redirectUri) {
-        getMongoStore().pushItemToList(clientEntity, "redirectUris", redirectUri, true, invocationContext);
-    }
-
-    @Override
-    public void removeRedirectUri(String redirectUri) {
-        getMongoStore().pullItemFromList(clientEntity, "redirectUris", redirectUri, invocationContext);
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return getMongoEntityAsClient().isEnabled();
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        getMongoEntityAsClient().setEnabled(enabled);
-        updateMongoEntity();
-    }
-
-    @Override
-    public boolean validateSecret(String secret) {
-        return secret.equals(getMongoEntityAsClient().getSecret());
-    }
-
-    @Override
-    public String getSecret() {
-        return getMongoEntityAsClient().getSecret();
-    }
-
-    @Override
-    public void setSecret(String secret) {
-        getMongoEntityAsClient().setSecret(secret);
-        updateMongoEntity();
-    }
-
-    @Override
-    public boolean isPublicClient() {
-        return getMongoEntityAsClient().isPublicClient();
-    }
-
-    @Override
-    public void setPublicClient(boolean flag) {
-        getMongoEntityAsClient().setPublicClient(flag);
-        updateMongoEntity();
-    }
-
-
-    @Override
-    public boolean isFrontchannelLogout() {
-        return getMongoEntityAsClient().isFrontchannelLogout();
-    }
-
-    @Override
-    public void setFrontchannelLogout(boolean flag) {
-        getMongoEntityAsClient().setFrontchannelLogout(flag);
-        updateMongoEntity();
-    }
-
-    @Override
-    public boolean isFullScopeAllowed() {
-        return getMongoEntityAsClient().isFullScopeAllowed();
-    }
-
-    @Override
-    public void setFullScopeAllowed(boolean value) {
-        getMongoEntityAsClient().setFullScopeAllowed(value);
-        updateMongoEntity();
-
-    }
-
-    @Override
-    public RealmModel getRealm() {
-        return realm;
-    }
-
-    @Override
-    public int getNotBefore() {
-        return getMongoEntityAsClient().getNotBefore();
-    }
-
-    @Override
-    public void setNotBefore(int notBefore) {
-        getMongoEntityAsClient().setNotBefore(notBefore);
-        updateMongoEntity();
-    }
-
-    @Override
-    public Set<RoleModel> getScopeMappings() {
-        Set<RoleModel> result = new HashSet<RoleModel>();
-        List<MongoRoleEntity> roles = MongoModelUtils.getAllScopesOfClient(this, invocationContext);
-
-        for (MongoRoleEntity role : roles) {
-            if (realm.getId().equals(role.getRealmId())) {
-                result.add(new RoleAdapter(session, realm, role, realm, invocationContext));
-            } else {
-                // Likely applicationRole, but we don't have this application yet
-                result.add(new RoleAdapter(session, realm, role, invocationContext));
-            }
-        }
-        return result;
-    }
-
-    @Override
-    public Set<RoleModel> getRealmScopeMappings() {
-        Set<RoleModel> allScopes = getScopeMappings();
-
-        // Filter to retrieve just realm roles TODO: Maybe improve to avoid filter programmatically... Maybe have separate fields for realmRoles and appRoles on user?
-        Set<RoleModel> realmRoles = new HashSet<RoleModel>();
-        for (RoleModel role : allScopes) {
-            MongoRoleEntity roleEntity = ((RoleAdapter) role).getRole();
-
-            if (realm.getId().equals(roleEntity.getRealmId())) {
-                realmRoles.add(role);
-            }
-        }
-        return realmRoles;
-    }
-
-    @Override
-    public boolean hasScope(RoleModel role) {
-        if (isFullScopeAllowed()) return true;
-        Set<RoleModel> roles = getScopeMappings();
-        if (roles.contains(role)) return true;
-
-        for (RoleModel mapping : roles) {
-            if (mapping.hasRole(role)) return true;
-        }
-        return false;
-    }
-
-
-    @Override
-    public void addScopeMapping(RoleModel role) {
-        getMongoStore().pushItemToList(this.getMongoEntity(), "scopeIds", role.getId(), true, invocationContext);
-    }
-
-    @Override
-    public void deleteScopeMapping(RoleModel role) {
-        getMongoStore().pullItemFromList(this.getMongoEntity(), "scopeIds", role.getId(), invocationContext);
-    }
-
-    @Override
-    public String getProtocol() {
-        return getMongoEntityAsClient().getProtocol();
-    }
-
-    @Override
-    public void setProtocol(String protocol) {
-        getMongoEntityAsClient().setProtocol(protocol);
-        updateMongoEntity();
-
-    }
-
-    @Override
-    public void setAttribute(String name, String value) {
-        getMongoEntityAsClient().getAttributes().put(name, value);
-        updateMongoEntity();
-
-    }
-
-    @Override
-    public void removeAttribute(String name) {
-        getMongoEntityAsClient().getAttributes().remove(name);
-        updateMongoEntity();
-    }
-
-    @Override
-    public String getAttribute(String name) {
-        return getMongoEntityAsClient().getAttributes().get(name);
-    }
-
-    @Override
-    public Map<String, String> getAttributes() {
-        Map<String, String> copy = new HashMap<String, String>();
-        copy.putAll(getMongoEntityAsClient().getAttributes());
-        return copy;
-    }
-
-    @Override
-    public Set<ProtocolMapperModel> getProtocolMappers() {
-        Set<ProtocolMapperModel> result = new HashSet<ProtocolMapperModel>();
-        for (ProtocolMapperEntity entity : getMongoEntityAsClient().getProtocolMappers()) {
-            ProtocolMapperModel mapping = new ProtocolMapperModel();
-            mapping.setId(entity.getId());
-            mapping.setName(entity.getName());
-            mapping.setProtocol(entity.getProtocol());
-            mapping.setProtocolMapper(entity.getProtocolMapper());
-            mapping.setConsentRequired(entity.isConsentRequired());
-            mapping.setConsentText(entity.getConsentText());
-            Map<String, String> config = new HashMap<String, String>();
-            if (entity.getConfig() != null) {
-                config.putAll(entity.getConfig());
-            }
-            mapping.setConfig(config);
-            result.add(mapping);
-        }
-        return result;
-    }
-
-    @Override
-    public ProtocolMapperModel addProtocolMapper(ProtocolMapperModel model) {
-        if (getProtocolMapperByName(model.getProtocol(), model.getName()) != null) {
-            throw new RuntimeException("protocol mapper name must be unique per protocol");
-        }
-        ProtocolMapperEntity entity = new ProtocolMapperEntity();
-        entity.setId(KeycloakModelUtils.generateId());
-        entity.setProtocol(model.getProtocol());
-        entity.setName(model.getName());
-        entity.setProtocolMapper(model.getProtocolMapper());
-        entity.setConfig(model.getConfig());
-        entity.setConsentRequired(model.isConsentRequired());
-        entity.setConsentText(model.getConsentText());
-        getMongoEntityAsClient().getProtocolMappers().add(entity);
-        updateMongoEntity();
-        return entityToModel(entity);
-    }
-
-    @Override
-    public void removeProtocolMapper(ProtocolMapperModel mapping) {
-        for (ProtocolMapperEntity entity : getMongoEntityAsClient().getProtocolMappers()) {
-            if (entity.getId().equals(mapping.getId())) {
-                getMongoEntityAsClient().getProtocolMappers().remove(entity);
-                updateMongoEntity();
-                break;
-            }
-        }
-
-    }
-
-    protected ProtocolMapperEntity getProtocolMapperyEntityById(String id) {
-        for (ProtocolMapperEntity entity : getMongoEntityAsClient().getProtocolMappers()) {
-            if (entity.getId().equals(id)) {
-                return entity;
-            }
-        }
-        return null;
-
-    }
-    protected ProtocolMapperEntity getProtocolMapperEntityByName(String protocol, String name) {
-        for (ProtocolMapperEntity entity : getMongoEntityAsClient().getProtocolMappers()) {
-            if (entity.getProtocol().equals(protocol) && entity.getName().equals(name)) {
-                return entity;
-            }
-        }
-        return null;
-
-    }
-
-
-    @Override
-    public void updateProtocolMapper(ProtocolMapperModel mapping) {
-        ProtocolMapperEntity entity = getProtocolMapperyEntityById(mapping.getId());
-        entity.setProtocolMapper(mapping.getProtocolMapper());
-        entity.setConsentRequired(mapping.isConsentRequired());
-        entity.setConsentText(mapping.getConsentText());
-        if (entity.getConfig() != null) {
-            entity.getConfig().clear();
-            entity.getConfig().putAll(mapping.getConfig());
-        } else {
-            entity.setConfig(mapping.getConfig());
-        }
-        updateMongoEntity();
-
-    }
-
-    @Override
-    public ProtocolMapperModel getProtocolMapperById(String id) {
-        ProtocolMapperEntity entity = getProtocolMapperyEntityById(id);
-        if (entity == null) return null;
-        return entityToModel(entity);
-    }
-
-    @Override
-    public ProtocolMapperModel getProtocolMapperByName(String protocol, String name) {
-        ProtocolMapperEntity entity = getProtocolMapperEntityByName(protocol, name);
-        if (entity == null) return null;
-        return entityToModel(entity);
-    }
-
-    protected ProtocolMapperModel entityToModel(ProtocolMapperEntity entity) {
-        ProtocolMapperModel mapping = new ProtocolMapperModel();
-        mapping.setId(entity.getId());
-        mapping.setName(entity.getName());
-        mapping.setProtocol(entity.getProtocol());
-        mapping.setProtocolMapper(entity.getProtocolMapper());
-        mapping.setConsentRequired(entity.isConsentRequired());
-        mapping.setConsentText(entity.getConsentText());
-        Map<String, String> config = new HashMap<String, String>();
-        if (entity.getConfig() != null) config.putAll(entity.getConfig());
-        mapping.setConfig(config);
-        return mapping;
-    }
-
-
-    @Override
-    public void updateIdentityProviders(List<ClientIdentityProviderMappingModel> identityProviders) {
-        List<ClientIdentityProviderMappingEntity> stored = new ArrayList<ClientIdentityProviderMappingEntity>();
-
-        for (ClientIdentityProviderMappingModel model : identityProviders) {
-            ClientIdentityProviderMappingEntity entity = new ClientIdentityProviderMappingEntity();
-
-            entity.setId(model.getIdentityProvider());
-            entity.setRetrieveToken(model.isRetrieveToken());
-            stored.add(entity);
-        }
-
-        getMongoEntityAsClient().setIdentityProviders(stored);
-        updateMongoEntity();
-    }
-
-    @Override
-    public List<ClientIdentityProviderMappingModel> getIdentityProviders() {
-        List<ClientIdentityProviderMappingModel> models = new ArrayList<ClientIdentityProviderMappingModel>();
-
-        for (ClientIdentityProviderMappingEntity entity : getMongoEntityAsClient().getIdentityProviders()) {
-            ClientIdentityProviderMappingModel model = new ClientIdentityProviderMappingModel();
-
-            model.setIdentityProvider(entity.getId());
-            model.setRetrieveToken(entity.isRetrieveToken());
-
-            models.add(model);
-        }
-
-        return models;
-    }
-
-    @Override
-    public boolean isAllowedRetrieveTokenFromIdentityProvider(String providerId) {
-        for (ClientIdentityProviderMappingEntity identityProviderMappingModel : getMongoEntityAsClient().getIdentityProviders()) {
-            if (identityProviderMappingModel.getId().equals(providerId)) {
-                return identityProviderMappingModel.isRetrieveToken();
-            }
-        }
-
-        return false;
-    }
-
-}
+package org.keycloak.models.mongo.keycloak.adapters;
+
+import com.mongodb.DBObject;
+import com.mongodb.QueryBuilder;
+import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientIdentityProviderMappingModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.entities.ClientIdentityProviderMappingEntity;
+import org.keycloak.models.entities.ProtocolMapperEntity;
+import org.keycloak.models.mongo.keycloak.entities.MongoClientEntity;
+import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
+import org.keycloak.models.mongo.utils.MongoModelUtils;
+import org.keycloak.models.utils.KeycloakModelUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class ClientAdapter extends AbstractMongoAdapter<MongoClientEntity> implements ClientModel {
+
+    protected final MongoClientEntity applicationEntity;
+    private final RealmModel realm;
+    protected  KeycloakSession session;
+
+    public ClientAdapter(KeycloakSession session, RealmModel realm, MongoClientEntity applicationEntity, MongoStoreInvocationContext invContext) {
+        super(invContext);
+        this.session = session;
+        this.realm = realm;
+        this.applicationEntity = applicationEntity;
+    }
+
+    @Override
+    public MongoClientEntity getMongoEntity() {
+        return applicationEntity;
+    }
+
+    @Override
+    public void updateClient() {
+        updateMongoEntity();
+    }
+
+
+    @Override
+    public String getId() {
+        return getMongoEntity().getId();
+    }
+
+    @Override
+    public String getClientId() {
+        return getMongoEntity().getClientId();
+    }
+
+    @Override
+    public void setClientId(String clientId) {
+        getMongoEntity().setClientId(clientId);
+        updateMongoEntity();
+    }
+
+    @Override
+    public Set<String> getWebOrigins() {
+        Set<String> result = new HashSet<String>();
+        if (getMongoEntity().getWebOrigins() != null) {
+            result.addAll(getMongoEntity().getWebOrigins());
+        }
+        return result;
+    }
+
+    @Override
+    public void setWebOrigins(Set<String> webOrigins) {
+        List<String> result = new ArrayList<String>();
+        result.addAll(webOrigins);
+        getMongoEntity().setWebOrigins(result);
+        updateMongoEntity();
+    }
+
+    @Override
+    public void addWebOrigin(String webOrigin) {
+        getMongoStore().pushItemToList(applicationEntity, "webOrigins", webOrigin, true, invocationContext);
+    }
+
+    @Override
+    public void removeWebOrigin(String webOrigin) {
+        getMongoStore().pullItemFromList(applicationEntity, "webOrigins", webOrigin, invocationContext);
+    }
+
+    @Override
+    public Set<String> getRedirectUris() {
+        Set<String> result = new HashSet<String>();
+        if (getMongoEntity().getRedirectUris() != null) {
+            result.addAll(getMongoEntity().getRedirectUris());
+        }
+        return result;
+    }
+
+    @Override
+    public void setRedirectUris(Set<String> redirectUris) {
+        List<String> result = new ArrayList<String>();
+        result.addAll(redirectUris);
+        getMongoEntity().setRedirectUris(result);
+        updateMongoEntity();
+    }
+
+    @Override
+    public void addRedirectUri(String redirectUri) {
+        getMongoStore().pushItemToList(applicationEntity, "redirectUris", redirectUri, true, invocationContext);
+    }
+
+    @Override
+    public void removeRedirectUri(String redirectUri) {
+        getMongoStore().pullItemFromList(applicationEntity, "redirectUris", redirectUri, invocationContext);
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return getMongoEntity().isEnabled();
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        getMongoEntity().setEnabled(enabled);
+        updateMongoEntity();
+    }
+
+    @Override
+    public boolean validateSecret(String secret) {
+        return secret.equals(getMongoEntity().getSecret());
+    }
+
+    @Override
+    public String getSecret() {
+        return getMongoEntity().getSecret();
+    }
+
+    @Override
+    public void setSecret(String secret) {
+        getMongoEntity().setSecret(secret);
+        updateMongoEntity();
+    }
+
+    @Override
+    public boolean isPublicClient() {
+        return getMongoEntity().isPublicClient();
+    }
+
+    @Override
+    public void setPublicClient(boolean flag) {
+        getMongoEntity().setPublicClient(flag);
+        updateMongoEntity();
+    }
+
+
+    @Override
+    public boolean isFrontchannelLogout() {
+        return getMongoEntity().isFrontchannelLogout();
+    }
+
+    @Override
+    public void setFrontchannelLogout(boolean flag) {
+        getMongoEntity().setFrontchannelLogout(flag);
+        updateMongoEntity();
+    }
+
+    @Override
+    public boolean isFullScopeAllowed() {
+        return getMongoEntity().isFullScopeAllowed();
+    }
+
+    @Override
+    public void setFullScopeAllowed(boolean value) {
+        getMongoEntity().setFullScopeAllowed(value);
+        updateMongoEntity();
+
+    }
+
+    @Override
+    public RealmModel getRealm() {
+        return realm;
+    }
+
+    @Override
+    public int getNotBefore() {
+        return getMongoEntity().getNotBefore();
+    }
+
+    @Override
+    public void setNotBefore(int notBefore) {
+        getMongoEntity().setNotBefore(notBefore);
+        updateMongoEntity();
+    }
+
+    @Override
+    public Set<RoleModel> getScopeMappings() {
+        Set<RoleModel> result = new HashSet<RoleModel>();
+        List<MongoRoleEntity> roles = MongoModelUtils.getAllScopesOfClient(this, invocationContext);
+
+        for (MongoRoleEntity role : roles) {
+            if (realm.getId().equals(role.getRealmId())) {
+                result.add(new RoleAdapter(session, realm, role, realm, invocationContext));
+            } else {
+                // Likely applicationRole, but we don't have this application yet
+                result.add(new RoleAdapter(session, realm, role, invocationContext));
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public Set<RoleModel> getRealmScopeMappings() {
+        Set<RoleModel> allScopes = getScopeMappings();
+
+        // Filter to retrieve just realm roles TODO: Maybe improve to avoid filter programmatically... Maybe have separate fields for realmRoles and appRoles on user?
+        Set<RoleModel> realmRoles = new HashSet<RoleModel>();
+        for (RoleModel role : allScopes) {
+            MongoRoleEntity roleEntity = ((RoleAdapter) role).getRole();
+
+            if (realm.getId().equals(roleEntity.getRealmId())) {
+                realmRoles.add(role);
+            }
+        }
+        return realmRoles;
+    }
+
+    @Override
+    public void addScopeMapping(RoleModel role) {
+        getMongoStore().pushItemToList(this.getMongoEntity(), "scopeIds", role.getId(), true, invocationContext);
+    }
+
+    @Override
+    public void deleteScopeMapping(RoleModel role) {
+        getMongoStore().pullItemFromList(this.getMongoEntity(), "scopeIds", role.getId(), invocationContext);
+    }
+
+    @Override
+    public String getProtocol() {
+        return getMongoEntity().getProtocol();
+    }
+
+    @Override
+    public void setProtocol(String protocol) {
+        getMongoEntity().setProtocol(protocol);
+        updateMongoEntity();
+
+    }
+
+    @Override
+    public void setAttribute(String name, String value) {
+        getMongoEntity().getAttributes().put(name, value);
+        updateMongoEntity();
+
+    }
+
+    @Override
+    public void removeAttribute(String name) {
+        getMongoEntity().getAttributes().remove(name);
+        updateMongoEntity();
+    }
+
+    @Override
+    public String getAttribute(String name) {
+        return getMongoEntity().getAttributes().get(name);
+    }
+
+    @Override
+    public Map<String, String> getAttributes() {
+        Map<String, String> copy = new HashMap<String, String>();
+        copy.putAll(getMongoEntity().getAttributes());
+        return copy;
+    }
+
+    @Override
+    public Set<ProtocolMapperModel> getProtocolMappers() {
+        Set<ProtocolMapperModel> result = new HashSet<ProtocolMapperModel>();
+        for (ProtocolMapperEntity entity : getMongoEntity().getProtocolMappers()) {
+            ProtocolMapperModel mapping = new ProtocolMapperModel();
+            mapping.setId(entity.getId());
+            mapping.setName(entity.getName());
+            mapping.setProtocol(entity.getProtocol());
+            mapping.setProtocolMapper(entity.getProtocolMapper());
+            mapping.setConsentRequired(entity.isConsentRequired());
+            mapping.setConsentText(entity.getConsentText());
+            Map<String, String> config = new HashMap<String, String>();
+            if (entity.getConfig() != null) {
+                config.putAll(entity.getConfig());
+            }
+            mapping.setConfig(config);
+            result.add(mapping);
+        }
+        return result;
+    }
+
+    @Override
+    public ProtocolMapperModel addProtocolMapper(ProtocolMapperModel model) {
+        if (getProtocolMapperByName(model.getProtocol(), model.getName()) != null) {
+            throw new RuntimeException("protocol mapper name must be unique per protocol");
+        }
+        ProtocolMapperEntity entity = new ProtocolMapperEntity();
+        entity.setId(KeycloakModelUtils.generateId());
+        entity.setProtocol(model.getProtocol());
+        entity.setName(model.getName());
+        entity.setProtocolMapper(model.getProtocolMapper());
+        entity.setConfig(model.getConfig());
+        entity.setConsentRequired(model.isConsentRequired());
+        entity.setConsentText(model.getConsentText());
+        getMongoEntity().getProtocolMappers().add(entity);
+        updateMongoEntity();
+        return entityToModel(entity);
+    }
+
+    @Override
+    public void removeProtocolMapper(ProtocolMapperModel mapping) {
+        for (ProtocolMapperEntity entity : getMongoEntity().getProtocolMappers()) {
+            if (entity.getId().equals(mapping.getId())) {
+                getMongoEntity().getProtocolMappers().remove(entity);
+                updateMongoEntity();
+                break;
+            }
+        }
+
+    }
+
+    protected ProtocolMapperEntity getProtocolMapperyEntityById(String id) {
+        for (ProtocolMapperEntity entity : getMongoEntity().getProtocolMappers()) {
+            if (entity.getId().equals(id)) {
+                return entity;
+            }
+        }
+        return null;
+
+    }
+    protected ProtocolMapperEntity getProtocolMapperEntityByName(String protocol, String name) {
+        for (ProtocolMapperEntity entity : getMongoEntity().getProtocolMappers()) {
+            if (entity.getProtocol().equals(protocol) && entity.getName().equals(name)) {
+                return entity;
+            }
+        }
+        return null;
+
+    }
+
+
+    @Override
+    public void updateProtocolMapper(ProtocolMapperModel mapping) {
+        ProtocolMapperEntity entity = getProtocolMapperyEntityById(mapping.getId());
+        entity.setProtocolMapper(mapping.getProtocolMapper());
+        entity.setConsentRequired(mapping.isConsentRequired());
+        entity.setConsentText(mapping.getConsentText());
+        if (entity.getConfig() != null) {
+            entity.getConfig().clear();
+            entity.getConfig().putAll(mapping.getConfig());
+        } else {
+            entity.setConfig(mapping.getConfig());
+        }
+        updateMongoEntity();
+
+    }
+
+    @Override
+    public ProtocolMapperModel getProtocolMapperById(String id) {
+        ProtocolMapperEntity entity = getProtocolMapperyEntityById(id);
+        if (entity == null) return null;
+        return entityToModel(entity);
+    }
+
+    @Override
+    public ProtocolMapperModel getProtocolMapperByName(String protocol, String name) {
+        ProtocolMapperEntity entity = getProtocolMapperEntityByName(protocol, name);
+        if (entity == null) return null;
+        return entityToModel(entity);
+    }
+
+    protected ProtocolMapperModel entityToModel(ProtocolMapperEntity entity) {
+        ProtocolMapperModel mapping = new ProtocolMapperModel();
+        mapping.setId(entity.getId());
+        mapping.setName(entity.getName());
+        mapping.setProtocol(entity.getProtocol());
+        mapping.setProtocolMapper(entity.getProtocolMapper());
+        mapping.setConsentRequired(entity.isConsentRequired());
+        mapping.setConsentText(entity.getConsentText());
+        Map<String, String> config = new HashMap<String, String>();
+        if (entity.getConfig() != null) config.putAll(entity.getConfig());
+        mapping.setConfig(config);
+        return mapping;
+    }
+
+
+    @Override
+    public void updateIdentityProviders(List<ClientIdentityProviderMappingModel> identityProviders) {
+        List<ClientIdentityProviderMappingEntity> stored = new ArrayList<ClientIdentityProviderMappingEntity>();
+
+        for (ClientIdentityProviderMappingModel model : identityProviders) {
+            ClientIdentityProviderMappingEntity entity = new ClientIdentityProviderMappingEntity();
+
+            entity.setId(model.getIdentityProvider());
+            entity.setRetrieveToken(model.isRetrieveToken());
+            stored.add(entity);
+        }
+
+        getMongoEntity().setIdentityProviders(stored);
+        updateMongoEntity();
+    }
+
+    @Override
+    public List<ClientIdentityProviderMappingModel> getIdentityProviders() {
+        List<ClientIdentityProviderMappingModel> models = new ArrayList<ClientIdentityProviderMappingModel>();
+
+        for (ClientIdentityProviderMappingEntity entity : getMongoEntity().getIdentityProviders()) {
+            ClientIdentityProviderMappingModel model = new ClientIdentityProviderMappingModel();
+
+            model.setIdentityProvider(entity.getId());
+            model.setRetrieveToken(entity.isRetrieveToken());
+
+            models.add(model);
+        }
+
+        return models;
+    }
+
+    @Override
+    public boolean isAllowedRetrieveTokenFromIdentityProvider(String providerId) {
+        for (ClientIdentityProviderMappingEntity identityProviderMappingModel : getMongoEntity().getIdentityProviders()) {
+            if (identityProviderMappingModel.getId().equals(providerId)) {
+                return identityProviderMappingModel.isRetrieveToken();
+            }
+        }
+
+        return false;
+    }
+
+    @Override
+    public boolean isSurrogateAuthRequired() {
+        return getMongoEntity().isSurrogateAuthRequired();
+    }
+
+    @Override
+    public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
+        getMongoEntity().setSurrogateAuthRequired(surrogateAuthRequired);
+        updateMongoEntity();
+    }
+
+    @Override
+    public String getManagementUrl() {
+        return getMongoEntity().getManagementUrl();
+    }
+
+    @Override
+    public void setManagementUrl(String url) {
+        getMongoEntity().setManagementUrl(url);
+        updateMongoEntity();
+    }
+
+    @Override
+    public void setBaseUrl(String url) {
+        getMongoEntity().setBaseUrl(url);
+        updateMongoEntity();
+    }
+
+    @Override
+    public String getBaseUrl() {
+        return getMongoEntity().getBaseUrl();
+    }
+
+    @Override
+    public boolean isBearerOnly() {
+        return getMongoEntity().isBearerOnly();
+    }
+
+    @Override
+    public void setBearerOnly(boolean only) {
+        getMongoEntity().setBearerOnly(only);
+        updateMongoEntity();
+    }
+
+    @Override
+    public boolean isConsentRequired() {
+        return getMongoEntity().isConsentRequired();
+    }
+
+    @Override
+    public void setConsentRequired(boolean consentRequired) {
+        getMongoEntity().setConsentRequired(consentRequired);
+        updateMongoEntity();
+    }
+
+    @Override
+    public boolean isDirectGrantsOnly() {
+        return getMongoEntity().isDirectGrantsOnly();
+    }
+
+    @Override
+    public void setDirectGrantsOnly(boolean flag) {
+        getMongoEntity().setDirectGrantsOnly(flag);
+        updateMongoEntity();
+    }
+
+    @Override
+    public RoleAdapter getRole(String name) {
+        DBObject query = new QueryBuilder()
+                .and("name").is(name)
+                .and("clientId").is(getId())
+                .get();
+        MongoRoleEntity role = getMongoStore().loadSingleEntity(MongoRoleEntity.class, query, invocationContext);
+        if (role == null) {
+            return null;
+        } else {
+            return new RoleAdapter(session, getRealm(), role, invocationContext);
+        }
+    }
+
+    @Override
+    public RoleAdapter addRole(String name) {
+        return this.addRole(null, name);
+    }
+
+    @Override
+    public RoleAdapter addRole(String id, String name) {
+        MongoRoleEntity roleEntity = new MongoRoleEntity();
+        roleEntity.setId(id);
+        roleEntity.setName(name);
+        roleEntity.setClientId(getId());
+
+        getMongoStore().insertEntity(roleEntity, invocationContext);
+
+        return new RoleAdapter(session, getRealm(), roleEntity, this, invocationContext);
+    }
+
+    @Override
+    public boolean removeRole(RoleModel role) {
+        session.users().preRemove(getRealm(), role);
+        return getMongoStore().removeEntity(MongoRoleEntity.class, role.getId(), invocationContext);
+    }
+
+    @Override
+    public Set<RoleModel> getRoles() {
+        DBObject query = new QueryBuilder()
+                .and("clientId").is(getId())
+                .get();
+        List<MongoRoleEntity> roles = getMongoStore().loadEntities(MongoRoleEntity.class, query, invocationContext);
+
+        Set<RoleModel> result = new HashSet<RoleModel>();
+        for (MongoRoleEntity role : roles) {
+            result.add(new RoleAdapter(session, getRealm(), role, this, invocationContext));
+        }
+
+        return result;
+    }
+
+    @Override
+    public boolean hasScope(RoleModel role) {
+        if (isFullScopeAllowed()) return true;
+        Set<RoleModel> roles = getScopeMappings();
+        if (roles.contains(role)) return true;
+
+        for (RoleModel mapping : roles) {
+            if (mapping.hasRole(role)) return true;
+        }
+
+        roles = getRoles();
+        if (roles.contains(role)) return true;
+
+        for (RoleModel mapping : roles) {
+            if (mapping.hasRole(role)) return true;
+        }
+        return false;
+    }
+
+    @Override
+    public Set<RoleModel> getClientScopeMappings(ClientModel client) {
+        Set<RoleModel> result = new HashSet<RoleModel>();
+        List<MongoRoleEntity> roles = MongoModelUtils.getAllScopesOfClient(client, invocationContext);
+
+        for (MongoRoleEntity role : roles) {
+            if (getId().equals(role.getClientId())) {
+                result.add(new RoleAdapter(session, getRealm(), role, this, invocationContext));
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public List<String> getDefaultRoles() {
+        return getMongoEntity().getDefaultRoles();
+    }
+
+    @Override
+    public void addDefaultRole(String name) {
+        RoleModel role = getRole(name);
+        if (role == null) {
+            addRole(name);
+        }
+
+        getMongoStore().pushItemToList(getMongoEntity(), "defaultRoles", name, true, invocationContext);
+    }
+
+    @Override
+    public void updateDefaultRoles(String[] defaultRoles) {
+        List<String> roleNames = new ArrayList<String>();
+        for (String roleName : defaultRoles) {
+            RoleModel role = getRole(roleName);
+            if (role == null) {
+                addRole(roleName);
+            }
+
+            roleNames.add(roleName);
+        }
+
+        getMongoEntity().setDefaultRoles(roleNames);
+        updateMongoEntity();
+    }
+
+    @Override
+    public int getNodeReRegistrationTimeout() {
+        return getMongoEntity().getNodeReRegistrationTimeout();
+    }
+
+    @Override
+    public void setNodeReRegistrationTimeout(int timeout) {
+        getMongoEntity().setNodeReRegistrationTimeout(timeout);
+        updateMongoEntity();
+    }
+
+    @Override
+    public Map<String, Integer> getRegisteredNodes() {
+        return getMongoEntity().getRegisteredNodes() == null ? Collections.<String, Integer>emptyMap() : Collections.unmodifiableMap(getMongoEntity().getRegisteredNodes());
+    }
+
+    @Override
+    public void registerNode(String nodeHost, int registrationTime) {
+        MongoClientEntity entity = getMongoEntity();
+        if (entity.getRegisteredNodes() == null) {
+            entity.setRegisteredNodes(new HashMap<String, Integer>());
+        }
+
+        entity.getRegisteredNodes().put(nodeHost, registrationTime);
+        updateMongoEntity();
+    }
+
+    @Override
+    public void unregisterNode(String nodeHost) {
+        MongoClientEntity entity = getMongoEntity();
+        if (entity.getRegisteredNodes() == null) return;
+
+        entity.getRegisteredNodes().remove(nodeHost);
+        updateMongoEntity();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof ClientModel)) return false;
+
+        ClientModel that = (ClientModel) o;
+        return that.getId().equals(getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return getId().hashCode();
+    }
+
+
+}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProvider.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProvider.java
index 61865d6..c8bdb38 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProvider.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoRealmProvider.java
@@ -5,14 +5,12 @@ import com.mongodb.DBObject;
 import com.mongodb.QueryBuilder;
 import org.keycloak.connections.mongo.api.MongoStore;
 import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RealmProvider;
 import org.keycloak.models.RoleModel;
-import org.keycloak.models.mongo.keycloak.entities.MongoApplicationEntity;
-import org.keycloak.models.mongo.keycloak.entities.MongoOAuthClientEntity;
+import org.keycloak.models.mongo.keycloak.entities.MongoClientEntity;
 import org.keycloak.models.mongo.keycloak.entities.MongoRealmEntity;
 import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
 import org.keycloak.models.utils.KeycloakModelUtils;
@@ -107,30 +105,20 @@ public class MongoRealmProvider implements RealmProvider {
         MongoRoleEntity role = getMongoStore().loadEntity(MongoRoleEntity.class, id, invocationContext);
         if (role == null) return null;
         if (role.getRealmId() != null && !role.getRealmId().equals(realm.getId())) return null;
-        if (role.getApplicationId() != null && realm.getApplicationById(role.getApplicationId()) == null) return null;
+        if (role.getClientId() != null && realm.getClientById(role.getClientId()) == null) return null;
         return new RoleAdapter(session, realm, role, null, invocationContext);
     }
 
     @Override
-    public ApplicationModel getApplicationById(String id, RealmModel realm) {
-        MongoApplicationEntity appData = getMongoStore().loadEntity(MongoApplicationEntity.class, id, invocationContext);
+    public ClientModel getClientById(String id, RealmModel realm) {
+        MongoClientEntity appData = getMongoStore().loadEntity(MongoClientEntity.class, id, invocationContext);
 
         // Check if application belongs to this realm
         if (appData == null || !realm.getId().equals(appData.getRealmId())) {
             return null;
         }
 
-        return new ApplicationAdapter(session, realm, appData, invocationContext);
-    }
-
-    @Override
-    public OAuthClientModel getOAuthClientById(String id, RealmModel realm) {
-        MongoOAuthClientEntity clientEntity = getMongoStore().loadEntity(MongoOAuthClientEntity.class, id, invocationContext);
-
-        // Check if client belongs to this realm
-        if (clientEntity == null || !realm.getId().equals(clientEntity.getRealmId())) return null;
-
-        return new OAuthClientAdapter(session, realm, clientEntity, invocationContext);
+        return new ClientAdapter(session, realm, appData, invocationContext);
     }
 
 }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java
index bcae24d..862e387 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java
@@ -5,7 +5,7 @@ import com.mongodb.DBObject;
 import com.mongodb.QueryBuilder;
 import org.keycloak.connections.mongo.api.MongoStore;
 import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.CredentialValidationOutput;
 import org.keycloak.models.FederatedIdentityModel;
 import org.keycloak.models.KeycloakSession;
@@ -249,7 +249,7 @@ public class MongoUserProvider implements UserProvider {
                 userModel.grantRole(realm.getRole(r));
             }
 
-            for (ApplicationModel application : realm.getApplications()) {
+            for (ClientModel application : realm.getClients()) {
                 for (String r : application.getDefaultRoles()) {
                     userModel.grantRole(application.getRole(r));
                 }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
index eac9583..d7a534a 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
@@ -4,12 +4,10 @@ import com.mongodb.DBObject;
 import com.mongodb.QueryBuilder;
 import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
 import org.keycloak.enums.SslRequired;
-import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.IdentityProviderMapperModel;
 import org.keycloak.models.IdentityProviderModel;
 import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.PasswordPolicy;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RealmProvider;
@@ -20,8 +18,7 @@ import org.keycloak.models.entities.IdentityProviderEntity;
 import org.keycloak.models.entities.IdentityProviderMapperEntity;
 import org.keycloak.models.entities.RequiredCredentialEntity;
 import org.keycloak.models.entities.UserFederationProviderEntity;
-import org.keycloak.models.mongo.keycloak.entities.MongoApplicationEntity;
-import org.keycloak.models.mongo.keycloak.entities.MongoOAuthClientEntity;
+import org.keycloak.models.mongo.keycloak.entities.MongoClientEntity;
 import org.keycloak.models.mongo.keycloak.entities.MongoRealmEntity;
 import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
 import org.keycloak.models.utils.KeycloakModelUtils;
@@ -579,113 +576,59 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
     }
 
     @Override
-    public ClientModel findClient(String clientId) {
-        ClientModel model = getApplicationByName(clientId);
-        if (model != null) return model;
-        return getOAuthClient(clientId);
+    public ClientModel getClientById(String id) {
+        return model.getClientById(id, this);
     }
 
     @Override
-    public ClientModel findClientById(String id) {
-        ClientModel model = getApplicationById(id);
-        if (model != null) return model;
-        return getOAuthClientById(id);
-    }
-
-
-
-    @Override
-    public ApplicationModel getApplicationById(String id) {
-        return model.getApplicationById(id, this);
-    }
-
-    @Override
-    public ApplicationModel getApplicationByName(String name) {
+    public ClientModel getClientByClientId(String clientId) {
         DBObject query = new QueryBuilder()
                 .and("realmId").is(getId())
-                .and("name").is(name)
+                .and("clientId").is(clientId)
                 .get();
-        MongoApplicationEntity appEntity = getMongoStore().loadSingleEntity(MongoApplicationEntity.class, query, invocationContext);
-        return appEntity == null ? null : new ApplicationAdapter(session, this, appEntity, invocationContext);
+        MongoClientEntity appEntity = getMongoStore().loadSingleEntity(MongoClientEntity.class, query, invocationContext);
+        return appEntity == null ? null : new ClientAdapter(session, this, appEntity, invocationContext);
     }
 
     @Override
-    public Map<String, ApplicationModel> getApplicationNameMap() {
-        Map<String, ApplicationModel> resourceMap = new HashMap<String, ApplicationModel>();
-        for (ApplicationModel resource : getApplications()) {
-            resourceMap.put(resource.getName(), resource);
+    public Map<String, ClientModel> getClientNameMap() {
+        Map<String, ClientModel> resourceMap = new HashMap<String, ClientModel>();
+        for (ClientModel resource : getClients()) {
+            resourceMap.put(resource.getClientId(), resource);
         }
         return resourceMap;
     }
 
     @Override
-    public List<ApplicationModel> getApplications() {
+    public List<ClientModel> getClients() {
         DBObject query = new QueryBuilder()
                 .and("realmId").is(getId())
                 .get();
-        List<MongoApplicationEntity> appDatas = getMongoStore().loadEntities(MongoApplicationEntity.class, query, invocationContext);
+        List<MongoClientEntity> appDatas = getMongoStore().loadEntities(MongoClientEntity.class, query, invocationContext);
 
-        List<ApplicationModel> result = new ArrayList<ApplicationModel>();
-        for (MongoApplicationEntity appData : appDatas) {
-            result.add(new ApplicationAdapter(session, this, appData, invocationContext));
+        List<ClientModel> result = new ArrayList<ClientModel>();
+        for (MongoClientEntity appData : appDatas) {
+            result.add(new ClientAdapter(session, this, appData, invocationContext));
         }
         return result;
     }
 
     @Override
-    public ApplicationModel addApplication(String name) {
-        return this.addApplication(null, name);
+    public ClientModel addClient(String name) {
+        return this.addClient(null, name);
     }
 
     @Override
-    public ApplicationModel addApplication(String id, String name) {
-        MongoApplicationEntity appData = new MongoApplicationEntity();
+    public ClientModel addClient(String id, String clientId) {
+        MongoClientEntity appData = new MongoClientEntity();
         appData.setId(id);
-        appData.setName(name);
+        appData.setClientId(clientId);
         appData.setRealmId(getId());
         appData.setEnabled(true);
         getMongoStore().insertEntity(appData, invocationContext);
 
-        final ApplicationModel model = new ApplicationAdapter(session, this, appData, invocationContext);
-        session.getKeycloakSessionFactory().publish(new ApplicationCreationEvent() {
-            @Override
-            public ApplicationModel getCreatedApplication() {
-                return model;
-            }
-
-            @Override
-            public ClientModel getCreatedClient() {
-                return model;
-            }
-        });
-        return model;
-    }
-
-    @Override
-    public boolean removeApplication(String id) {
-        return getMongoStore().removeEntity(MongoApplicationEntity.class, id, invocationContext);
-    }
-
-    @Override
-    public OAuthClientModel addOAuthClient(String name) {
-        return this.addOAuthClient(null, name);
-    }
-
-    @Override
-    public OAuthClientModel addOAuthClient(String id, String name) {
-        MongoOAuthClientEntity oauthClient = new MongoOAuthClientEntity();
-        oauthClient.setId(id);
-        oauthClient.setRealmId(getId());
-        oauthClient.setName(name);
-        getMongoStore().insertEntity(oauthClient, invocationContext);
-
-        final OAuthClientAdapter model = new OAuthClientAdapter(session, this, oauthClient, invocationContext);
-        session.getKeycloakSessionFactory().publish(new OAuthClientCreationEvent() {
-            @Override
-            public OAuthClientModel getCreatedOAuthClient() {
-                return model;
-            }
-
+        final ClientModel model = new ClientAdapter(session, this, appData, invocationContext);
+        session.getKeycloakSessionFactory().publish(new ClientCreationEvent() {
             @Override
             public ClientModel getCreatedClient() {
                 return model;
@@ -695,36 +638,8 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
     }
 
     @Override
-    public boolean removeOAuthClient(String id) {
-        return getMongoStore().removeEntity(MongoOAuthClientEntity.class, id, invocationContext);
-    }
-
-    @Override
-    public OAuthClientModel getOAuthClient(String name) {
-        DBObject query = new QueryBuilder()
-                .and("realmId").is(getId())
-                .and("name").is(name)
-                .get();
-        MongoOAuthClientEntity oauthClient = getMongoStore().loadSingleEntity(MongoOAuthClientEntity.class, query, invocationContext);
-        return oauthClient == null ? null : new OAuthClientAdapter(session, this, oauthClient, invocationContext);
-    }
-
-    @Override
-    public OAuthClientModel getOAuthClientById(String id) {
-        return model.getOAuthClientById(id, this);
-    }
-
-    @Override
-    public List<OAuthClientModel> getOAuthClients() {
-        DBObject query = new QueryBuilder()
-                .and("realmId").is(getId())
-                .get();
-        List<MongoOAuthClientEntity> results = getMongoStore().loadEntities(MongoOAuthClientEntity.class, query, invocationContext);
-        List<OAuthClientModel> list = new ArrayList<OAuthClientModel>();
-        for (MongoOAuthClientEntity data : results) {
-            list.add(new OAuthClientAdapter(session, this, data, invocationContext));
-        }
-        return list;
+    public boolean removeClient(String id) {
+        return getMongoStore().removeEntity(MongoClientEntity.class, id, invocationContext);
     }
 
     @Override
@@ -1063,14 +978,14 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
     }
 
     @Override
-    public ApplicationModel getMasterAdminApp() {
-        MongoApplicationEntity appData = getMongoStore().loadEntity(MongoApplicationEntity.class, realm.getAdminAppId(), invocationContext);
-        return appData != null ? new ApplicationAdapter(session, this, appData, invocationContext) : null;
+    public ClientModel getMasterAdminClient() {
+        MongoClientEntity appData = getMongoStore().loadEntity(MongoClientEntity.class, realm.getAdminAppId(), invocationContext);
+        return appData != null ? new ClientAdapter(session, this, appData, invocationContext) : null;
     }
 
     @Override
-    public void setMasterAdminApp(ApplicationModel app) {
-        String adminAppId = app != null ? app.getId() : null;
+    public void setMasterAdminClient(ClientModel client) {
+        String adminAppId = client != null ? client.getId() : null;
         realm.setAdminAppId(adminAppId);
         updateRealm();
     }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RoleAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RoleAdapter.java
index c2a8317..91ef361 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RoleAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RoleAdapter.java
@@ -7,7 +7,7 @@ import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleContainerModel;
 import org.keycloak.models.RoleModel;
-import org.keycloak.models.mongo.keycloak.entities.MongoApplicationEntity;
+import org.keycloak.models.mongo.keycloak.entities.MongoClientEntity;
 import org.keycloak.models.mongo.keycloak.entities.MongoRealmEntity;
 import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
 import org.keycloak.models.utils.KeycloakModelUtils;
@@ -115,14 +115,14 @@ public class RoleAdapter extends AbstractMongoAdapter<MongoRoleEntity> implement
                     throw new IllegalStateException("Realm with id: " + role.getRealmId() + " doesn't exists");
                 }
                 roleContainer = new RealmAdapter(session, realm, invocationContext);
-            } else if (role.getApplicationId() != null) {
-                MongoApplicationEntity appEntity = getMongoStore().loadEntity(MongoApplicationEntity.class, role.getApplicationId(), invocationContext);
+            } else if (role.getClientId() != null) {
+                MongoClientEntity appEntity = getMongoStore().loadEntity(MongoClientEntity.class, role.getClientId(), invocationContext);
                 if (appEntity == null) {
-                    throw new IllegalStateException("Application with id: " + role.getApplicationId() + " doesn't exists");
+                    throw new IllegalStateException("Application with id: " + role.getClientId() + " doesn't exists");
                 }
-                roleContainer = new ApplicationAdapter(session, realm, appEntity, invocationContext);
+                roleContainer = new ClientAdapter(session, realm, appEntity, invocationContext);
             } else {
-                throw new IllegalStateException("Both realmId and applicationId are null for role: " + this);
+                throw new IllegalStateException("Both realmId and clientId are null for role: " + this);
             }
         }
         return roleContainer;
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java
index da26379..874f7d8 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java
@@ -1,7 +1,7 @@
 package org.keycloak.models.mongo.keycloak.adapters;
 
 import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.PasswordPolicy;
 import org.keycloak.models.RealmModel;
@@ -316,12 +316,12 @@ public class UserAdapter extends AbstractMongoAdapter<MongoUserEntity> implement
     }
 
     @Override
-    public Set<RoleModel> getApplicationRoleMappings(ApplicationModel app) {
+    public Set<RoleModel> getClientRoleMappings(ClientModel app) {
         Set<RoleModel> result = new HashSet<RoleModel>();
         List<MongoRoleEntity> roles = MongoModelUtils.getAllRolesOfUser(this, invocationContext);
 
         for (MongoRoleEntity role : roles) {
-            if (app.getId().equals(role.getApplicationId())) {
+            if (app.getId().equals(role.getClientId())) {
                 result.add(new RoleAdapter(session, realm, role, app, invocationContext));
             }
         }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRealmEntity.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRealmEntity.java
index 2784352..2209751 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRealmEntity.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRealmEntity.java
@@ -26,9 +26,6 @@ public class MongoRealmEntity extends RealmEntity implements MongoIdentifiableEn
         context.getMongoStore().removeEntities(MongoRoleEntity.class, query, context);
 
         // Remove all applications of this realm
-        context.getMongoStore().removeEntities(MongoApplicationEntity.class, query, context);
-
-        // Remove all clients of this realm
-        context.getMongoStore().removeEntities(MongoOAuthClientEntity.class, query, context);
+        context.getMongoStore().removeEntities(MongoClientEntity.class, query, context);
     }
 }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRoleEntity.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRoleEntity.java
index 4b4e80f..dc820c2 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRoleEntity.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRoleEntity.java
@@ -24,13 +24,13 @@ public class MongoRoleEntity extends RoleEntity implements MongoIdentifiableEnti
     // TODO This is required as Mongo doesn't support sparse indexes with compound keys (see https://jira.mongodb.org/browse/SERVER-2193)
     public String getNameIndex() {
         String realmId = getRealmId();
-        String applicationId = getApplicationId();
+        String clientId = getClientId();
         String name = getName();
 
         if (realmId != null) {
             return realmId + "//" + name;
         } else {
-            return applicationId + "//" + name;
+            return clientId + "//" + name;
         }
     }
 
@@ -74,8 +74,8 @@ public class MongoRoleEntity extends RoleEntity implements MongoIdentifiableEnti
         }
 
         // Remove defaultRoles from application
-        if (getApplicationId() != null) {
-            MongoApplicationEntity appEntity = mongoStore.loadEntity(MongoApplicationEntity.class, getApplicationId(), invContext);
+        if (getClientId() != null) {
+            MongoClientEntity appEntity = mongoStore.loadEntity(MongoClientEntity.class, getClientId(), invContext);
 
             // Application might be already removed at this point
             if (appEntity != null) {
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/utils/MongoModelUtils.java b/model/mongo/src/main/java/org/keycloak/models/mongo/utils/MongoModelUtils.java
index 63f0bfd..48828de 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/utils/MongoModelUtils.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/utils/MongoModelUtils.java
@@ -36,7 +36,7 @@ public class MongoModelUtils {
 
     // Get everything including both application and realm scopes
     public static List<MongoRoleEntity> getAllScopesOfClient(ClientModel client, MongoStoreInvocationContext invContext) {
-        ClientEntity scopedEntity = ((ClientAdapter)client).getMongoEntityAsClient();
+        ClientEntity scopedEntity = ((ClientAdapter)client).getMongoEntity();
         List<String> scopeIds = scopedEntity.getScopeIds();
 
         if (scopeIds == null || scopeIds.isEmpty()) {
diff --git a/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/ClientSessionAdapter.java b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/ClientSessionAdapter.java
index 645a76f..e380441 100644
--- a/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/ClientSessionAdapter.java
+++ b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/ClientSessionAdapter.java
@@ -43,7 +43,7 @@ public class ClientSessionAdapter implements ClientSessionModel {
 
     @Override
     public ClientModel getClient() {
-        return realm.findClientById(entity.getClient());
+        return realm.getClientById(entity.getClient());
     }
 
     @Override
diff --git a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/ClientSessionAdapter.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/ClientSessionAdapter.java
index 18b0332..ebb47b6 100755
--- a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/ClientSessionAdapter.java
+++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/ClientSessionAdapter.java
@@ -82,7 +82,7 @@ public class ClientSessionAdapter implements ClientSessionModel {
 
     @Override
     public ClientModel getClient() {
-        return realm.findClientById(entity.getClientId());
+        return realm.getClientById(entity.getClientId());
     }
 
     @Override
diff --git a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/JpaUserSessionProvider.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/JpaUserSessionProvider.java
index d70c326..0731de3 100755
--- a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/JpaUserSessionProvider.java
+++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/JpaUserSessionProvider.java
@@ -20,7 +20,6 @@ import javax.persistence.EntityManager;
 import javax.persistence.TypedQuery;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
diff --git a/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/ClientSessionAdapter.java b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/ClientSessionAdapter.java
index 9981fb7..62a3246 100755
--- a/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/ClientSessionAdapter.java
+++ b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/ClientSessionAdapter.java
@@ -41,7 +41,7 @@ public class ClientSessionAdapter implements ClientSessionModel {
 
     @Override
     public ClientModel getClient() {
-        return realm.findClientById(entity.getClientId());
+        return realm.getClientById(entity.getClientId());
     }
 
     @Override
diff --git a/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/MemUserSessionProvider.java b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/MemUserSessionProvider.java
index c185a0b..67a2180 100755
--- a/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/MemUserSessionProvider.java
+++ b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/MemUserSessionProvider.java
@@ -25,7 +25,6 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CopyOnWriteArraySet;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
diff --git a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/ClientSessionAdapter.java b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/ClientSessionAdapter.java
index 2ab8630..12efd4a 100755
--- a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/ClientSessionAdapter.java
+++ b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/ClientSessionAdapter.java
@@ -44,7 +44,7 @@ public class ClientSessionAdapter extends AbstractMongoAdapter<MongoClientSessio
 
     @Override
     public ClientModel getClient() {
-        return realm.findClientById(entity.getClientId());
+        return realm.getClientById(entity.getClientId());
     }
 
     @Override

pom.xml 1(+0 -1)

diff --git a/pom.xml b/pom.xml
index f3f68b0..87ac607 100755
--- a/pom.xml
+++ b/pom.xml
@@ -114,7 +114,6 @@
         <module>model</module>
         <module>integration</module>
         <module>proxy</module>
-        <module>picketlink</module>
         <module>federation</module>
         <module>services</module>
         <module>saml</module>
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporter.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporter.java
index 32f0990..1ad72bf 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporter.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporter.java
@@ -1,6 +1,6 @@
 package org.keycloak.protocol.saml;
 
-import org.keycloak.exportimport.ApplicationImporter;
+import org.keycloak.exportimport.ClientImporter;
 import org.keycloak.models.RealmModel;
 import org.keycloak.services.resources.admin.RealmAuth;
 
@@ -8,7 +8,7 @@ import org.keycloak.services.resources.admin.RealmAuth;
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public class EntityDescriptorImporter implements ApplicationImporter {
+public class EntityDescriptorImporter implements ClientImporter {
     @Override
     public Object createJaxrsService(RealmModel realm, RealmAuth auth) {
         return new EntityDescriptorImporterService(realm, auth);
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporterFactory.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporterFactory.java
index 51644d9..14af685 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporterFactory.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporterFactory.java
@@ -1,8 +1,8 @@
 package org.keycloak.protocol.saml;
 
 import org.keycloak.Config;
-import org.keycloak.exportimport.ApplicationImporter;
-import org.keycloak.exportimport.ApplicationImporterFactory;
+import org.keycloak.exportimport.ClientImporter;
+import org.keycloak.exportimport.ClientImporterFactory;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
 
@@ -10,14 +10,14 @@ import org.keycloak.models.KeycloakSessionFactory;
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public class EntityDescriptorImporterFactory implements ApplicationImporterFactory {
+public class EntityDescriptorImporterFactory implements ClientImporterFactory {
     @Override
     public String getDisplayName() {
         return "SAML 2.0 Entity Descriptor";
     }
 
     @Override
-    public ApplicationImporter create(KeycloakSession session) {
+    public ClientImporter create(KeycloakSession session) {
         return new EntityDescriptorImporter();
     }
 
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporterService.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporterService.java
index 68a7412..4ef05ea 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporterService.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/EntityDescriptorImporterService.java
@@ -2,7 +2,7 @@ package org.keycloak.protocol.saml;
 
 import org.jboss.resteasy.plugins.providers.multipart.InputPart;
 import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.services.resources.admin.RealmAuth;
@@ -79,7 +79,7 @@ public class EntityDescriptorImporterService {
         for (Object o : entities.getEntityDescriptor()) {
             EntityDescriptorType entity = (EntityDescriptorType)o;
             String entityId = entity.getEntityID();
-            ApplicationModel app = realm.addApplication(entityId);
+            ClientModel app = realm.addClient(entityId);
             app.setFullScopeAllowed(true);
             app.setProtocol(SamlProtocol.LOGIN_PROTOCOL);
             app.setAttribute(SamlProtocol.SAML_SERVER_SIGNATURE, SamlProtocol.ATTRIBUTE_TRUE_VALUE); // default to true
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/RoleNameMapper.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/RoleNameMapper.java
index 1cbf936..e47ca3d 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/RoleNameMapper.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/RoleNameMapper.java
@@ -1,6 +1,6 @@
 package org.keycloak.protocol.saml.mappers;
 
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.ProtocolMapperModel;
 import org.keycloak.models.RoleContainerModel;
 import org.keycloak.models.RoleModel;
@@ -73,9 +73,9 @@ public class RoleNameMapper extends AbstractOIDCProtocolMapper implements SAMLRo
     @Override
     public String mapName(ProtocolMapperModel model, RoleModel roleModel) {
         RoleContainerModel container = roleModel.getContainer();
-        ApplicationModel app = null;
-        if (container instanceof ApplicationModel) {
-            app = ((ApplicationModel) container);
+        ClientModel app = null;
+        if (container instanceof ClientModel) {
+            app = ((ClientModel) container);
         }
         String role = model.getConfig().get(ROLE_CONFIG);
         String newName = model.getConfig().get(NEW_ROLE_NAME);
@@ -84,7 +84,7 @@ public class RoleNameMapper extends AbstractOIDCProtocolMapper implements SAMLRo
         if (scopeIndex > -1) {
             if (app == null) return null;
             appName = role.substring(0, scopeIndex);
-            if (!app.getName().equals(appName)) return null;
+            if (!app.getClientId().equals(appName)) return null;
             role = role.substring(scopeIndex + 1);
         } else {
             if (app != null) return null;
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
index 3c3ada6..b38d5b9 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
@@ -4,8 +4,10 @@ import org.jboss.logging.Logger;
 import org.jboss.resteasy.client.ClientRequest;
 import org.jboss.resteasy.client.ClientResponse;
 import org.jboss.resteasy.client.core.executors.ApacheHttpClient4Executor;
+import org.keycloak.dom.saml.v2.assertion.AssertionType;
+import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
+import org.keycloak.dom.saml.v2.protocol.ResponseType;
 import org.keycloak.events.EventBuilder;
-import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.KeycloakSession;
@@ -18,20 +20,17 @@ import org.keycloak.protocol.ProtocolMapper;
 import org.keycloak.protocol.saml.mappers.SAMLAttributeStatementMapper;
 import org.keycloak.protocol.saml.mappers.SAMLLoginResponseMapper;
 import org.keycloak.protocol.saml.mappers.SAMLRoleListMapper;
+import org.keycloak.saml.common.constants.GeneralConstants;
+import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
+import org.keycloak.saml.common.exceptions.ConfigurationException;
+import org.keycloak.saml.common.exceptions.ParsingException;
+import org.keycloak.saml.common.exceptions.ProcessingException;
 import org.keycloak.services.managers.ClientSessionCode;
 import org.keycloak.services.managers.ResourceAdminManager;
 import org.keycloak.services.messages.Messages;
 import org.keycloak.services.resources.RealmsResource;
 import org.keycloak.services.resources.admin.ClientAttributeCertificateResource;
 import org.keycloak.services.resources.flows.Flows;
-import org.keycloak.saml.common.constants.GeneralConstants;
-import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
-import org.keycloak.saml.common.exceptions.ConfigurationException;
-import org.keycloak.saml.common.exceptions.ParsingException;
-import org.keycloak.saml.common.exceptions.ProcessingException;
-import org.keycloak.dom.saml.v2.assertion.AssertionType;
-import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
-import org.keycloak.dom.saml.v2.protocol.ResponseType;
 import org.w3c.dom.Document;
 
 import javax.ws.rs.core.HttpHeaders;
@@ -429,7 +428,7 @@ public class SamlProtocol implements LoginProtocol {
         } else {
             logoutServiceUrl = client.getAttribute(SAML_SINGLE_LOGOUT_SERVICE_URL_REDIRECT_ATTRIBUTE);
         }
-        if (logoutServiceUrl == null && client instanceof ApplicationModel) logoutServiceUrl = ((ApplicationModel)client).getManagementUrl();
+        if (logoutServiceUrl == null && client instanceof ClientModel) logoutServiceUrl = ((ClientModel)client).getManagementUrl();
         if (logoutServiceUrl == null || logoutServiceUrl.trim().equals("")) return null;
         return ResourceAdminManager.resolveUri(uriInfo.getRequestUri(), logoutServiceUrl);
 
@@ -438,7 +437,7 @@ public class SamlProtocol implements LoginProtocol {
     @Override
     public Response frontchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession) {
         ClientModel client = clientSession.getClient();
-        if (!(client instanceof ApplicationModel)) return null;
+        if (!(client instanceof ClientModel)) return null;
         try {
             if (isLogoutPostBindingForClient(clientSession)) {
                 String bindingUri = getLogoutServiceUrl(uriInfo, client, SAML_POST_BINDING);
@@ -500,8 +499,6 @@ public class SamlProtocol implements LoginProtocol {
     @Override
     public void backchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession) {
         ClientModel client = clientSession.getClient();
-        if (!(client instanceof ApplicationModel)) return;
-        ApplicationModel app = (ApplicationModel)client;
         String logoutUrl = getLogoutServiceUrl(uriInfo, client, SAML_POST_BINDING);
         if (logoutUrl == null) {
             logger.warnv("Can't do backchannel logout. No SingleLogoutService POST Binding registered for client: {1}", client.getClientId());
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolUtils.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolUtils.java
index 6a4c313..11007c8 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolUtils.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocolUtils.java
@@ -2,11 +2,11 @@ package org.keycloak.protocol.saml;
 
 import org.keycloak.VerificationException;
 import org.keycloak.models.ClientModel;
-import org.keycloak.util.PemUtils;
 import org.keycloak.saml.common.constants.GeneralConstants;
 import org.keycloak.saml.common.exceptions.ProcessingException;
 import org.keycloak.saml.processing.api.saml.v2.sig.SAML2Signature;
 import org.keycloak.saml.processing.web.util.RedirectBindingUtil;
+import org.keycloak.util.PemUtils;
 import org.w3c.dom.Document;
 
 import javax.ws.rs.core.MultivaluedMap;
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java
index b6dfebb..3b1ff99 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java
@@ -11,7 +11,6 @@ import org.keycloak.events.Errors;
 import org.keycloak.events.EventBuilder;
 import org.keycloak.events.EventType;
 import org.keycloak.login.LoginFormsProvider;
-import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.KeycloakSession;
@@ -165,7 +164,7 @@ public class SamlService {
 
             RequestAbstractType requestAbstractType = (RequestAbstractType)samlObject;
             String issuer = requestAbstractType.getIssuer().getValue();
-            ClientModel client = realm.findClient(issuer);
+            ClientModel client = realm.getClientByClientId(issuer);
 
             if (client == null) {
                 event.event(EventType.LOGIN);
@@ -178,7 +177,7 @@ public class SamlService {
                 event.error(Errors.CLIENT_DISABLED);
                 return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.LOGIN_REQUESTER_NOT_ENABLED);
             }
-            if ((client instanceof ApplicationModel) && ((ApplicationModel)client).isBearerOnly()) {
+            if ((client instanceof ClientModel) && ((ClientModel)client).isBearerOnly()) {
                 event.event(EventType.LOGIN);
                 event.error(Errors.NOT_ALLOWED);
                 return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.BEARER_ONLY);
@@ -241,8 +240,8 @@ public class SamlService {
                 } else {
                     redirect = client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_REDIRECT_ATTRIBUTE);
                 }
-                if (redirect == null && client instanceof ApplicationModel) {
-                    redirect = ((ApplicationModel)client).getManagementUrl();
+                if (redirect == null && client instanceof ClientModel) {
+                    redirect = ((ClientModel)client).getManagementUrl();
                 }
 
             }
@@ -368,8 +367,8 @@ public class SamlService {
 
             String redirectUri = null;
 
-            if (client instanceof ApplicationModel) {
-                redirectUri = ((ApplicationModel)client).getBaseUrl();
+            if (client instanceof ClientModel) {
+                redirectUri = ((ClientModel)client).getBaseUrl();
             }
 
             if (redirectUri != null) {
@@ -404,7 +403,6 @@ public class SamlService {
 
     protected class PostBindingProtocol extends BindingProtocol {
 
-
         @Override
         protected void verifySignature(SAMLDocumentHolder documentHolder, ClientModel client) throws VerificationException {
             SamlProtocolUtils.verifyDocumentSignature(client, documentHolder.getSamlDocument());

services/pom.xml 6(+0 -6)

diff --git a/services/pom.xml b/services/pom.xml
index e5fde97..ea6e90e 100755
--- a/services/pom.xml
+++ b/services/pom.xml
@@ -103,12 +103,6 @@
             <scope>provided</scope>
         </dependency>
         <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-picketlink-api</artifactId>
-            <version>${project.version}</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
             <groupId>org.jboss.spec.javax.servlet</groupId>
             <artifactId>jboss-servlet-api_3.0_spec</artifactId>
             <scope>provided</scope>
diff --git a/services/src/main/java/org/keycloak/protocol/AbstractLoginProtocolFactory.java b/services/src/main/java/org/keycloak/protocol/AbstractLoginProtocolFactory.java
index f009c6b..aa86a26 100755
--- a/services/src/main/java/org/keycloak/protocol/AbstractLoginProtocolFactory.java
+++ b/services/src/main/java/org/keycloak/protocol/AbstractLoginProtocolFactory.java
@@ -1,24 +1,18 @@
 package org.keycloak.protocol;
 
-import org.jboss.logging.Logger;
 import org.keycloak.Config;
 import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
 import org.keycloak.models.RealmModel;
 import org.keycloak.provider.ProviderEvent;
 import org.keycloak.provider.ProviderEventListener;
 
-import java.util.List;
-
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
 public abstract class AbstractLoginProtocolFactory implements LoginProtocolFactory {
 
-    private static final Logger logger = Logger.getLogger(AbstractLoginProtocolFactory.class);
-
     @Override
     public void init(Config.Scope config) {
     }
@@ -34,8 +28,6 @@ public abstract class AbstractLoginProtocolFactory implements LoginProtocolFacto
                 }
             }
         });
-
-
     }
 
     protected abstract void addDefaults(ClientModel realm);
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
index dfe6b2f..e33cb67 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
@@ -11,7 +11,6 @@ import org.keycloak.events.Errors;
 import org.keycloak.events.EventBuilder;
 import org.keycloak.events.EventType;
 import org.keycloak.login.LoginFormsProvider;
-import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.IdentityProviderModel;
@@ -168,13 +167,13 @@ public class AuthorizationEndpoint {
 
         event.client(clientId);
 
-        client = realm.findClient(clientId);
+        client = realm.getClientByClientId(clientId);
         if (client == null) {
             event.error(Errors.CLIENT_NOT_FOUND);
             throw new ErrorPageException(session, realm, uriInfo, headers, Messages.CLIENT_NOT_FOUND );
         }
 
-        if ((client instanceof ApplicationModel) && ((ApplicationModel) client).isBearerOnly()) {
+        if ((client instanceof ClientModel) && ((ClientModel) client).isBearerOnly()) {
             event.error(Errors.NOT_ALLOWED);
             throw new ErrorPageException(session, realm, uriInfo, headers, Messages.BEARER_ONLY );
         }
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LoginStatusIframeEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LoginStatusIframeEndpoint.java
index 30359d1..156ee44 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LoginStatusIframeEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LoginStatusIframeEndpoint.java
@@ -42,7 +42,7 @@ public class LoginStatusIframeEndpoint {
             throw new BadRequestException("Invalid origin");
         }
 
-        ClientModel client = realm.findClient(client_id);
+        ClientModel client = realm.getClientByClientId(client_id);
         if (client == null) {
             throw new NotFoundException("could not find client");
         }
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java
index a61c811..5bab0e0 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java
@@ -10,7 +10,6 @@ import org.keycloak.events.Details;
 import org.keycloak.events.Errors;
 import org.keycloak.events.EventBuilder;
 import org.keycloak.events.EventType;
-import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
@@ -146,9 +145,9 @@ public class LogoutEndpoint {
      * authenticate the client if it is not public.
      *
      * If the client is a confidential client
-     * you must include the client-id (application name or oauth client name) and secret in an Basic Auth Authorization header.
+     * you must include the client-id and secret in an Basic Auth Authorization header.
      *
-     * If the client is a public client, then you must include a "client_id" form parameter with the app's or oauth client's name.
+     * If the client is a public client, then you must include a "client_id" form parameter.
      *
      * returns 204 if successful, 400 if not with a json error response.
      *
@@ -191,7 +190,7 @@ public class LogoutEndpoint {
     private ClientModel authorizeClient(String authorizationHeader, MultivaluedMap<String, String> formData, EventBuilder event) {
         ClientModel client = AuthorizeClientUtil.authorizeClient(authorizationHeader, formData, event, realm);
 
-        if ( (client instanceof ApplicationModel) && ((ApplicationModel)client).isBearerOnly()) {
+        if ( (client instanceof ClientModel) && ((ClientModel)client).isBearerOnly()) {
             throw new ErrorResponseException("invalid_client", "Bearer-only not allowed", Response.Status.BAD_REQUEST);
         }
 
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java
index bd211e4..60b1b98 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java
@@ -10,7 +10,6 @@ import org.keycloak.events.Details;
 import org.keycloak.events.Errors;
 import org.keycloak.events.EventBuilder;
 import org.keycloak.events.EventType;
-import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.KeycloakSession;
@@ -20,7 +19,6 @@ import org.keycloak.models.UserSessionModel;
 import org.keycloak.models.UserSessionProvider;
 import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.protocol.oidc.OIDCLoginProtocol;
-import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.protocol.oidc.TokenManager;
 import org.keycloak.protocol.oidc.utils.AuthorizeClientUtil;
 import org.keycloak.representations.AccessToken;
@@ -31,7 +29,6 @@ import org.keycloak.services.managers.ClientSessionCode;
 import org.keycloak.services.resources.Cors;
 import org.keycloak.services.resources.flows.Urls;
 
-import javax.ws.rs.Consumes;
 import javax.ws.rs.OPTIONS;
 import javax.ws.rs.POST;
 import javax.ws.rs.core.Context;
@@ -147,7 +144,7 @@ public class TokenEndpoint {
         String authorizationHeader = headers.getRequestHeaders().getFirst(HttpHeaders.AUTHORIZATION);
         client = AuthorizeClientUtil.authorizeClient(authorizationHeader, formParams, event, realm);
 
-        if ((client instanceof ApplicationModel) && ((ApplicationModel) client).isBearerOnly()) {
+        if ((client instanceof ClientModel) && ((ClientModel) client).isBearerOnly()) {
             throw new ErrorResponseException("invalid_client", "Bearer-only not allowed", Response.Status.BAD_REQUEST);
         }
     }
@@ -234,15 +231,15 @@ public class TokenEndpoint {
             throw new ErrorResponseException("invalid_grant", "Session not active", Response.Status.BAD_REQUEST);
         }
 
-        String adapterSessionId = formParams.getFirst(AdapterConstants.APPLICATION_SESSION_STATE);
+        String adapterSessionId = formParams.getFirst(AdapterConstants.CLIENT_SESSION_STATE);
         if (adapterSessionId != null) {
-            String adapterSessionHost = formParams.getFirst(AdapterConstants.APPLICATION_SESSION_HOST);
+            String adapterSessionHost = formParams.getFirst(AdapterConstants.CLIENT_SESSION_HOST);
             logger.debugf("Adapter Session '%s' saved in ClientSession for client '%s'. Host is '%s'", adapterSessionId, client.getClientId(), adapterSessionHost);
 
-            event.detail(AdapterConstants.APPLICATION_SESSION_STATE, adapterSessionId);
-            clientSession.setNote(AdapterConstants.APPLICATION_SESSION_STATE, adapterSessionId);
-            event.detail(AdapterConstants.APPLICATION_SESSION_HOST, adapterSessionHost);
-            clientSession.setNote(AdapterConstants.APPLICATION_SESSION_HOST, adapterSessionHost);
+            event.detail(AdapterConstants.CLIENT_SESSION_STATE, adapterSessionId);
+            clientSession.setNote(AdapterConstants.CLIENT_SESSION_STATE, adapterSessionId);
+            event.detail(AdapterConstants.CLIENT_SESSION_HOST, adapterSessionHost);
+            clientSession.setNote(AdapterConstants.CLIENT_SESSION_HOST, adapterSessionHost);
         }
 
         AccessToken token = tokenManager.createClientAccessToken(session, accessCode.getRequestedRoles(), realm, client, user, userSession, clientSession);
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java
index e4f5c41..ba2f99c 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java
@@ -122,7 +122,7 @@ public class UserInfoEndpoint {
         }
 
         UserSessionModel userSession = session.sessions().getUserSession(realm, token.getSessionState());
-        ClientModel clientModel = realm.findClient(token.getIssuedFor());
+        ClientModel clientModel = realm.getClientByClientId(token.getIssuedFor());
         UserModel userModel = userSession.getUser();
         AccessToken userInfo = new AccessToken();
         tokenManager.transformAccessToken(session, userInfo, realm, clientModel, userModel, userSession, null);
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/ValidateTokenEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/ValidateTokenEndpoint.java
index 31499d1..249aa30 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/ValidateTokenEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/ValidateTokenEndpoint.java
@@ -88,7 +88,7 @@ public class ValidateTokenEndpoint {
             error.put(OAuth2Constants.ERROR, e.getError());
             if (e.getDescription() != null) error.put(OAuth2Constants.ERROR_DESCRIPTION, e.getDescription());
             event.error(Errors.INVALID_TOKEN);
-            return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
+            return Response.status(Response.Status.BAD_REQUEST).entity(error).type(MediaType.APPLICATION_JSON_TYPE).build();
         }
         event.success();
 
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java
index 5815037..88525db 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java
@@ -27,7 +27,7 @@ import org.keycloak.OAuth2Constants;
 import org.keycloak.events.Details;
 import org.keycloak.events.EventBuilder;
 import org.keycloak.events.EventType;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
@@ -164,8 +164,8 @@ public class OIDCLoginProtocol implements LoginProtocol {
 
     @Override
     public void backchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession) {
-        if (!(clientSession.getClient() instanceof ApplicationModel)) return;
-        ApplicationModel app = (ApplicationModel)clientSession.getClient();
+        if (!(clientSession.getClient() instanceof ClientModel)) return;
+        ClientModel app = (ClientModel)clientSession.getClient();
         ApacheHttpClient4Executor executor = ResourceAdminManager.createExecutor();
 
         try {
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java b/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
index e21d091..8d9ab8c 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
@@ -8,7 +8,6 @@ import org.keycloak.events.EventBuilder;
 import org.keycloak.jose.jws.JWSBuilder;
 import org.keycloak.jose.jws.JWSInput;
 import org.keycloak.jose.jws.crypto.RSAProvider;
-import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.KeycloakSession;
@@ -233,8 +232,8 @@ public class TokenManager {
         if (client.isFullScopeAllowed()) return roleMappings;
 
         Set<RoleModel> scopeMappings = client.getScopeMappings();
-        if (client instanceof ApplicationModel) {
-            scopeMappings.addAll(((ApplicationModel) client).getRoles());
+        if (client instanceof ClientModel) {
+            scopeMappings.addAll(((ClientModel) client).getRoles());
         }
 
         for (RoleModel role : roleMappings) {
@@ -261,12 +260,12 @@ public class TokenManager {
             for (Map.Entry<String, AccessToken.Access> entry : token.getResourceAccess().entrySet()) {
                 AccessToken.Access appAccess = newToken.getResourceAccess(entry.getKey());
                 if (appAccess == null && !entry.getValue().getRoles().isEmpty()) {
-                    throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "User or application no longer has role permissions for application key: " + entry.getKey());
+                    throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "User or client no longer has role permissions for client key: " + entry.getKey());
 
                 }
                 for (String roleName : entry.getValue().getRoles()) {
                     if (!appAccess.getRoles().contains(roleName)) {
-                        throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "User no long has permission for application role " + roleName);
+                        throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "User no long has permission for client role " + roleName);
                     }
                 }
             }
@@ -339,10 +338,10 @@ public class TokenManager {
                 return;
 
         } else {
-            ApplicationModel app = (ApplicationModel) role.getContainer();
-            access = token.getResourceAccess(app.getName());
+            ClientModel app = (ClientModel) role.getContainer();
+            access = token.getResourceAccess(app.getClientId());
             if (access == null) {
-                access = token.addAccess(app.getName());
+                access = token.addAccess(app.getClientId());
                 if (app.isSurrogateAuthRequired()) access.verifyCaller(true);
             } else if (access.isUserInRole(role.getName())) return;
 
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/utils/AuthorizeClientUtil.java b/services/src/main/java/org/keycloak/protocol/oidc/utils/AuthorizeClientUtil.java
index 1a78b64..a8a9e2a 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/utils/AuthorizeClientUtil.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/utils/AuthorizeClientUtil.java
@@ -10,6 +10,7 @@ import org.keycloak.models.RealmModel;
 import org.keycloak.util.BasicAuthHelper;
 
 import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
 import java.util.HashMap;
@@ -39,18 +40,18 @@ public class AuthorizeClientUtil {
             Map<String, String> error = new HashMap<String, String>();
             error.put(OAuth2Constants.ERROR, "invalid_client");
             error.put(OAuth2Constants.ERROR_DESCRIPTION, "Could not find client");
-            throw new BadRequestException("Could not find client", Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build());
+            throw new BadRequestException("Could not find client", Response.status(Response.Status.BAD_REQUEST).entity(error).type(MediaType.APPLICATION_JSON_TYPE).build());
         }
 
         event.client(client_id);
 
-        ClientModel client = realm.findClient(client_id);
+        ClientModel client = realm.getClientByClientId(client_id);
         if (client == null) {
             Map<String, String> error = new HashMap<String, String>();
             error.put(OAuth2Constants.ERROR, "invalid_client");
             error.put(OAuth2Constants.ERROR_DESCRIPTION, "Could not find client");
             event.error(Errors.CLIENT_NOT_FOUND);
-            throw new BadRequestException("Could not find client", Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build());
+            throw new BadRequestException("Could not find client", Response.status(Response.Status.BAD_REQUEST).entity(error).type(MediaType.APPLICATION_JSON_TYPE).build());
         }
 
         if (!client.isEnabled()) {
@@ -58,7 +59,7 @@ public class AuthorizeClientUtil {
             error.put(OAuth2Constants.ERROR, "invalid_client");
             error.put(OAuth2Constants.ERROR_DESCRIPTION, "Client is not enabled");
             event.error(Errors.CLIENT_DISABLED);
-            throw new BadRequestException("Client is not enabled", Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build());
+            throw new BadRequestException("Client is not enabled", Response.status(Response.Status.BAD_REQUEST).entity(error).type(MediaType.APPLICATION_JSON_TYPE).build());
         }
 
         if (!client.isPublicClient()) {
@@ -66,7 +67,7 @@ public class AuthorizeClientUtil {
                 Map<String, String> error = new HashMap<String, String>();
                 error.put(OAuth2Constants.ERROR, "unauthorized_client");
                 event.error(Errors.INVALID_CLIENT_CREDENTIALS);
-                throw new BadRequestException("Unauthorized Client", Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build());
+                throw new BadRequestException("Unauthorized Client", Response.status(Response.Status.BAD_REQUEST).entity(error).type(MediaType.APPLICATION_JSON_TYPE).build());
             }
         }
 
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/utils/RedirectUtils.java b/services/src/main/java/org/keycloak/protocol/oidc/utils/RedirectUtils.java
index 2fa3aee..68da825 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/utils/RedirectUtils.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/utils/RedirectUtils.java
@@ -1,10 +1,8 @@
 package org.keycloak.protocol.oidc.utils;
 
 import org.jboss.logging.Logger;
-import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.Constants;
-import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.services.resources.flows.Urls;
 
@@ -46,12 +44,7 @@ public class RedirectUtils {
 
     private static Set<String> getValidateRedirectUris(RealmModel realm) {
         Set<String> redirects = new HashSet<String>();
-        for (ApplicationModel client : realm.getApplications()) {
-            for (String redirect : client.getRedirectUris()) {
-                redirects.add(redirect);
-            }
-        }
-        for (OAuthClientModel client : realm.getOAuthClients()) {
+        for (ClientModel client : realm.getClients()) {
             for (String redirect : client.getRedirectUris()) {
                 redirects.add(redirect);
             }
diff --git a/services/src/main/java/org/keycloak/services/ErrorResponseException.java b/services/src/main/java/org/keycloak/services/ErrorResponseException.java
index bf9f278..0dd3e13 100644
--- a/services/src/main/java/org/keycloak/services/ErrorResponseException.java
+++ b/services/src/main/java/org/keycloak/services/ErrorResponseException.java
@@ -6,6 +6,7 @@ import org.keycloak.models.RealmModel;
 import org.keycloak.services.resources.flows.Flows;
 
 import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 import java.util.HashMap;
@@ -33,7 +34,7 @@ public class ErrorResponseException extends WebApplicationException {
         if (errorDescription != null) {
             e.put(OAuth2Constants.ERROR_DESCRIPTION, errorDescription);
         }
-        return Response.status(status).entity(e).type("application/json").build();
+        return Response.status(status).entity(e).type(MediaType.APPLICATION_JSON_TYPE).build();
     }
 
 }
diff --git a/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java b/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java
index 96d97e3..8760ff0 100755
--- a/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java
+++ b/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java
@@ -4,7 +4,7 @@ import org.jboss.logging.Logger;
 import org.keycloak.Config;
 import org.keycloak.enums.SslRequired;
 import org.keycloak.models.AdminRoles;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.Constants;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
@@ -71,7 +71,7 @@ public class ApplianceBootstrap {
         RoleModel adminRole = realm.getRole(AdminRoles.ADMIN);
         adminUser.grantRole(adminRole);
 
-        ApplicationModel accountApp = realm.getApplicationNameMap().get(Constants.ACCOUNT_MANAGEMENT_APP);
+        ClientModel accountApp = realm.getClientNameMap().get(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
         for (String r : accountApp.getDefaultRoles()) {
             adminUser.grantRole(accountApp.getRole(r));
         }
diff --git a/services/src/main/java/org/keycloak/services/managers/Auth.java b/services/src/main/java/org/keycloak/services/managers/Auth.java
index 1527ea5..8d76e56 100755
--- a/services/src/main/java/org/keycloak/services/managers/Auth.java
+++ b/services/src/main/java/org/keycloak/services/managers/Auth.java
@@ -1,6 +1,5 @@
 package org.keycloak.services.managers;
 
-import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.RealmModel;
@@ -81,18 +80,18 @@ public class Auth {
         return false;
     }
 
-    public boolean hasAppRole(ApplicationModel app, String role) {
+    public boolean hasClientRole(ClientModel app, String role) {
         if (cookie) {
             return user.hasRole(app.getRole(role));
         } else {
-            AccessToken.Access access = token.getResourceAccess(app.getName());
+            AccessToken.Access access = token.getResourceAccess(app.getClientId());
             return access != null && access.isUserInRole(role);
         }
     }
 
-    public boolean hasOneOfAppRole(ApplicationModel app, String... roles) {
+    public boolean hasOneOfAppRole(ClientModel app, String... roles) {
         for (String r : roles) {
-            if (hasAppRole(app, r)) {
+            if (hasClientRole(app, r)) {
                 return true;
             }
         }
diff --git a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
index 8ebcf74..8cd9483 100755
--- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
@@ -12,7 +12,6 @@ import org.keycloak.events.EventBuilder;
 import org.keycloak.events.EventType;
 import org.keycloak.jose.jws.JWSBuilder;
 import org.keycloak.login.LoginFormsProvider;
-import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.KeycloakSession;
@@ -111,7 +110,7 @@ public class AuthenticationManager {
 
         for (ClientSessionModel clientSession : userSession.getClientSessions()) {
             ClientModel client = clientSession.getClient();
-            if (client instanceof ApplicationModel && !client.isFrontchannelLogout() && clientSession.getAction() != ClientSessionModel.Action.LOGGED_OUT) {
+            if (client instanceof ClientModel && !client.isFrontchannelLogout() && clientSession.getAction() != ClientSessionModel.Action.LOGGED_OUT) {
                 String authMethod = clientSession.getAuthMethod();
                 if (authMethod == null) continue; // must be a keycloak service like account
                 LoginProtocol protocol = session.getProvider(LoginProtocol.class, authMethod);
@@ -145,7 +144,7 @@ public class AuthenticationManager {
                 redirectClients.add(clientSession);
                 continue;
             }
-            if (client instanceof ApplicationModel && !client.isFrontchannelLogout()) {
+            if (client instanceof ClientModel && !client.isFrontchannelLogout()) {
                 String authMethod = clientSession.getAuthMethod();
                 if (authMethod == null) continue; // must be a keycloak service like account
                 LoginProtocol protocol = session.getProvider(LoginProtocol.class, authMethod);
@@ -381,13 +380,9 @@ public class AuthenticationManager {
         isEmailVerificationRequired(realm, user);
         ClientModel client = clientSession.getClient();
 
-        boolean isResource = client instanceof ApplicationModel;
         ClientSessionCode accessCode = new ClientSessionCode(realm, clientSession);
 
-
-        logger.debugv("processAccessCode: isResource: {0}", isResource);
-        logger.debugv("processAccessCode: go to oauth page?: {0}",
-                !isResource);
+        logger.debugv("processAccessCode: go to oauth page?: {0}", client.isConsentRequired());
 
         event.detail(Details.CODE_ID, clientSession.getId());
 
@@ -417,7 +412,7 @@ public class AuthenticationManager {
             }
         }
 
-        if (!isResource) {
+        if (client.isConsentRequired()) {
             accessCode.setAction(ClientSessionModel.Action.OAUTH_GRANT);
 
             List<RoleModel> realmRoles = new LinkedList<RoleModel>();
@@ -426,7 +421,7 @@ public class AuthenticationManager {
                 if (r.getContainer() instanceof RealmModel) {
                     realmRoles.add(r);
                 } else {
-                    resourceRoles.add(((ApplicationModel) r.getContainer()).getName(), r);
+                    resourceRoles.add(((ClientModel) r.getContainer()).getClientId(), r);
                 }
             }
 
diff --git a/services/src/main/java/org/keycloak/services/managers/RealmManager.java b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
index 138b0e4..53b460a 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -6,7 +6,7 @@ import org.keycloak.enums.SslRequired;
 import org.keycloak.exportimport.util.ImportUtils;
 import org.keycloak.models.AccountRoles;
 import org.keycloak.models.AdminRoles;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.BrowserSecurityHeaders;
 import org.keycloak.models.Constants;
 import org.keycloak.models.KeycloakSession;
@@ -18,14 +18,13 @@ import org.keycloak.models.UserModel;
 import org.keycloak.models.UserSessionProvider;
 import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.models.utils.RepresentationToModel;
-import org.keycloak.representations.idm.ApplicationRepresentation;
+import org.keycloak.representations.idm.ClientRepresentation;
 import org.keycloak.representations.idm.RealmEventsConfigRepresentation;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.timer.TimerProvider;
 
 import java.util.Collections;
 import java.util.HashSet;
-import java.util.LinkedList;
 import java.util.List;
 
 /**
@@ -91,8 +90,8 @@ public class RealmManager {
     }
 
     protected void setupAdminConsole(RealmModel realm) {
-        ApplicationModel adminConsole = realm.getApplicationByName(Constants.ADMIN_CONSOLE_APPLICATION);
-        if (adminConsole == null) adminConsole = new ApplicationManager(this).createApplication(realm, Constants.ADMIN_CONSOLE_APPLICATION);
+        ClientModel adminConsole = realm.getClientByClientId(Constants.ADMIN_CONSOLE_CLIENT_ID);
+        if (adminConsole == null) adminConsole = new ClientManager(this).createClient(realm, Constants.ADMIN_CONSOLE_CLIENT_ID);
         String baseUrl = contextPath + "/admin/" + realm.getName() + "/console";
         adminConsole.setBaseUrl(baseUrl + "/index.html");
         adminConsole.setEnabled(true);
@@ -104,18 +103,18 @@ public class RealmManager {
         if (realm.getName().equals(Config.getAdminRealm())) {
             adminRole = realm.getRole(AdminRoles.ADMIN);
         } else {
-            String realmAdminApplicationName = getRealmAdminApplicationName(realm);
-            ApplicationModel realmAdminApp = realm.getApplicationByName(realmAdminApplicationName);
+            String realmAdminApplicationClientId = getRealmAdminClientId(realm);
+            ClientModel realmAdminApp = realm.getClientByClientId(realmAdminApplicationClientId);
             adminRole = realmAdminApp.getRole(AdminRoles.REALM_ADMIN);
         }
         adminConsole.addScopeMapping(adminRole);
     }
 
-    public String getRealmAdminApplicationName(RealmModel realm) {
+    public String getRealmAdminClientId(RealmModel realm) {
         return "realm-management";
     }
 
-    public String getRealmAdminApplicationName(RealmRepresentation realm) {
+    public String getRealmAdminClientId(RealmRepresentation realm) {
         return "realm-management";
     }
 
@@ -140,7 +139,7 @@ public class RealmManager {
 
         boolean removed = model.removeRealm(realm.getId());
         if (removed) {
-            new ApplicationManager(this).removeApplication(getKeycloakAdminstrationRealm(), realm.getMasterAdminApp());
+            new ClientManager(this).removeClient(getKeycloakAdminstrationRealm(), realm.getMasterAdminClient());
 
             UserSessionProvider sessions = session.sessions();
             if (sessions != null) {
@@ -175,20 +174,20 @@ public class RealmManager {
     private void setupRealmAdminManagement(RealmModel realm) {
         if (realm.getName().equals(Config.getAdminRealm())) { return; } // don't need to do this for master realm
 
-        ApplicationManager applicationManager = new ApplicationManager(new RealmManager(session));
+        ClientManager clientManager = new ClientManager(new RealmManager(session));
 
-        String realmAdminApplicationName = getRealmAdminApplicationName(realm);
-        ApplicationModel realmAdminApp = realm.getApplicationByName(realmAdminApplicationName);
-        if (realmAdminApp == null) {
-            realmAdminApp = applicationManager.createApplication(realm, realmAdminApplicationName);
+        String realmAdminClientId = getRealmAdminClientId(realm);
+        ClientModel realmAdminClient = realm.getClientByClientId(realmAdminClientId);
+        if (realmAdminClient == null) {
+            realmAdminClient = clientManager.createClient(realm, realmAdminClientId);
         }
-        RoleModel adminRole = realmAdminApp.addRole(AdminRoles.REALM_ADMIN);
-        adminRole.setDescription("${role_"+AdminRoles.REALM_ADMIN+"}");
-        realmAdminApp.setBearerOnly(true);
-        realmAdminApp.setFullScopeAllowed(false);
+        RoleModel adminRole = realmAdminClient.addRole(AdminRoles.REALM_ADMIN);
+        adminRole.setDescription("${role_" + AdminRoles.REALM_ADMIN + "}");
+        realmAdminClient.setBearerOnly(true);
+        realmAdminClient.setFullScopeAllowed(false);
 
         for (String r : AdminRoles.ALL_REALM_ROLES) {
-            RoleModel role = realmAdminApp.addRole(r);
+            RoleModel role = realmAdminClient.addRole(r);
             role.setDescription("${role_"+r+"}");
             adminRole.addCompositeRole(role);
         }
@@ -196,19 +195,19 @@ public class RealmManager {
 
 
     private void setupAccountManagement(RealmModel realm) {
-        ApplicationModel application = realm.getApplicationNameMap().get(Constants.ACCOUNT_MANAGEMENT_APP);
-        if (application == null) {
-            application = new ApplicationManager(this).createApplication(realm, Constants.ACCOUNT_MANAGEMENT_APP);
-            application.setEnabled(true);
-            application.setFullScopeAllowed(false);
+        ClientModel client = realm.getClientNameMap().get(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
+        if (client == null) {
+            client = new ClientManager(this).createClient(realm, Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
+            client.setEnabled(true);
+            client.setFullScopeAllowed(false);
             String base = contextPath + "/realms/" + realm.getName() + "/account";
             String redirectUri = base + "/*";
-            application.addRedirectUri(redirectUri);
-            application.setBaseUrl(base);
+            client.addRedirectUri(redirectUri);
+            client.setBaseUrl(base);
 
             for (String role : AccountRoles.ALL) {
-                application.addDefaultRole(role);
-                application.getRole(role).setDescription("${role_"+role+"}");
+                client.addDefaultRole(role);
+                client.getRole(role).setDescription("${role_"+role+"}");
             }
         }
     }
@@ -225,9 +224,9 @@ public class RealmManager {
 
         setupRealmDefaults(realm);
         setupMasterAdminManagement(realm);
-        if (!hasRealmAdminManagementApp(rep)) setupRealmAdminManagement(realm);
-        if (!hasAccountManagementApp(rep)) setupAccountManagement(realm);
-        if (!hasAdminConsoleApp(rep)) setupAdminConsole(realm);
+        if (!hasRealmAdminManagementClient(rep)) setupRealmAdminManagement(realm);
+        if (!hasAccountManagementClient(rep)) setupAccountManagement(realm);
+        if (!hasAdminConsoleClient(rep)) setupAdminConsole(realm);
 
         RepresentationToModel.importRealm(session, rep, realm);
 
@@ -240,30 +239,30 @@ public class RealmManager {
         return realm;
     }
 
-    private boolean hasRealmAdminManagementApp(RealmRepresentation rep) {
-        if (rep.getApplications() == null) return false;
-        for (ApplicationRepresentation app : rep.getApplications()) {
-            if (app.getName().equals(getRealmAdminApplicationName(rep))) {
+    private boolean hasRealmAdminManagementClient(RealmRepresentation rep) {
+        if (rep.getClients() == null) return false;
+        for (ClientRepresentation clientRep : rep.getClients()) {
+            if (clientRep.getClientId().equals(getRealmAdminClientId(rep))) {
                 return true;
             }
         }
         return false;
     }
 
-    private boolean hasAccountManagementApp(RealmRepresentation rep) {
-        if (rep.getApplications() == null) return false;
-        for (ApplicationRepresentation app : rep.getApplications()) {
-            if (app.getName().equals(Constants.ACCOUNT_MANAGEMENT_APP)) {
+    private boolean hasAccountManagementClient(RealmRepresentation rep) {
+        if (rep.getClients() == null) return false;
+        for (ClientRepresentation clientRep : rep.getClients()) {
+            if (clientRep.getClientId().equals(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID)) {
                 return true;
             }
         }
         return false;
     }
 
-    private boolean hasAdminConsoleApp(RealmRepresentation rep) {
-        if (rep.getApplications() == null) return false;
-        for (ApplicationRepresentation app : rep.getApplications()) {
-            if (app.getName().equals(Constants.ADMIN_CONSOLE_APPLICATION)) {
+    private boolean hasAdminConsoleClient(RealmRepresentation rep) {
+        if (rep.getClients() == null) return false;
+        for (ClientRepresentation clientRep : rep.getClients()) {
+            if (clientRep.getClientId().equals(Constants.ADMIN_CONSOLE_CLIENT_ID)) {
                 return true;
             }
         }
diff --git a/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java b/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java
index 1bd7fdc..ac64cbc 100755
--- a/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java
@@ -7,7 +7,6 @@ import org.jboss.resteasy.client.ClientResponse;
 import org.jboss.resteasy.client.core.executors.ApacheHttpClient4Executor;
 import org.keycloak.TokenIdGenerator;
 import org.keycloak.constants.AdapterConstants;
-import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.KeycloakSession;
@@ -43,7 +42,7 @@ import java.util.Set;
  */
 public class ResourceAdminManager {
     protected static Logger logger = Logger.getLogger(ResourceAdminManager.class);
-    private static final String APPLICATION_SESSION_HOST_PROPERTY = "${application.session.host}";
+    private static final String CLIENT_SESSION_HOST_PROPERTY = "${application.session.host}";
 
     public static ApacheHttpClient4Executor createExecutor() {
         HttpClient client = new HttpClientBuilder()
@@ -58,13 +57,13 @@ public class ResourceAdminManager {
 
    }
 
-    public static String getManagementUrl(URI requestUri, ApplicationModel application) {
-        String mgmtUrl = application.getManagementUrl();
+    public static String getManagementUrl(URI requestUri, ClientModel client) {
+        String mgmtUrl = client.getManagementUrl();
         if (mgmtUrl == null || mgmtUrl.equals("")) {
             return null;
         }
 
-        // this is to support relative admin urls when keycloak and applications are deployed on the same machine
+        // this is to support relative admin urls when keycloak and clients are deployed on the same machine
         String absoluteURI = ResolveRelative.resolveRelativeUri(requestUri, mgmtUrl);
 
         // this is for resolving URI like "http://${jboss.host.name}:8080/..." in order to send request to same machine and avoid request to LB in cluster environment
@@ -73,13 +72,13 @@ public class ResourceAdminManager {
 
     // For non-cluster setup, return just single configured managementUrls
     // For cluster setup, return the management Urls corresponding to all registered cluster nodes
-    private List<String> getAllManagementUrls(URI requestUri, ApplicationModel application) {
-        String baseMgmtUrl = getManagementUrl(requestUri, application);
+    private List<String> getAllManagementUrls(URI requestUri, ClientModel client) {
+        String baseMgmtUrl = getManagementUrl(requestUri, client);
         if (baseMgmtUrl == null) {
             return Collections.emptyList();
         }
 
-        Set<String> registeredNodesHosts = new ApplicationManager().validateRegisteredNodes(application);
+        Set<String> registeredNodesHosts = new ClientManager().validateRegisteredNodes(client);
 
         // No-cluster setup
         if (registeredNodesHosts.isEmpty()) {
@@ -106,7 +105,7 @@ public class ResourceAdminManager {
 
         try {
             // Map from "app" to clientSessions for this app
-            MultivaluedHashMap<ApplicationModel, ClientSessionModel> clientSessions = new MultivaluedHashMap<ApplicationModel, ClientSessionModel>();
+            MultivaluedHashMap<ClientModel, ClientSessionModel> clientSessions = new MultivaluedHashMap<ClientModel, ClientSessionModel>();
             for (UserSessionModel userSession : userSessions) {
                 putClientSessions(clientSessions, userSession);
             }
@@ -114,7 +113,7 @@ public class ResourceAdminManager {
             logger.debugv("logging out {0} resources ", clientSessions.size());
             //logger.infov("logging out resources: {0}", clientSessions);
 
-            for (Map.Entry<ApplicationModel, List<ClientSessionModel>> entry : clientSessions.entrySet()) {
+            for (Map.Entry<ClientModel, List<ClientSessionModel>> entry : clientSessions.entrySet()) {
                 logoutClientSessions(requestUri, realm, entry.getKey(), entry.getValue(), executor);
             }
         } finally {
@@ -122,23 +121,21 @@ public class ResourceAdminManager {
         }
     }
 
-    private void putClientSessions(MultivaluedHashMap<ApplicationModel, ClientSessionModel> clientSessions, UserSessionModel userSession) {
+    private void putClientSessions(MultivaluedHashMap<ClientModel, ClientSessionModel> clientSessions, UserSessionModel userSession) {
         for (ClientSessionModel clientSession : userSession.getClientSessions()) {
             ClientModel client = clientSession.getClient();
-            if (client instanceof ApplicationModel) {
-                clientSessions.add((ApplicationModel)client, clientSession);
-            }
+            clientSessions.add(client, clientSession);
         }
     }
 
-    public void logoutUserFromApplication(URI requestUri, RealmModel realm, ApplicationModel resource, UserModel user, KeycloakSession session) {
+    public void logoutUserFromClient(URI requestUri, RealmModel realm, ClientModel resource, UserModel user, KeycloakSession session) {
         ApacheHttpClient4Executor executor = createExecutor();
 
         try {
             List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, user);
             List<ClientSessionModel> ourAppClientSessions = null;
             if (userSessions != null) {
-                MultivaluedHashMap<ApplicationModel, ClientSessionModel> clientSessions = new MultivaluedHashMap<ApplicationModel, ClientSessionModel>();
+                MultivaluedHashMap<ClientModel, ClientSessionModel> clientSessions = new MultivaluedHashMap<ClientModel, ClientSessionModel>();
                 for (UserSessionModel userSession : userSessions) {
                     putClientSessions(clientSessions, userSession);
                 }
@@ -152,11 +149,11 @@ public class ResourceAdminManager {
 
     }
 
-    public boolean logoutClientSession(URI requestUri, RealmModel realm, ApplicationModel resource, ClientSessionModel clientSession, ApacheHttpClient4Executor client) {
+    public boolean logoutClientSession(URI requestUri, RealmModel realm, ClientModel resource, ClientSessionModel clientSession, ApacheHttpClient4Executor client) {
         return logoutClientSessions(requestUri, realm, resource, Arrays.asList(clientSession), client);
     }
 
-    protected boolean logoutClientSessions(URI requestUri, RealmModel realm, ApplicationModel resource, List<ClientSessionModel> clientSessions, ApacheHttpClient4Executor client) {
+    protected boolean logoutClientSessions(URI requestUri, RealmModel realm, ClientModel resource, List<ClientSessionModel> clientSessions, ApacheHttpClient4Executor client) {
         String managementUrl = getManagementUrl(requestUri, resource);
         if (managementUrl != null) {
 
@@ -166,9 +163,9 @@ public class ResourceAdminManager {
             if (clientSessions != null && clientSessions.size() > 0) {
                 adapterSessionIds = new MultivaluedHashMap<String, String>();
                 for (ClientSessionModel clientSession : clientSessions) {
-                    String adapterSessionId = clientSession.getNote(AdapterConstants.APPLICATION_SESSION_STATE);
+                    String adapterSessionId = clientSession.getNote(AdapterConstants.CLIENT_SESSION_STATE);
                     if (adapterSessionId != null) {
-                        String host = clientSession.getNote(AdapterConstants.APPLICATION_SESSION_HOST);
+                        String host = clientSession.getNote(AdapterConstants.CLIENT_SESSION_HOST);
                         adapterSessionIds.add(host, adapterSessionId);
                     }
                     if (clientSession.getUserSession() != null) userSessions.add(clientSession.getUserSession().getId());
@@ -176,17 +173,17 @@ public class ResourceAdminManager {
             }
 
             if (adapterSessionIds == null || adapterSessionIds.isEmpty()) {
-                logger.debugv("Can't logout {0}: no logged adapter sessions", resource.getName());
+                logger.debugv("Can't logout {0}: no logged adapter sessions", resource.getClientId());
                 return false;
             }
 
-            if (managementUrl.contains(APPLICATION_SESSION_HOST_PROPERTY)) {
+            if (managementUrl.contains(CLIENT_SESSION_HOST_PROPERTY)) {
                 boolean allPassed = true;
                 // Send logout separately to each host (needed for single-sign-out in cluster for non-distributable apps - KEYCLOAK-748)
                 for (Map.Entry<String, List<String>> entry : adapterSessionIds.entrySet()) {
                     String host = entry.getKey();
                     List<String> sessionIds = entry.getValue();
-                    String currentHostMgmtUrl = managementUrl.replace(APPLICATION_SESSION_HOST_PROPERTY, host);
+                    String currentHostMgmtUrl = managementUrl.replace(CLIENT_SESSION_HOST_PROPERTY, host);
                     allPassed = sendLogoutRequest(realm, resource, sessionIds, userSessions, client, 0, currentHostMgmtUrl) && allPassed;
                 }
 
@@ -201,7 +198,7 @@ public class ResourceAdminManager {
                 return sendLogoutRequest(realm, resource, allSessionIds, userSessions, client, 0, managementUrl);
             }
         } else {
-            logger.debugv("Can't logout {0}: no management url", resource.getName());
+            logger.debugv("Can't logout {0}: no management url", resource.getClientId());
             return false;
         }
     }
@@ -213,12 +210,12 @@ public class ResourceAdminManager {
 
         try {
             realm.setNotBefore(Time.currentTime());
-            List<ApplicationModel> resources = realm.getApplications();
+            List<ClientModel> resources = realm.getClients();
             logger.debugv("logging out {0} resources ", resources.size());
 
             GlobalRequestResult finalResult = new GlobalRequestResult();
-            for (ApplicationModel resource : resources) {
-                GlobalRequestResult currentResult = logoutApplication(requestUri, realm, resource, executor, realm.getNotBefore());
+            for (ClientModel resource : resources) {
+                GlobalRequestResult currentResult = logoutClient(requestUri, realm, resource, executor, realm.getNotBefore());
                 finalResult.addAll(currentResult);
             }
             return finalResult;
@@ -227,25 +224,25 @@ public class ResourceAdminManager {
         }
     }
 
-    public GlobalRequestResult logoutApplication(URI requestUri, RealmModel realm, ApplicationModel resource) {
+    public GlobalRequestResult logoutClient(URI requestUri, RealmModel realm, ClientModel resource) {
         ApacheHttpClient4Executor executor = createExecutor();
         try {
             resource.setNotBefore(Time.currentTime());
-            return logoutApplication(requestUri, realm, resource, executor, resource.getNotBefore());
+            return logoutClient(requestUri, realm, resource, executor, resource.getNotBefore());
         } finally {
             executor.getHttpClient().getConnectionManager().shutdown();
         }
     }
 
 
-    protected GlobalRequestResult logoutApplication(URI requestUri, RealmModel realm, ApplicationModel resource, ApacheHttpClient4Executor executor, int notBefore) {
+    protected GlobalRequestResult logoutClient(URI requestUri, RealmModel realm, ClientModel resource, ApacheHttpClient4Executor executor, int notBefore) {
         List<String> mgmtUrls = getAllManagementUrls(requestUri, resource);
         if (mgmtUrls.isEmpty()) {
-            logger.debug("No management URL or no registered cluster nodes for the application " + resource.getName());
+            logger.debug("No management URL or no registered cluster nodes for the client " + resource.getClientId());
             return new GlobalRequestResult();
         }
 
-        if (logger.isDebugEnabled()) logger.debug("Send logoutApplication for URLs: " + mgmtUrls);
+        if (logger.isDebugEnabled()) logger.debug("Send logoutClient for URLs: " + mgmtUrls);
 
         // Propagate this to all hosts
         GlobalRequestResult result = new GlobalRequestResult();
@@ -259,16 +256,16 @@ public class ResourceAdminManager {
         return result;
     }
 
-    protected boolean sendLogoutRequest(RealmModel realm, ApplicationModel resource, List<String> adapterSessionIds, List<String> userSessions, ApacheHttpClient4Executor client, int notBefore, String managementUrl) {
-        LogoutAction adminAction = new LogoutAction(TokenIdGenerator.generateId(), Time.currentTime() + 30, resource.getName(), adapterSessionIds, notBefore, userSessions);
+    protected boolean sendLogoutRequest(RealmModel realm, ClientModel resource, List<String> adapterSessionIds, List<String> userSessions, ApacheHttpClient4Executor client, int notBefore, String managementUrl) {
+        LogoutAction adminAction = new LogoutAction(TokenIdGenerator.generateId(), Time.currentTime() + 30, resource.getClientId(), adapterSessionIds, notBefore, userSessions);
         String token = new TokenManager().encodeToken(realm, adminAction);
-        if (logger.isDebugEnabled()) logger.debugv("logout resource {0} url: {1} sessionIds: " + adapterSessionIds, resource.getName(), managementUrl);
+        if (logger.isDebugEnabled()) logger.debugv("logout resource {0} url: {1} sessionIds: " + adapterSessionIds, resource.getClientId(), managementUrl);
         ClientRequest request = client.createRequest(UriBuilder.fromUri(managementUrl).path(AdapterConstants.K_LOGOUT).build().toString());
         ClientResponse response;
         try {
             response = request.body(MediaType.TEXT_PLAIN_TYPE, token).post();
         } catch (Exception e) {
-            logger.warn("Logout for application '" + resource.getName() + "' failed", e);
+            logger.warn("Logout for client '" + resource.getClientId() + "' failed", e);
             return false;
         }
         try {
@@ -285,8 +282,8 @@ public class ResourceAdminManager {
 
         try {
             GlobalRequestResult finalResult = new GlobalRequestResult();
-            for (ApplicationModel application : realm.getApplications()) {
-                GlobalRequestResult currentResult = pushRevocationPolicy(requestUri, realm, application, realm.getNotBefore(), executor);
+            for (ClientModel client : realm.getClients()) {
+                GlobalRequestResult currentResult = pushRevocationPolicy(requestUri, realm, client, realm.getNotBefore(), executor);
                 finalResult.addAll(currentResult);
             }
             return finalResult;
@@ -295,21 +292,21 @@ public class ResourceAdminManager {
         }
     }
 
-    public GlobalRequestResult pushApplicationRevocationPolicy(URI requestUri, RealmModel realm, ApplicationModel application) {
+    public GlobalRequestResult pushClientRevocationPolicy(URI requestUri, RealmModel realm, ClientModel client) {
         ApacheHttpClient4Executor executor = createExecutor();
 
         try {
-            return pushRevocationPolicy(requestUri, realm, application, application.getNotBefore(), executor);
+            return pushRevocationPolicy(requestUri, realm, client, client.getNotBefore(), executor);
         } finally {
             executor.getHttpClient().getConnectionManager().shutdown();
         }
     }
 
 
-    protected GlobalRequestResult pushRevocationPolicy(URI requestUri, RealmModel realm, ApplicationModel resource, int notBefore, ApacheHttpClient4Executor executor) {
+    protected GlobalRequestResult pushRevocationPolicy(URI requestUri, RealmModel realm, ClientModel resource, int notBefore, ApacheHttpClient4Executor executor) {
         List<String> mgmtUrls = getAllManagementUrls(requestUri, resource);
         if (mgmtUrls.isEmpty()) {
-            logger.debugf("No management URL or no registered cluster nodes for the application %s", resource.getName());
+            logger.debugf("No management URL or no registered cluster nodes for the client %s", resource.getClientId());
             return new GlobalRequestResult();
         }
 
@@ -327,10 +324,10 @@ public class ResourceAdminManager {
         return result;
     }
 
-    protected boolean sendPushRevocationPolicyRequest(RealmModel realm, ApplicationModel resource, int notBefore, ApacheHttpClient4Executor client, String managementUrl) {
-        PushNotBeforeAction adminAction = new PushNotBeforeAction(TokenIdGenerator.generateId(), Time.currentTime() + 30, resource.getName(), notBefore);
+    protected boolean sendPushRevocationPolicyRequest(RealmModel realm, ClientModel resource, int notBefore, ApacheHttpClient4Executor client, String managementUrl) {
+        PushNotBeforeAction adminAction = new PushNotBeforeAction(TokenIdGenerator.generateId(), Time.currentTime() + 30, resource.getClientId(), notBefore);
         String token = new TokenManager().encodeToken(realm, adminAction);
-        logger.infov("pushRevocation resource: {0} url: {1}", resource.getName(), managementUrl);
+        logger.infov("pushRevocation resource: {0} url: {1}", resource.getClientId(), managementUrl);
         ClientRequest request = client.createRequest(UriBuilder.fromUri(managementUrl).path(AdapterConstants.K_PUSH_NOT_BEFORE).build().toString());
         ClientResponse response;
         try {
@@ -348,10 +345,10 @@ public class ResourceAdminManager {
         }
     }
 
-    public GlobalRequestResult testNodesAvailability(URI requestUri, RealmModel realm, ApplicationModel application) {
-        List<String> mgmtUrls = getAllManagementUrls(requestUri, application);
+    public GlobalRequestResult testNodesAvailability(URI requestUri, RealmModel realm, ClientModel client) {
+        List<String> mgmtUrls = getAllManagementUrls(requestUri, client);
         if (mgmtUrls.isEmpty()) {
-            logger.debug("No management URL or no registered cluster nodes for the application " + application.getName());
+            logger.debug("No management URL or no registered cluster nodes for the application " + client.getClientId());
             return new GlobalRequestResult();
         }
 
@@ -363,7 +360,7 @@ public class ResourceAdminManager {
             // Propagate this to all hosts
             GlobalRequestResult result = new GlobalRequestResult();
             for (String mgmtUrl : mgmtUrls) {
-                if (sendTestNodeAvailabilityRequest(realm, application, executor, mgmtUrl)) {
+                if (sendTestNodeAvailabilityRequest(realm, client, executor, mgmtUrl)) {
                     result.addSuccessRequest(mgmtUrl);
                 } else {
                     result.addFailedRequest(mgmtUrl);
@@ -375,11 +372,11 @@ public class ResourceAdminManager {
         }
     }
 
-    protected boolean sendTestNodeAvailabilityRequest(RealmModel realm, ApplicationModel application, ApacheHttpClient4Executor client, String managementUrl) {
-        TestAvailabilityAction adminAction = new TestAvailabilityAction(TokenIdGenerator.generateId(), Time.currentTime() + 30, application.getName());
+    protected boolean sendTestNodeAvailabilityRequest(RealmModel realm, ClientModel client, ApacheHttpClient4Executor httpClient, String managementUrl) {
+        TestAvailabilityAction adminAction = new TestAvailabilityAction(TokenIdGenerator.generateId(), Time.currentTime() + 30, client.getClientId());
         String token = new TokenManager().encodeToken(realm, adminAction);
-        logger.debugv("testNodes availability resource: {0} url: {1}", application.getName(), managementUrl);
-        ClientRequest request = client.createRequest(UriBuilder.fromUri(managementUrl).path(AdapterConstants.K_TEST_AVAILABLE).build().toString());
+        logger.debugv("testNodes availability resource: {0} url: {1}", client.getClientId(), managementUrl);
+        ClientRequest request = httpClient.createRequest(UriBuilder.fromUri(managementUrl).path(AdapterConstants.K_TEST_AVAILABLE).build().toString());
         ClientResponse response;
         try {
             response = request.body(MediaType.TEXT_PLAIN_TYPE, token).post();
diff --git a/services/src/main/java/org/keycloak/services/resources/AccountService.java b/services/src/main/java/org/keycloak/services/resources/AccountService.java
index 906e3e2..71fb570 100755
--- a/services/src/main/java/org/keycloak/services/resources/AccountService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java
@@ -131,16 +131,16 @@ public class AccountService {
     private KeycloakSession session;
 
     private final AppAuthManager authManager;
-    private final ApplicationModel application;
+    private final ClientModel client;
     private EventBuilder event;
     private AccountProvider account;
     private Auth auth;
     private EventStoreProvider eventStore;
     private String stateChecker;
 
-    public AccountService(RealmModel realm, ApplicationModel application, EventBuilder event) {
+    public AccountService(RealmModel realm, ClientModel client, EventBuilder event) {
         this.realm = realm;
-        this.application = application;
+        this.client = client;
         this.event = event;
         this.authManager = new AppAuthManager();
     }
@@ -152,11 +152,11 @@ public class AccountService {
 
         AuthenticationManager.AuthResult authResult = authManager.authenticateBearerToken(session, realm, uriInfo, clientConnection, headers);
         if (authResult != null) {
-            auth = new Auth(realm, authResult.getToken(), authResult.getUser(), application, authResult.getSession(), false);
+            auth = new Auth(realm, authResult.getToken(), authResult.getUser(), client, authResult.getSession(), false);
         } else {
             authResult = authManager.authenticateIdentityCookie(session, realm, uriInfo, clientConnection, headers);
             if (authResult != null) {
-                auth = new Auth(realm, authResult.getToken(), authResult.getUser(), application, authResult.getSession(), true);
+                auth = new Auth(realm, authResult.getToken(), authResult.getUser(), client, authResult.getSession(), true);
                 Cookie cookie = headers.getCookies().get(KEYCLOAK_STATE_CHECKER);
                 if (cookie != null) {
                     stateChecker = cookie.getValue();
@@ -193,14 +193,14 @@ public class AccountService {
             if (userSession != null) {
                 boolean associated = false;
                 for (ClientSessionModel c : userSession.getClientSessions()) {
-                    if (c.getClient().equals(application)) {
+                    if (c.getClient().equals(client)) {
                         auth.setClientSession(c);
                         associated = true;
                         break;
                     }
                 }
                 if (!associated) {
-                    ClientSessionModel clientSession = session.sessions().createClientSession(realm, application);
+                    ClientSessionModel clientSession = session.sessions().createClientSession(realm, client);
                     clientSession.setUserSession(userSession);
                     auth.setClientSession(clientSession);
                 }
@@ -737,7 +737,7 @@ public class AccountService {
                 logger.debug("realm not enabled");
                 throw new ForbiddenException();
             }
-            if (!application.isEnabled()) {
+            if (!client.isEnabled()) {
                 logger.debug("account management app not enabled");
                 throw new ForbiddenException();
             }
@@ -766,7 +766,7 @@ public class AccountService {
         String authUrl = OIDCLoginProtocolService.authUrl(uriInfo).build(realm.getName()).toString();
         oauth.setAuthUrl(authUrl);
 
-        oauth.setClientId(Constants.ACCOUNT_MANAGEMENT_APP);
+        oauth.setClientId(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
 
         UriBuilder uriBuilder = Urls.accountPageBuilder(uriInfo.getBaseUri()).path(AccountService.class, "loginRedirect");
 
@@ -813,21 +813,21 @@ public class AccountService {
 
         String referrerUri = uriInfo.getQueryParameters().getFirst("referrer_uri");
 
-        ApplicationModel application = realm.getApplicationByName(referrer);
-        if (application != null) {
+        ClientModel referrerClient = realm.getClientByClientId(referrer);
+        if (referrerClient != null) {
             if (referrerUri != null) {
-                referrerUri = RedirectUtils.verifyRedirectUri(uriInfo, referrerUri, realm, application);
+                referrerUri = RedirectUtils.verifyRedirectUri(uriInfo, referrerUri, realm, referrerClient);
             } else {
-                referrerUri = ResolveRelative.resolveRelativeUri(uriInfo.getRequestUri(), application.getBaseUrl());
+                referrerUri = ResolveRelative.resolveRelativeUri(uriInfo.getRequestUri(), referrerClient.getBaseUrl());
             }
 
             if (referrerUri != null) {
                 return new String[]{referrer, referrerUri};
             }
         } else if (referrerUri != null) {
-            ClientModel client = realm.getOAuthClient(referrer);
+            referrerClient = realm.getClientByClientId(referrer);
             if (client != null) {
-                referrerUri = RedirectUtils.verifyRedirectUri(uriInfo, referrerUri, realm, application);
+                referrerUri = RedirectUtils.verifyRedirectUri(uriInfo, referrerUri, realm, referrerClient);
 
                 if (referrerUri != null) {
                     return new String[]{referrer, referrerUri};
@@ -843,7 +843,7 @@ public class AccountService {
             throw new ForbiddenException();
         }
 
-        if (!auth.hasAppRole(application, role)) {
+        if (!auth.hasClientRole(client, role)) {
             throw new ForbiddenException();
         }
     }
@@ -853,7 +853,7 @@ public class AccountService {
             throw new ForbiddenException();
         }
 
-        if (!auth.hasOneOfAppRole(application, roles)) {
+        if (!auth.hasOneOfAppRole(client, roles)) {
             throw new ForbiddenException();
         }
     }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminAuth.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminAuth.java
index ca7dece..3dd1123 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AdminAuth.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminAuth.java
@@ -1,6 +1,5 @@
 package org.keycloak.services.resources.admin;
 
-import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
@@ -43,7 +42,7 @@ public class AdminAuth {
 
 
     public boolean hasRealmRole(String role) {
-        if (client instanceof ApplicationModel) {
+        if (client instanceof ClientModel) {
             RoleModel roleModel = realm.getRole(role);
             return user.hasRole(roleModel) && client.hasScope(roleModel);
         } else {
@@ -61,17 +60,17 @@ public class AdminAuth {
         return false;
     }
 
-    public boolean hasAppRole(ApplicationModel app, String role) {
-        if (client instanceof ApplicationModel) {
+    public boolean hasAppRole(ClientModel app, String role) {
+        if (client instanceof ClientModel) {
             RoleModel roleModel = app.getRole(role);
             return user.hasRole(roleModel) && client.hasScope(roleModel);
         } else {
-            AccessToken.Access access = token.getResourceAccess(app.getName());
+            AccessToken.Access access = token.getResourceAccess(app.getClientId());
             return access != null && access.isUserInRole(role);
         }
     }
 
-    public boolean hasOneOfAppRole(ApplicationModel app, String... roles) {
+    public boolean hasOneOfAppRole(ClientModel app, String... roles) {
         for (String r : roles) {
             if (hasAppRole(app, r)) {
                 return true;
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java
index 8ed297a..24d76b2 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java
@@ -14,7 +14,7 @@ import org.keycloak.freemarker.FreeMarkerUtil;
 import org.keycloak.freemarker.Theme;
 import org.keycloak.freemarker.ThemeProvider;
 import org.keycloak.models.AdminRoles;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.Constants;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
@@ -22,7 +22,7 @@ import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.services.managers.AppAuthManager;
-import org.keycloak.services.managers.ApplicationManager;
+import org.keycloak.services.managers.ClientManager;
 import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.services.resources.KeycloakApplication;
@@ -151,14 +151,14 @@ public class AdminConsole {
      */
     @Path("config")
     @GET
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     @NoCache
-    public ApplicationManager.InstallationAdapterConfig config() {
-        ApplicationModel consoleApp = realm.getApplicationByName(Constants.ADMIN_CONSOLE_APPLICATION);
+    public ClientManager.InstallationAdapterConfig config() {
+        ClientModel consoleApp = realm.getClientByClientId(Constants.ADMIN_CONSOLE_CLIENT_ID);
         if (consoleApp == null) {
-            throw new NotFoundException("Could not find admin console application");
+            throw new NotFoundException("Could not find admin console client");
         }
-        return new ApplicationManager().toInstallationRepresentation(realm, consoleApp, keycloak.getBaseUri(uriInfo));
+        return new ClientManager().toInstallationRepresentation(realm, consoleApp, keycloak.getBaseUri(uriInfo));
 
     }
 
@@ -170,7 +170,7 @@ public class AdminConsole {
      */
     @Path("whoami")
     @GET
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     @NoCache
     public Response whoAmI(final @Context HttpHeaders headers) {
         RealmManager realmManager = new RealmManager(session);
@@ -208,7 +208,7 @@ public class AdminConsole {
 
     private void addRealmAccess(RealmModel realm, UserModel user, Map<String, Set<String>> realmAdminAccess) {
         RealmManager realmManager = new RealmManager(session);
-        ApplicationModel realmAdminApp = realm.getApplicationByName(realmManager.getRealmAdminApplicationName(realm));
+        ClientModel realmAdminApp = realm.getClientByClientId(realmManager.getRealmAdminClientId(realm));
         Set<RoleModel> roles = realmAdminApp.getRoles();
         for (RoleModel role : roles) {
             if (!user.hasRole(role)) continue;
@@ -223,7 +223,7 @@ public class AdminConsole {
     private void addMasterRealmAccess(RealmModel masterRealm, UserModel user, Map<String, Set<String>> realmAdminAccess) {
         List<RealmModel> realms = session.realms().getRealms();
         for (RealmModel realm : realms) {
-            ApplicationModel realmAdminApp = realm.getMasterAdminApp();
+            ClientModel realmAdminApp = realm.getMasterAdminClient();
             Set<RoleModel> roles = realmAdminApp.getRoles();
             for (RoleModel role : roles) {
                 if (!user.hasRole(role)) continue;
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java
index c049ac4..2ece39b 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java
@@ -149,7 +149,7 @@ public class AdminRoot {
             throw new UnauthorizedException("Bearer");
         }
 
-        ClientModel client = realm.findClient(token.getIssuedFor());
+        ClientModel client = realm.getClientByClientId(token.getIssuedFor());
         if (client == null) {
             throw new NotFoundException("Could not find client for authorization");
 
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java
index 1140627..b1ec4d1 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java
@@ -6,8 +6,6 @@ import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
 import org.jboss.resteasy.spi.BadRequestException;
 import org.jboss.resteasy.spi.NotAcceptableException;
 import org.jboss.resteasy.spi.NotFoundException;
-import org.keycloak.events.EventBuilder;
-import org.keycloak.events.EventType;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java
index 07444af..bbb32b4 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java
@@ -4,8 +4,8 @@ import org.jboss.logging.Logger;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.keycloak.broker.provider.IdentityProvider;
 import org.keycloak.broker.provider.IdentityProviderFactory;
-import org.keycloak.models.ClientIdentityProviderMappingModel;
 import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientIdentityProviderMappingModel;
 import org.keycloak.models.FederatedIdentityModel;
 import org.keycloak.models.IdentityProviderModel;
 import org.keycloak.models.KeycloakSession;
@@ -27,6 +27,7 @@ import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 import java.util.ArrayList;
@@ -53,7 +54,7 @@ public class IdentityProviderResource {
 
     @GET
     @NoCache
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     public IdentityProviderRepresentation getIdentityProvider() {
         IdentityProviderRepresentation rep = ModelToRepresentation.toRepresentation(this.identityProviderModel);
 
@@ -65,8 +66,7 @@ public class IdentityProviderResource {
     public Response delete() {
         this.auth.requireManage();
 
-        removeClientIdentityProviders(this.realm.getApplications(), this.identityProviderModel);
-        removeClientIdentityProviders(this.realm.getOAuthClients(), this.identityProviderModel);
+        removeClientIdentityProviders(this.realm.getClients(), this.identityProviderModel);
 
         this.realm.removeIdentityProviderByAlias(this.identityProviderModel.getAlias());
 
@@ -74,7 +74,7 @@ public class IdentityProviderResource {
     }
 
     @PUT
-    @Consumes("application/json")
+    @Consumes(MediaType.APPLICATION_JSON)
     public Response update(IdentityProviderRepresentation providerRep) {
         try {
             this.auth.requireManage();
@@ -90,8 +90,7 @@ public class IdentityProviderResource {
                 // Admin changed the ID (alias) of identity provider. We must update all clients and users
                 logger.debug("Changing providerId in all clients and linked users. oldProviderId=" + oldProviderId + ", newProviderId=" + newProviderId);
 
-                updateClientsAfterProviderAliasChange(this.realm.getApplications(), oldProviderId, newProviderId);
-                updateClientsAfterProviderAliasChange(this.realm.getOAuthClients(), oldProviderId, newProviderId);
+                updateClientsAfterProviderAliasChange(this.realm.getClients(), oldProviderId, newProviderId);
                 updateUsersAfterProviderAliasChange(this.session.users().getUsers(this.realm), oldProviderId, newProviderId);
             }
 
@@ -113,7 +112,7 @@ public class IdentityProviderResource {
         return null;
     }
 
-    private void updateClientsAfterProviderAliasChange(List<? extends ClientModel> clients, String oldProviderId, String newProviderId) {
+    private void updateClientsAfterProviderAliasChange(List<ClientModel> clients, String oldProviderId, String newProviderId) {
         for (ClientModel client : clients) {
             List<ClientIdentityProviderMappingModel> clientIdentityProviders = client.getIdentityProviders();
             boolean found = true;
@@ -175,11 +174,11 @@ public class IdentityProviderResource {
     }
 
 
-    private void removeClientIdentityProviders(List<? extends ClientModel> clients, IdentityProviderModel identityProvider) {
+    private void removeClientIdentityProviders(List<ClientModel> clients, IdentityProviderModel identityProvider) {
         for (ClientModel clientModel : clients) {
             List<ClientIdentityProviderMappingModel> identityProviders = clientModel.getIdentityProviders();
 
-            for (ClientIdentityProviderMappingModel providerMappingModel : new ArrayList<ClientIdentityProviderMappingModel>(identityProviders)) {
+            for (ClientIdentityProviderMappingModel providerMappingModel : new ArrayList<>(identityProviders)) {
                 if (providerMappingModel.getIdentityProvider().equals(identityProvider.getAlias())) {
                     identityProviders.remove(providerMappingModel);
                     clientModel.updateIdentityProviders(identityProviders);
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java
index e59ee6e..ef0e94b 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java
@@ -57,7 +57,7 @@ public class IdentityProvidersResource {
     @Path("/providers/{provider_id}")
     @GET
     @NoCache
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     public Response getIdentityProviders(@PathParam("provider_id") String providerId) {
         this.auth.requireView();
         IdentityProviderFactory providerFactory = getProviderFactorytById(providerId);
@@ -108,7 +108,7 @@ public class IdentityProvidersResource {
     @GET
     @Path("instances")
     @NoCache
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     public List<IdentityProviderRepresentation> getIdentityProviders() {
         this.auth.requireView();
 
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ProtocolMappersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ProtocolMappersResource.java
index 717a116..36428b8 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ProtocolMappersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ProtocolMappersResource.java
@@ -19,9 +19,9 @@ import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
-
 import java.util.LinkedList;
 import java.util.List;
 
@@ -60,7 +60,7 @@ public class ProtocolMappersResource {
     @GET
     @NoCache
     @Path("protocol/{protocol}")
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     public List<ProtocolMapperRepresentation> getMappersPerProtocol(@PathParam("protocol") String protocol) {
         auth.requireView();
         List<ProtocolMapperRepresentation> mappers = new LinkedList<ProtocolMapperRepresentation>();
@@ -78,7 +78,7 @@ public class ProtocolMappersResource {
     @Path("models")
     @POST
     @NoCache
-    @Consumes("application/json")
+    @Consumes(MediaType.APPLICATION_JSON)
     public Response createMapper(ProtocolMapperRepresentation rep) {
         auth.requireManage();
         ProtocolMapperModel model = RepresentationToModel.toModel(rep);
@@ -92,7 +92,7 @@ public class ProtocolMappersResource {
     @Path("add-models")
     @POST
     @NoCache
-    @Consumes("application/json")
+    @Consumes(MediaType.APPLICATION_JSON)
     public void createMapper(List<ProtocolMapperRepresentation> reps) {
         auth.requireManage();
         for (ProtocolMapperRepresentation rep : reps) {
@@ -104,7 +104,7 @@ public class ProtocolMappersResource {
     @GET
     @NoCache
     @Path("models")
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     public List<ProtocolMapperRepresentation> getMappers() {
         auth.requireView();
         List<ProtocolMapperRepresentation> mappers = new LinkedList<ProtocolMapperRepresentation>();
@@ -117,7 +117,7 @@ public class ProtocolMappersResource {
     @GET
     @NoCache
     @Path("models/{id}")
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     public ProtocolMapperRepresentation getMapperById(@PathParam("id") String id) {
         auth.requireView();
         ProtocolMapperModel model = client.getProtocolMapperById(id);
@@ -128,7 +128,7 @@ public class ProtocolMappersResource {
     @PUT
     @NoCache
     @Path("models/{id}")
-    @Consumes("application/json")
+    @Consumes(MediaType.APPLICATION_JSON)
     public void update(@PathParam("id") String id, ProtocolMapperRepresentation rep) {
         auth.requireManage();
         ProtocolMapperModel model = client.getProtocolMapperById(id);
@@ -147,6 +147,4 @@ public class ProtocolMappersResource {
         client.removeProtocolMapper(model);
     }
 
-
-
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
index 34cd97e..5fea57d 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
@@ -9,8 +9,8 @@ import org.keycloak.events.Event;
 import org.keycloak.events.EventQuery;
 import org.keycloak.events.EventStoreProvider;
 import org.keycloak.events.EventType;
-import org.keycloak.exportimport.ApplicationImporter;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.exportimport.ClientImporter;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.ModelDuplicateException;
 import org.keycloak.models.RealmModel;
@@ -46,7 +46,6 @@ import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
-
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
@@ -86,66 +85,38 @@ public class RealmAdminResource {
     }
 
     /**
-     * Base path for importing applications under this realm.
+     * Base path for importing clients under this realm.
      *
      * @return
      */
-    @Path("application-importers/{formatId}")
-    public Object getApplicationImporter(@PathParam("formatId") String formatId) {
-        ApplicationImporter importer = session.getProvider(ApplicationImporter.class, formatId);
+    @Path("client-importers/{formatId}")
+    public Object getClientImporter(@PathParam("formatId") String formatId) {
+        ClientImporter importer = session.getProvider(ClientImporter.class, formatId);
         return importer.createJaxrsService(realm, auth);
     }
 
     /**
-     * Base path for managing applications under this realm.
-     *
-     * @return
-     */
-    @Path("applications")
-    public ApplicationsResource getApplications() {
-        ApplicationsResource applicationsResource = new ApplicationsResource(realm, auth);
-        ResteasyProviderFactory.getInstance().injectProperties(applicationsResource);
-        //resourceContext.initResource(applicationsResource);
-        return applicationsResource;
-    }
-
-    /**
-     * Base path for managing applications under this realm.
+     * Base path for managing clients under this realm.
      *
      * @return
      */
-    @Path("applications-by-id")
-    public ApplicationsByIdResource getApplicationsById() {
-        ApplicationsByIdResource applicationsResource = new ApplicationsByIdResource(realm, auth);
-        ResteasyProviderFactory.getInstance().injectProperties(applicationsResource);
-        //resourceContext.initResource(applicationsResource);
-        return applicationsResource;
+    @Path("clients")
+    public ClientsResource getClients() {
+        ClientsResource clientsResource = new ClientsResource(realm, auth);
+        ResteasyProviderFactory.getInstance().injectProperties(clientsResource);
+        return clientsResource;
     }
 
     /**
-     * base path for managing oauth clients in this realm uses name of client
+     * Base path for managing clients under this realm.
      *
      * @return
      */
-    @Path("oauth-clients")
-    public OAuthClientsResource getOAuthClients() {
-        OAuthClientsResource oauth = new OAuthClientsResource(realm, auth, session);
-        ResteasyProviderFactory.getInstance().injectProperties(oauth);
-        //resourceContext.initResource(oauth);
-        return oauth;
-    }
-
-    /**
-     * base path for managing oauth clients in this realm uses ids
-     *
-     * @return
-     */
-    @Path("oauth-clients-by-id")
-    public OAuthClientsByIdResource getOAuthClientsById() {
-        OAuthClientsByIdResource oauth = new OAuthClientsByIdResource(realm, auth, session);
-        ResteasyProviderFactory.getInstance().injectProperties(oauth);
-        //resourceContext.initResource(oauth);
-        return oauth;
+    @Path("clients-by-id")
+    public ClientsByIdResource getClientsById() {
+        ClientsByIdResource clientsResource = new ClientsByIdResource(realm, auth);
+        ResteasyProviderFactory.getInstance().injectProperties(clientsResource);
+        return clientsResource;
     }
 
     /**
@@ -159,14 +130,13 @@ public class RealmAdminResource {
     }
 
     /**
-     * Get the top-level representation of the realm.  It will not include nested information like User, Application, or OAuth
-     * Client representations.
+     * Get the top-level representation of the realm.  It will not include nested information like User and Client representations.
      *
      * @return
      */
     @GET
     @NoCache
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     public RealmRepresentation getRealm() {
         if (auth.hasView()) {
             RealmRepresentation rep = ModelToRepresentation.toRepresentation(realm, false);
@@ -189,14 +159,14 @@ public class RealmAdminResource {
     }
 
     /**
-     * Update the top-level information of this realm.  Any user, roles, application, or oauth client information in the representation
+     * Update the top-level information of this realm.  Any user, roles or client information in the representation
      * will be ignored.  This will only update top-level attributes of the realm.
      *
      * @param rep
      * @return
      */
     @PUT
-    @Consumes("application/json")
+    @Consumes(MediaType.APPLICATION_JSON)
     public Response updateRealm(final RealmRepresentation rep) {
         auth.requireManage();
 
@@ -264,7 +234,7 @@ public class RealmAdminResource {
     }
 
     /**
-     * Path for managing all realm-level or application-level roles defined in this realm by it's id.
+     * Path for managing all realm-level or client-level roles defined in this realm by it's id.
      *
      * @return
      */
@@ -277,7 +247,7 @@ public class RealmAdminResource {
     }
 
     /**
-     * Push the realm's revocation policy to any application that has an admin url associated with it.
+     * Push the realm's revocation policy to any client that has an admin url associated with it.
      *
      */
     @Path("push-revocation")
@@ -288,7 +258,7 @@ public class RealmAdminResource {
     }
 
     /**
-     * Removes all user sessions.  Any application that has an admin url will also be told to invalidate any sessions
+     * Removes all user sessions.  Any client that has an admin url will also be told to invalidate any sessions
      * they have.
      *
      */
@@ -300,7 +270,7 @@ public class RealmAdminResource {
     }
 
     /**
-     * Remove a specific user session. Any application that has an admin url will also be told to invalidate this
+     * Remove a specific user session. Any client that has an admin url will also be told to invalidate this
      * particular session.
      *
      * @param sessionId
@@ -314,46 +284,46 @@ public class RealmAdminResource {
     }
 
     /**
-     * Returns a JSON map.  The key is the application name, the value is the number of sessions that currently are active
-     * with that application.  Only application's that actually have a session associated with them will be in this map.
+     * Returns a JSON map.  The key is the client name, the value is the number of sessions that currently are active
+     * with that client.  Only client's that actually have a session associated with them will be in this map.
      *
      * @return
      */
-    @Path("application-session-stats")
+    @Path("client-session-stats")
     @GET
     @NoCache
     @Produces(MediaType.APPLICATION_JSON)
     @Deprecated
-    public Map<String, Integer> getApplicationSessionStats() {
+    public Map<String, Integer> getClientSessionStats() {
         auth.requireView();
         Map<String, Integer> stats = new HashMap<String, Integer>();
-        for (ApplicationModel application : realm.getApplications()) {
-            int size = session.sessions().getActiveUserSessions(application.getRealm(), application);
+        for (ClientModel client : realm.getClients()) {
+            int size = session.sessions().getActiveUserSessions(client.getRealm(), client);
             if (size == 0) continue;
-            stats.put(application.getName(), size);
+            stats.put(client.getClientId(), size);
         }
         return stats;
     }
 
     /**
-     * Returns a JSON map.  The key is the application id, the value is the number of sessions that currently are active
-     * with that application.  Only application's that actually have a session associated with them will be in this map.
+     * Returns a JSON map.  The key is the client id, the value is the number of sessions that currently are active
+     * with that client.  Only client's that actually have a session associated with them will be in this map.
      *
      * @return
      */
-    @Path("application-by-id-session-stats")
+    @Path("client-by-id-session-stats")
     @GET
     @NoCache
     @Produces(MediaType.APPLICATION_JSON)
-    public List<Map<String, String>> getApplicationByIdSessionStats() {
+    public List<Map<String, String>> getClientByIdSessionStats() {
         auth.requireView();
         List<Map<String, String>> data = new LinkedList<Map<String, String>>();
-        for (ApplicationModel application : realm.getApplications()) {
-            int size = session.sessions().getActiveUserSessions(application.getRealm(), application);
+        for (ClientModel client : realm.getClients()) {
+            int size = session.sessions().getActiveUserSessions(client.getRealm(), client);
             if (size == 0) continue;
             Map<String, String> map = new HashMap<String, String>();
-            map.put("id", application.getId());
-            map.put("name", application.getName());
+            map.put("id", client.getId());
+            map.put("clientId", client.getClientId());
             map.put("active", size + "");
             data.add(map);
         }
@@ -368,7 +338,7 @@ public class RealmAdminResource {
     @GET
     @NoCache
     @Path("events/config")
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     public RealmEventsConfigRepresentation getRealmEventsConfig() {
         auth.init(RealmAuth.Resource.EVENTS).requireView();
 
@@ -382,7 +352,7 @@ public class RealmAdminResource {
      */
     @PUT
     @Path("events/config")
-    @Consumes("application/json")
+    @Consumes(MediaType.APPLICATION_JSON)
     public void updateRealmEventsConfig(final RealmEventsConfigRepresentation rep) {
         auth.init(RealmAuth.Resource.EVENTS).requireManage();
 
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAuth.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAuth.java
index 20238f1..f93e8c7 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAuth.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAuth.java
@@ -1,7 +1,7 @@
 package org.keycloak.services.resources.admin;
 
 import org.keycloak.models.AdminRoles;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.services.ForbiddenException;
 
 
@@ -13,13 +13,13 @@ public class RealmAuth {
     private Resource resource;
 
     public enum Resource {
-        APPLICATION, CLIENT, USER, REALM, EVENTS, IDENTITY_PROVIDER
+        CLIENT, USER, REALM, EVENTS, IDENTITY_PROVIDER
     }
 
     private AdminAuth auth;
-    private ApplicationModel realmAdminApp;
+    private ClientModel realmAdminApp;
 
-    public RealmAuth(AdminAuth auth, ApplicationModel realmAdminApp) {
+    public RealmAuth(AdminAuth auth, ClientModel realmAdminApp) {
         this.auth = auth;
         this.realmAdminApp = realmAdminApp;
     }
@@ -57,8 +57,6 @@ public class RealmAuth {
 
     private String getViewRole(Resource resource) {
         switch (resource) {
-            case APPLICATION:
-                return AdminRoles.VIEW_APPLICATIONS;
             case CLIENT:
                 return AdminRoles.VIEW_CLIENTS;
             case USER:
@@ -76,8 +74,6 @@ public class RealmAuth {
 
     private String getManageRole(Resource resource) {
         switch (resource) {
-            case APPLICATION:
-                return AdminRoles.MANAGE_APPLICATIONS;
             case CLIENT:
                 return AdminRoles.MANAGE_CLIENTS;
             case USER:
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java
index 07b29b2..21fc79e 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java
@@ -4,11 +4,10 @@ import org.jboss.logging.Logger;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.plugins.providers.multipart.InputPart;
 import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
-import org.jboss.resteasy.spi.HttpRequest;
 import org.jboss.resteasy.spi.NotFoundException;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
 import org.keycloak.models.AdminRoles;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.ModelDuplicateException;
 import org.keycloak.models.RealmModel;
@@ -75,27 +74,27 @@ public class RealmsAdminResource {
      */
     @GET
     @NoCache
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     public List<RealmRepresentation> getRealms() {
         RealmManager realmManager = new RealmManager(session);
         List<RealmRepresentation> reps = new ArrayList<RealmRepresentation>();
         if (auth.getRealm().equals(realmManager.getKeycloakAdminstrationRealm())) {
             List<RealmModel> realms = session.realms().getRealms();
             for (RealmModel realm : realms) {
-                addRealmRep(reps, realm, realm.getMasterAdminApp());
+                addRealmRep(reps, realm, realm.getMasterAdminClient());
             }
         } else {
-            ApplicationModel adminApp = auth.getRealm().getApplicationByName(realmManager.getRealmAdminApplicationName(auth.getRealm()));
+            ClientModel adminApp = auth.getRealm().getClientByClientId(realmManager.getRealmAdminClientId(auth.getRealm()));
             addRealmRep(reps, auth.getRealm(), adminApp);
         }
         logger.debug(("getRealms()"));
         return reps;
     }
 
-    protected void addRealmRep(List<RealmRepresentation> reps, RealmModel realm, ApplicationModel realmManagementApplication) {
-        if (auth.hasAppRole(realmManagementApplication, AdminRoles.MANAGE_REALM)) {
+    protected void addRealmRep(List<RealmRepresentation> reps, RealmModel realm, ClientModel realmManagementClient) {
+        if (auth.hasAppRole(realmManagementClient, AdminRoles.MANAGE_REALM)) {
             reps.add(ModelToRepresentation.toRepresentation(realm, false));
-        } else if (auth.hasOneOfAppRole(realmManagementApplication, AdminRoles.ALL_REALM_ROLES)) {
+        } else if (auth.hasOneOfAppRole(realmManagementClient, AdminRoles.ALL_REALM_ROLES)) {
             RealmRepresentation rep = new RealmRepresentation();
             rep.setRealm(realm.getName());
             reps.add(rep);
@@ -110,7 +109,7 @@ public class RealmsAdminResource {
      * @return
      */
     @POST
-    @Consumes("application/json")
+    @Consumes(MediaType.APPLICATION_JSON)
     public Response importRealm(@Context final UriInfo uriInfo, final RealmRepresentation rep) {
         RealmManager realmManager = new RealmManager(session);
         realmManager.setContextPath(keycloak.getContextPath());
@@ -187,7 +186,7 @@ public class RealmsAdminResource {
         }
 
         RealmModel adminRealm = new RealmManager(session).getKeycloakAdminstrationRealm();
-        ApplicationModel realmAdminApp = realm.getMasterAdminApp();
+        ClientModel realmAdminApp = realm.getMasterAdminClient();
         for (String r : AdminRoles.ALL_REALM_ROLES) {
             RoleModel role = realmAdminApp.getRole(r);
             auth.getUser().grantRole(role);
@@ -215,9 +214,9 @@ public class RealmsAdminResource {
         RealmAuth realmAuth;
 
         if (auth.getRealm().equals(realmManager.getKeycloakAdminstrationRealm())) {
-            realmAuth = new RealmAuth(auth, realm.getMasterAdminApp());
+            realmAuth = new RealmAuth(auth, realm.getMasterAdminClient());
         } else {
-            realmAuth = new RealmAuth(auth, realm.getApplicationByName(realmManager.getRealmAdminApplicationName(auth.getRealm())));
+            realmAuth = new RealmAuth(auth, realm.getClientByClientId(realmManager.getRealmAdminClientId(auth.getRealm())));
         }
 
         RealmAdminResource adminResource = new RealmAdminResource(realmAuth, realm, tokenManager);
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RoleByIdResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RoleByIdResource.java
index 41ede41..67d8c12 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RoleByIdResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RoleByIdResource.java
@@ -3,9 +3,8 @@ package org.keycloak.services.resources.admin;
 import org.jboss.logging.Logger;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.NotFoundException;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserModel;
@@ -20,6 +19,7 @@ import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
 import java.util.List;
 import java.util.Set;
 
@@ -53,7 +53,7 @@ public class RoleByIdResource extends RoleResource {
     @Path("{role-id}")
     @GET
     @NoCache
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     public RoleRepresentation getRole(final @PathParam("role-id") String id) {
         RoleModel roleModel = getRoleModel(id);
         auth.requireView();
@@ -70,9 +70,7 @@ public class RoleByIdResource extends RoleResource {
         RealmAuth.Resource r = null;
         if (roleModel.getContainer() instanceof RealmModel) {
             r = RealmAuth.Resource.REALM;
-        } else if (roleModel.getContainer() instanceof ApplicationModel) {
-            r = RealmAuth.Resource.APPLICATION;
-        } else if (roleModel.getContainer() instanceof OAuthClientModel) {
+        } else if (roleModel.getContainer() instanceof ClientModel) {
             r = RealmAuth.Resource.CLIENT;
         } else if (roleModel.getContainer() instanceof UserModel) {
             r = RealmAuth.Resource.USER;
@@ -104,7 +102,7 @@ public class RoleByIdResource extends RoleResource {
      */
     @Path("{role-id}")
     @PUT
-    @Consumes("application/json")
+    @Consumes(MediaType.APPLICATION_JSON)
     public void updateRole(final @PathParam("role-id") String id, final RoleRepresentation rep) {
         RoleModel role = getRoleModel(id);
         auth.requireManage();
@@ -119,7 +117,7 @@ public class RoleByIdResource extends RoleResource {
      */
     @Path("{role-id}/composites")
     @POST
-    @Consumes("application/json")
+    @Consumes(MediaType.APPLICATION_JSON)
     public void addComposites(final @PathParam("role-id") String id, List<RoleRepresentation> roles) {
         RoleModel role = getRoleModel(id);
         auth.requireManage();
@@ -135,7 +133,7 @@ public class RoleByIdResource extends RoleResource {
     @Path("{role-id}/composites")
     @GET
     @NoCache
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     public Set<RoleRepresentation> getRoleComposites(final @PathParam("role-id") String id) {
 
         if (logger.isDebugEnabled()) logger.debug("*** getRoleComposites: '" + id + "'");
@@ -153,7 +151,7 @@ public class RoleByIdResource extends RoleResource {
     @Path("{role-id}/composites/realm")
     @GET
     @NoCache
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     public Set<RoleRepresentation> getRealmRoleComposites(final @PathParam("role-id") String id) {
         RoleModel role = getRoleModel(id);
         auth.requireView();
@@ -161,49 +159,49 @@ public class RoleByIdResource extends RoleResource {
     }
 
     /**
-     * Return a set of application-level roles for a specific app that are in the role's composite
+     * Return a set of client-level roles for a specific client that are in the role's composite
      *
      * @param id
      * @param appName
      * @return
      */
-    @Path("{role-id}/composites/applications/{app}")
+    @Path("{role-id}/composites/clients/{app}")
     @GET
     @NoCache
-    @Produces("application/json")
-    public Set<RoleRepresentation> getApplicationRoleComposites(final @PathParam("role-id") String id,
+    @Produces(MediaType.APPLICATION_JSON)
+    public Set<RoleRepresentation> getClientRoleComposites(final @PathParam("role-id") String id,
                                                                 final @PathParam("app") String appName) {
         RoleModel role = getRoleModel(id);
         auth.requireView();
-        ApplicationModel app = realm.getApplicationByName(appName);
+        ClientModel app = realm.getClientByClientId(appName);
         if (app == null) {
-            throw new NotFoundException("Could not find application: " + appName);
+            throw new NotFoundException("Could not find client: " + appName);
 
         }
-        return getApplicationRoleComposites(app, role);
+        return getClientRoleComposites(app, role);
     }
 
     /**
-     * Return a set of application-level roles for a specific app that are in the role's composite
+     * Return a set of client-level roles for a specific client that are in the role's composite
      *
      * @param id
      * @param appId
      * @return
      */
-    @Path("{role-id}/composites/applications-by-id/{appId}")
+    @Path("{role-id}/composites/clients-by-id/{appId}")
     @GET
     @NoCache
-    @Produces("application/json")
-    public Set<RoleRepresentation> getApplicationByIdRoleComposites(final @PathParam("role-id") String id,
+    @Produces(MediaType.APPLICATION_JSON)
+    public Set<RoleRepresentation> getClientByIdRoleComposites(final @PathParam("role-id") String id,
                                                                 final @PathParam("appId") String appId) {
         RoleModel role = getRoleModel(id);
         auth.requireView();
-        ApplicationModel app = realm.getApplicationById(appId);
+        ClientModel app = realm.getClientById(appId);
         if (app == null) {
-            throw new NotFoundException("Could not find application: " + appId);
+            throw new NotFoundException("Could not find client: " + appId);
 
         }
-        return getApplicationRoleComposites(app, role);
+        return getClientRoleComposites(app, role);
     }
 
     /**
@@ -214,7 +212,7 @@ public class RoleByIdResource extends RoleResource {
      */
     @Path("{role-id}/composites")
     @DELETE
-    @Consumes("application/json")
+    @Consumes(MediaType.APPLICATION_JSON)
     public void deleteComposites(final @PathParam("role-id") String id, List<RoleRepresentation> roles) {
         RoleModel role = getRoleModel(id);
         auth.requireManage();
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java
index 3ddeafb..66d37a9 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java
@@ -2,7 +2,7 @@ package org.keycloak.services.resources.admin;
 
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.NotFoundException;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.ModelDuplicateException;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleContainerModel;
@@ -20,6 +20,7 @@ import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 import java.util.ArrayList;
@@ -43,13 +44,13 @@ public class RoleContainerResource extends RoleResource {
     }
 
     /**
-     * List all roles for this realm or application
+     * List all roles for this realm or client
      *
      * @return
      */
     @GET
     @NoCache
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     public List<RoleRepresentation> getRoles() {
         auth.requireAny();
 
@@ -62,14 +63,14 @@ public class RoleContainerResource extends RoleResource {
     }
 
     /**
-     * Create a new role for this realm or application
+     * Create a new role for this realm or client
      *
      * @param uriInfo
      * @param rep
      * @return
      */
     @POST
-    @Consumes("application/json")
+    @Consumes(MediaType.APPLICATION_JSON)
     public Response createRole(final @Context UriInfo uriInfo, final RoleRepresentation rep) {
         auth.requireManage();
 
@@ -91,7 +92,7 @@ public class RoleContainerResource extends RoleResource {
     @Path("{role-name}")
     @GET
     @NoCache
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     public RoleRepresentation getRole(final @PathParam("role-name") String roleName) {
         auth.requireView();
 
@@ -131,7 +132,7 @@ public class RoleContainerResource extends RoleResource {
      */
     @Path("{role-name}")
     @PUT
-    @Consumes("application/json")
+    @Consumes(MediaType.APPLICATION_JSON)
     public Response updateRole(final @PathParam("role-name") String roleName, final RoleRepresentation rep) {
         auth.requireManage();
 
@@ -155,7 +156,7 @@ public class RoleContainerResource extends RoleResource {
      */
     @Path("{role-name}/composites")
     @POST
-    @Consumes("application/json")
+    @Consumes(MediaType.APPLICATION_JSON)
     public void addComposites(final @PathParam("role-name") String roleName, List<RoleRepresentation> roles) {
         auth.requireManage();
 
@@ -175,7 +176,7 @@ public class RoleContainerResource extends RoleResource {
     @Path("{role-name}/composites")
     @GET
     @NoCache
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     public Set<RoleRepresentation> getRoleComposites(final @PathParam("role-name") String roleName) {
         auth.requireManage();
 
@@ -195,7 +196,7 @@ public class RoleContainerResource extends RoleResource {
     @Path("{role-name}/composites/realm")
     @GET
     @NoCache
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     public Set<RoleRepresentation> getRealmRoleComposites(final @PathParam("role-name") String roleName) {
         auth.requireManage();
 
@@ -207,30 +208,30 @@ public class RoleContainerResource extends RoleResource {
     }
 
     /**
-     * An app-level roles for a specific app for this role's composite
+     * An client-level roles for a specific client for this role's composite
      *
      * @param roleName role's name (not id!)
-     * @param appName
+     * @param clientId
      * @return
      */
-    @Path("{role-name}/composites/application/{app}")
+    @Path("{role-name}/composites/client/{clientId}")
     @GET
     @NoCache
-    @Produces("application/json")
-    public Set<RoleRepresentation> getApplicationRoleComposites(final @PathParam("role-name") String roleName,
-                                                                final @PathParam("app") String appName) {
+    @Produces(MediaType.APPLICATION_JSON)
+    public Set<RoleRepresentation> getClientRoleComposites(final @PathParam("role-name") String roleName,
+                                                           final @PathParam("clientId") String clientId) {
         auth.requireManage();
 
         RoleModel role = roleContainer.getRole(roleName);
         if (role == null) {
             throw new NotFoundException("Could not find role: " + roleName);
         }
-        ApplicationModel app = realm.getApplicationByName(appName);
+        ClientModel app = realm.getClientByClientId(clientId);
         if (app == null) {
-            throw new NotFoundException("Could not find application: " + appName);
+            throw new NotFoundException("Could not find client: " + clientId);
 
         }
-        return getApplicationRoleComposites(app, role);
+        return getClientRoleComposites(app, role);
     }
 
 
@@ -238,27 +239,27 @@ public class RoleContainerResource extends RoleResource {
      * An app-level roles for a specific app for this role's composite
      *
      * @param roleName role's name (not id!)
-     * @param appId
+     * @param id
      * @return
      */
-    @Path("{role-name}/composites/application-by-id/{appId}")
+    @Path("{role-name}/composites/client-by-id/{id}")
     @GET
     @NoCache
-    @Produces("application/json")
-    public Set<RoleRepresentation> getApplicationByIdRoleComposites(final @PathParam("role-name") String roleName,
-                                                                final @PathParam("appId") String appId) {
+    @Produces(MediaType.APPLICATION_JSON)
+    public Set<RoleRepresentation> getClientByIdRoleComposites(final @PathParam("role-name") String roleName,
+                                                                final @PathParam("id") String id) {
         auth.requireManage();
 
         RoleModel role = roleContainer.getRole(roleName);
         if (role == null) {
             throw new NotFoundException("Could not find role: " + roleName);
         }
-        ApplicationModel app = realm.getApplicationById(appId);
-        if (app == null) {
-            throw new NotFoundException("Could not find application: " + appId);
+        ClientModel client = realm.getClientById(id);
+        if (client == null) {
+            throw new NotFoundException("Could not find client: " + id);
 
         }
-        return getApplicationRoleComposites(app, role);
+        return getClientRoleComposites(client, role);
     }
 
 
@@ -270,7 +271,7 @@ public class RoleContainerResource extends RoleResource {
      */
     @Path("{role-name}/composites")
     @DELETE
-    @Consumes("application/json")
+    @Consumes(MediaType.APPLICATION_JSON)
     public void deleteComposites(final @PathParam("role-name") String roleName, List<RoleRepresentation> roles) {
         auth.requireManage();
 
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RoleResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RoleResource.java
index 8d6fd44..8196528 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RoleResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RoleResource.java
@@ -1,7 +1,7 @@
 package org.keycloak.services.resources.admin;
 
 import org.jboss.resteasy.spi.NotFoundException;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.utils.ModelToRepresentation;
@@ -69,7 +69,7 @@ public abstract class RoleResource {
         return composites;
     }
 
-    protected Set<RoleRepresentation> getApplicationRoleComposites(ApplicationModel app, RoleModel role) {
+    protected Set<RoleRepresentation> getClientRoleComposites(ClientModel app, RoleModel role) {
         if (!role.isComposite() || role.getComposites().size() == 0) return Collections.emptySet();
 
         Set<RoleRepresentation> composites = new HashSet<RoleRepresentation>(role.getComposites().size());
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedResource.java
index 8084c44..8d4e005 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ScopeMappedResource.java
@@ -2,13 +2,12 @@ package org.keycloak.services.resources.admin;
 
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.NotFoundException;
-import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.utils.ModelToRepresentation;
-import org.keycloak.representations.idm.ApplicationMappingsRepresentation;
+import org.keycloak.representations.idm.ClientMappingsRepresentation;
 import org.keycloak.representations.idm.MappingsRepresentation;
 import org.keycloak.representations.idm.RoleRepresentation;
 
@@ -19,6 +18,7 @@ import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -26,7 +26,7 @@ import java.util.Map;
 import java.util.Set;
 
 /**
- * Base class for managing the scope mappings of a specific client (application or oauth).
+ * Base class for managing the scope mappings of a specific client.
  *
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
@@ -50,7 +50,7 @@ public class ScopeMappedResource {
      * @return
      */
     @GET
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     @NoCache
     public MappingsRepresentation getScopeMappings() {
         auth.requireView();
@@ -65,22 +65,22 @@ public class ScopeMappedResource {
             all.setRealmMappings(realmRep);
         }
 
-        List<ApplicationModel> applications = realm.getApplications();
-        if (applications.size() > 0) {
-            Map<String, ApplicationMappingsRepresentation> appMappings = new HashMap<String, ApplicationMappingsRepresentation>();
-            for (ApplicationModel app : applications) {
-                Set<RoleModel> roleMappings = app.getApplicationScopeMappings(client);
+        List<ClientModel> clients = realm.getClients();
+        if (clients.size() > 0) {
+            Map<String, ClientMappingsRepresentation> clientMappings = new HashMap<String, ClientMappingsRepresentation>();
+            for (ClientModel client : clients) {
+                Set<RoleModel> roleMappings = client.getClientScopeMappings(this.client);
                 if (roleMappings.size() > 0) {
-                    ApplicationMappingsRepresentation mappings = new ApplicationMappingsRepresentation();
-                    mappings.setApplicationId(app.getId());
-                    mappings.setApplication(app.getName());
+                    ClientMappingsRepresentation mappings = new ClientMappingsRepresentation();
+                    mappings.setId(client.getId());
+                    mappings.setClient(client.getClientId());
                     List<RoleRepresentation> roles = new ArrayList<RoleRepresentation>();
                     mappings.setMappings(roles);
                     for (RoleModel role : roleMappings) {
                         roles.add(ModelToRepresentation.toRepresentation(role));
                     }
-                    appMappings.put(app.getName(), mappings);
-                    all.setApplicationMappings(appMappings);
+                    clientMappings.put(client.getClientId(), mappings);
+                    all.setClientMappings(clientMappings);
                 }
             }
         }
@@ -94,7 +94,7 @@ public class ScopeMappedResource {
      */
     @Path("realm")
     @GET
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     @NoCache
     public List<RoleRepresentation> getRealmScopeMappings() {
         auth.requireView();
@@ -114,7 +114,7 @@ public class ScopeMappedResource {
      */
     @Path("realm/available")
     @GET
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     @NoCache
     public List<RoleRepresentation> getAvailableRealmScopeMappings() {
         auth.requireView();
@@ -141,7 +141,7 @@ public class ScopeMappedResource {
      */
     @Path("realm/composite")
     @GET
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     @NoCache
     public List<RoleRepresentation> getCompositeRealmScopeMappings() {
         auth.requireView();
@@ -165,7 +165,7 @@ public class ScopeMappedResource {
      */
     @Path("realm")
     @POST
-    @Consumes("application/json")
+    @Consumes(MediaType.APPLICATION_JSON)
     public void addRealmScopeMappings(List<RoleRepresentation> roles) {
         auth.requireManage();
 
@@ -187,7 +187,7 @@ public class ScopeMappedResource {
      */
     @Path("realm")
     @DELETE
-    @Consumes("application/json")
+    @Consumes(MediaType.APPLICATION_JSON)
     public void deleteRealmScopeMappings(List<RoleRepresentation> roles) {
         auth.requireManage();
 
@@ -201,32 +201,32 @@ public class ScopeMappedResource {
             for (RoleRepresentation role : roles) {
                 RoleModel roleModel = realm.getRoleById(role.getId());
                 if (roleModel == null) {
-                    throw new NotFoundException("Application not found");
+                    throw new NotFoundException("Client not found");
                 }
                 client.deleteScopeMapping(roleModel);
             }
         }
     }
 
-    @Path("applications/{app}")
-    public ScopeMappedApplicationResource getApplicationScopeMappings(@PathParam("app") String appName) {
-        ApplicationModel app = realm.getApplicationByName(appName);
+    @Path("clients/{clientId}")
+    public ScopeMappedClientResource getClientScopeMappings(@PathParam("clientId") String clientId) {
+        ClientModel app = realm.getClientByClientId(clientId);
 
         if (app == null) {
             throw new NotFoundException("Role not found");
         }
 
-        return new ScopeMappedApplicationResource(realm, auth, client, session, app);
+        return new ScopeMappedClientResource(realm, auth, client, session, app);
     }
 
-    @Path("applications-by-id/{appId}")
-    public ScopeMappedApplicationResource getApplicationByIdScopeMappings(@PathParam("appId") String appId) {
-        ApplicationModel app = realm.getApplicationById(appId);
+    @Path("clients-by-id/{id}")
+    public ScopeMappedClientResource getClientByIdScopeMappings(@PathParam("id") String id) {
+        ClientModel app = realm.getClientById(id);
 
         if (app == null) {
-            throw new NotFoundException("Application not found");
+            throw new NotFoundException("Client not found");
         }
 
-        return new ScopeMappedApplicationResource(realm, auth, client, session, app);
+        return new ScopeMappedClientResource(realm, auth, client, session, app);
     }
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ServerInfoAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ServerInfoAdminResource.java
index acaa0b8..0bdb525 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ServerInfoAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ServerInfoAdminResource.java
@@ -5,8 +5,8 @@ import org.keycloak.broker.provider.IdentityProvider;
 import org.keycloak.broker.provider.IdentityProviderFactory;
 import org.keycloak.events.EventListenerProvider;
 import org.keycloak.events.EventType;
-import org.keycloak.exportimport.ApplicationImporter;
-import org.keycloak.exportimport.ApplicationImporterFactory;
+import org.keycloak.exportimport.ClientImporter;
+import org.keycloak.exportimport.ClientImporterFactory;
 import org.keycloak.freemarker.Theme;
 import org.keycloak.freemarker.ThemeProvider;
 import org.keycloak.models.KeycloakSession;
@@ -56,7 +56,7 @@ public class ServerInfoAdminResource {
         setThemes(info);
         setEventListeners(info);
         setProtocols(info);
-        setApplicationImporters(info);
+        setClientImporters(info);
         setProviders(info);
         setProtocolMapperTypes(info);
         setBuiltinProtocolMappers(info);
@@ -168,14 +168,14 @@ public class ServerInfoAdminResource {
         }
     }
 
-    private void setApplicationImporters(ServerInfoRepresentation info) {
-        info.applicationImporters = new LinkedList<Map<String, String>>();
-        for (ProviderFactory p : session.getKeycloakSessionFactory().getProviderFactories(ApplicationImporter.class)) {
-            ApplicationImporterFactory factory = (ApplicationImporterFactory)p;
+    private void setClientImporters(ServerInfoRepresentation info) {
+        info.clientImporters = new LinkedList<Map<String, String>>();
+        for (ProviderFactory p : session.getKeycloakSessionFactory().getProviderFactories(ClientImporter.class)) {
+            ClientImporterFactory factory = (ClientImporterFactory)p;
             Map<String, String> data = new HashMap<String, String>();
             data.put("id", factory.getId());
             data.put("name", factory.getDisplayName());
-            info.applicationImporters.add(data);
+            info.clientImporters.add(data);
         }
     }
 
@@ -199,7 +199,7 @@ public class ServerInfoAdminResource {
         private List<Map<String, String>> socialProviders;
         public List<Map<String, String>> identityProviders;
         private List<String> protocols;
-        private List<Map<String, String>> applicationImporters;
+        private List<Map<String, String>> clientImporters;
 
         private Map<String, Set<String>> providers;
 
@@ -240,8 +240,8 @@ public class ServerInfoAdminResource {
             return protocols;
         }
 
-        public List<Map<String, String>> getApplicationImporters() {
-            return applicationImporters;
+        public List<Map<String, String>> getClientImporters() {
+            return clientImporters;
         }
 
         public Map<String, Set<String>> getProviders() {
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UserFederationResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UserFederationResource.java
index 006124b..188cb30 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/UserFederationResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UserFederationResource.java
@@ -28,6 +28,7 @@ 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.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 import java.util.LinkedList;
@@ -67,7 +68,7 @@ public class UserFederationResource {
     @GET
     @NoCache
     @Path("providers")
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     public List<UserFederationProviderFactoryRepresentation> getProviders() {
         auth.requireView();
         List<UserFederationProviderFactoryRepresentation> providers = new LinkedList<UserFederationProviderFactoryRepresentation>();
@@ -88,7 +89,7 @@ public class UserFederationResource {
     @GET
     @NoCache
     @Path("providers/{id}")
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     public UserFederationProviderFactoryRepresentation getProvider(@PathParam("id") String id) {
         auth.requireView();
         for (ProviderFactory factory : session.getKeycloakSessionFactory().getProviderFactories(UserFederationProvider.class)) {
@@ -111,7 +112,7 @@ public class UserFederationResource {
      */
     @POST
     @Path("instances")
-    @Consumes("application/json")
+    @Consumes(MediaType.APPLICATION_JSON)
     public Response createProviderInstance(UserFederationProviderRepresentation rep) {
         auth.requireManage();
         String displayName = rep.getDisplayName();
@@ -133,7 +134,7 @@ public class UserFederationResource {
      */
     @PUT
     @Path("instances/{id}")
-    @Consumes("application/json")
+    @Consumes(MediaType.APPLICATION_JSON)
     public void updateProviderInstance(@PathParam("id") String id, UserFederationProviderRepresentation rep) {
         auth.requireManage();
         String displayName = rep.getDisplayName();
@@ -155,7 +156,7 @@ public class UserFederationResource {
     @GET
     @NoCache
     @Path("instances/{id}")
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     public UserFederationProviderRepresentation getProviderInstance(@PathParam("id") String id) {
         auth.requireView();
         for (UserFederationProviderModel model : realm.getUserFederationProviders()) {
@@ -191,7 +192,7 @@ public class UserFederationResource {
      */
     @GET
     @Path("instances")
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     @NoCache
     public List<UserFederationProviderRepresentation> getUserFederationInstances() {
         auth.requireManage();
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
index ff5370b..8bad898 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
@@ -7,7 +7,6 @@ import org.jboss.resteasy.spi.NotFoundException;
 import org.keycloak.ClientConnection;
 import org.keycloak.email.EmailException;
 import org.keycloak.email.EmailProvider;
-import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.Constants;
@@ -26,7 +25,7 @@ import org.keycloak.models.utils.RepresentationToModel;
 import org.keycloak.protocol.oidc.OIDCLoginProtocol;
 import org.keycloak.protocol.oidc.TokenManager;
 import org.keycloak.protocol.oidc.utils.RedirectUtils;
-import org.keycloak.representations.idm.ApplicationMappingsRepresentation;
+import org.keycloak.representations.idm.ClientMappingsRepresentation;
 import org.keycloak.representations.idm.CredentialRepresentation;
 import org.keycloak.representations.idm.FederatedIdentityRepresentation;
 import org.keycloak.representations.idm.MappingsRepresentation;
@@ -107,7 +106,7 @@ public class UsersResource {
      */
     @Path("{username}")
     @PUT
-    @Consumes("application/json")
+    @Consumes(MediaType.APPLICATION_JSON)
     public Response updateUser(final @PathParam("username") String username, final UserRepresentation rep) {
         auth.requireManage();
 
@@ -138,7 +137,7 @@ public class UsersResource {
      * @return
      */
     @POST
-    @Consumes("application/json")
+    @Consumes(MediaType.APPLICATION_JSON)
     public Response createUser(final @Context UriInfo uriInfo, final UserRepresentation rep) {
         auth.requireManage();
 
@@ -210,7 +209,7 @@ public class UsersResource {
     @Path("{username}")
     @GET
     @NoCache
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     public UserRepresentation getUser(final @PathParam("username") String username) {
         auth.requireView();
 
@@ -312,7 +311,7 @@ public class UsersResource {
     }
 
     /**
-     * Remove all user sessions associated with this user.  And, for all applications that have an admin URL, tell
+     * Remove all user sessions associated with this user.  And, for all client that have an admin URL, tell
      * them to invalidate the sessions for this particular user.
      *
      * @param username username (not id!)
@@ -369,7 +368,7 @@ public class UsersResource {
      */
     @GET
     @NoCache
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     public List<UserRepresentation> getUsers(@QueryParam("search") String search,
                                              @QueryParam("lastName") String last,
                                              @QueryParam("firstName") String first,
@@ -419,7 +418,7 @@ public class UsersResource {
      */
     @Path("{username}/role-mappings")
     @GET
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     @NoCache
     public MappingsRepresentation getRoleMappings(@PathParam("username") String username) {
         auth.requireView();
@@ -440,22 +439,22 @@ public class UsersResource {
             all.setRealmMappings(realmRep);
         }
 
-        List<ApplicationModel> applications = realm.getApplications();
-        if (applications.size() > 0) {
-            Map<String, ApplicationMappingsRepresentation> appMappings = new HashMap<String, ApplicationMappingsRepresentation>();
-            for (ApplicationModel application : applications) {
-                Set<RoleModel> roleMappings = user.getApplicationRoleMappings(application);
+        List<ClientModel> clients = realm.getClients();
+        if (clients.size() > 0) {
+            Map<String, ClientMappingsRepresentation> appMappings = new HashMap<String, ClientMappingsRepresentation>();
+            for (ClientModel client : clients) {
+                Set<RoleModel> roleMappings = user.getClientRoleMappings(client);
                 if (roleMappings.size() > 0) {
-                    ApplicationMappingsRepresentation mappings = new ApplicationMappingsRepresentation();
-                    mappings.setApplicationId(application.getId());
-                    mappings.setApplication(application.getName());
+                    ClientMappingsRepresentation mappings = new ClientMappingsRepresentation();
+                    mappings.setId(client.getId());
+                    mappings.setClient(client.getClientId());
                     List<RoleRepresentation> roles = new ArrayList<RoleRepresentation>();
                     mappings.setMappings(roles);
                     for (RoleModel role : roleMappings) {
                         roles.add(ModelToRepresentation.toRepresentation(role));
                     }
-                    appMappings.put(application.getName(), mappings);
-                    all.setApplicationMappings(appMappings);
+                    appMappings.put(client.getClientId(), mappings);
+                    all.setClientMappings(appMappings);
                 }
             }
         }
@@ -470,7 +469,7 @@ public class UsersResource {
      */
     @Path("{username}/role-mappings/realm")
     @GET
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     @NoCache
     public List<RoleRepresentation> getRealmRoleMappings(@PathParam("username") String username) {
         auth.requireView();
@@ -496,7 +495,7 @@ public class UsersResource {
      */
     @Path("{username}/role-mappings/realm/composite")
     @GET
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     @NoCache
     public List<RoleRepresentation> getCompositeRealmRoleMappings(@PathParam("username") String username) {
         auth.requireView();
@@ -524,7 +523,7 @@ public class UsersResource {
      */
     @Path("{username}/role-mappings/realm/available")
     @GET
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     @NoCache
     public List<RoleRepresentation> getAvailableRealmRoleMappings(@PathParam("username") String username) {
         auth.requireView();
@@ -535,7 +534,7 @@ public class UsersResource {
         }
 
         Set<RoleModel> available = realm.getRoles();
-        return UserApplicationRoleMappingsResource.getAvailableRoles(user, available);
+        return UserClientRoleMappingsResource.getAvailableRoles(user, available);
     }
 
     /**
@@ -546,7 +545,7 @@ public class UsersResource {
      */
     @Path("{username}/role-mappings/realm")
     @POST
-    @Consumes("application/json")
+    @Consumes(MediaType.APPLICATION_JSON)
     public void addRealmRoleMappings(@PathParam("username") String username, List<RoleRepresentation> roles) {
         auth.requireManage();
 
@@ -575,7 +574,7 @@ public class UsersResource {
      */
     @Path("{username}/role-mappings/realm")
     @DELETE
-    @Consumes("application/json")
+    @Consumes(MediaType.APPLICATION_JSON)
     public void deleteRealmRoleMappings(@PathParam("username") String username, List<RoleRepresentation> roles) {
         auth.requireManage();
 
@@ -602,36 +601,36 @@ public class UsersResource {
         }
     }
 
-    @Path("{username}/role-mappings/applications/{app}")
-    public UserApplicationRoleMappingsResource getUserApplicationRoleMappingsResource(@PathParam("username") String username, @PathParam("app") String appName) {
+    @Path("{username}/role-mappings/clients/{clientId}")
+    public UserClientRoleMappingsResource getUserClientRoleMappingsResource(@PathParam("username") String username, @PathParam("clientId") String clientId) {
         UserModel user = session.users().getUserByUsername(username, realm);
         if (user == null) {
             throw new NotFoundException("User not found");
         }
 
-        ApplicationModel application = realm.getApplicationByName(appName);
+        ClientModel client = realm.getClientByClientId(clientId);
 
-        if (application == null) {
-            throw new NotFoundException("Application not found");
+        if (client == null) {
+            throw new NotFoundException("Client not found");
         }
 
-        return new UserApplicationRoleMappingsResource(realm, auth, user, application);
+        return new UserClientRoleMappingsResource(realm, auth, user, client);
 
     }
-    @Path("{username}/role-mappings/applications-by-id/{appId}")
-    public UserApplicationRoleMappingsResource getUserApplicationRoleMappingsResourceById(@PathParam("username") String username, @PathParam("appId") String appId) {
+    @Path("{username}/role-mappings/clients-by-id/{id}")
+    public UserClientRoleMappingsResource getUserClientRoleMappingsResourceById(@PathParam("username") String username, @PathParam("id") String id) {
         UserModel user = session.users().getUserByUsername(username, realm);
         if (user == null) {
             throw new NotFoundException("User not found");
         }
 
-        ApplicationModel application = realm.getApplicationById(appId);
+        ClientModel client = realm.getClientById(id);
 
-        if (application == null) {
-            throw new NotFoundException("Application not found");
+        if (client == null) {
+            throw new NotFoundException("Client not found");
         }
 
-        return new UserApplicationRoleMappingsResource(realm, auth, user, application);
+        return new UserClientRoleMappingsResource(realm, auth, user, client);
 
     }
     /**
@@ -643,7 +642,7 @@ public class UsersResource {
      */
     @Path("{username}/reset-password")
     @PUT
-    @Consumes("application/json")
+    @Consumes(MediaType.APPLICATION_JSON)
     public void resetPassword(@PathParam("username") String username, CredentialRepresentation pass) {
         auth.requireManage();
 
@@ -671,7 +670,7 @@ public class UsersResource {
      */
     @Path("{username}/remove-totp")
     @PUT
-    @Consumes("application/json")
+    @Consumes(MediaType.APPLICATION_JSON)
     public void removeTotp(@PathParam("username") String username) {
         auth.requireManage();
 
@@ -686,7 +685,7 @@ public class UsersResource {
     /**
      * Send an email to the user with a link they can click to reset their password.
      * The redirectUri and clientId parameters are optional. The default for the
-     * redirect is the account application.
+     * redirect is the account client.
      *
      * @param username username (not id!)
      * @param redirectUri redirect uri
@@ -695,7 +694,7 @@ public class UsersResource {
      */
     @Path("{username}/reset-password-email")
     @PUT
-    @Consumes("application/json")
+    @Consumes(MediaType.APPLICATION_JSON)
     public Response resetPasswordEmail(@PathParam("username") String username, @QueryParam(OIDCLoginProtocol.REDIRECT_URI_PARAM) String redirectUri, @QueryParam(OIDCLoginProtocol.CLIENT_ID_PARAM) String clientId) {
         auth.requireManage();
 
@@ -717,10 +716,10 @@ public class UsersResource {
         }
 
         if(clientId == null){
-            clientId = Constants.ACCOUNT_MANAGEMENT_APP;
+            clientId = Constants.ACCOUNT_MANAGEMENT_CLIENT_ID;
         }
 
-        ClientModel client = realm.findClient(clientId);
+        ClientModel client = realm.getClientByClientId(clientId);
         if (client == null || !client.isEnabled()) {
             return Flows.errors().error(clientId + " not enabled", Response.Status.INTERNAL_SERVER_ERROR);
         }
diff --git a/services/src/main/java/org/keycloak/services/resources/ClientsManagementService.java b/services/src/main/java/org/keycloak/services/resources/ClientsManagementService.java
index 1761138..1eb5480 100755
--- a/services/src/main/java/org/keycloak/services/resources/ClientsManagementService.java
+++ b/services/src/main/java/org/keycloak/services/resources/ClientsManagementService.java
@@ -1,20 +1,5 @@
 package org.keycloak.services.resources;
 
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.ws.rs.HeaderParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.core.UriInfo;
-import javax.ws.rs.ext.Providers;
-
 import org.jboss.logging.Logger;
 import org.jboss.resteasy.spi.BadRequestException;
 import org.jboss.resteasy.spi.HttpRequest;
@@ -26,15 +11,28 @@ import org.keycloak.events.Details;
 import org.keycloak.events.Errors;
 import org.keycloak.events.EventBuilder;
 import org.keycloak.events.EventType;
-import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
-import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.protocol.oidc.utils.AuthorizeClientUtil;
 import org.keycloak.services.ForbiddenException;
 import org.keycloak.util.Time;
 
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.ext.Providers;
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
  */
@@ -84,7 +82,7 @@ public class ClientsManagementService {
     }
 
     /**
-     * URL invoked by adapter to register new application cluster node. Each application cluster node will invoke this URL once it joins cluster
+     * URL invoked by adapter to register new client cluster node. Each application cluster node will invoke this URL once it joins cluster
      *
      * @param authorizationHeader
      * @param formData
@@ -92,7 +90,7 @@ public class ClientsManagementService {
      */
     @Path("register-node")
     @POST
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     public Response registerNode(@HeaderParam(HttpHeaders.AUTHORIZATION) String authorizationHeader, final MultivaluedMap<String, String> formData) {
         if (!checkSsl()) {
             throw new ForbiddenException("HTTPS required");
@@ -105,13 +103,13 @@ public class ClientsManagementService {
             throw new UnauthorizedException("Realm not enabled");
         }
 
-        ApplicationModel application = authorizeApplication(authorizationHeader, formData);
-        String nodeHost = getApplicationClusterHost(formData);
+        ClientModel client = authorizeClient(authorizationHeader, formData);
+        String nodeHost = getClientClusterHost(formData);
 
-        event.client(application).detail(Details.NODE_HOST, nodeHost);
-        logger.debugf("Registering cluster host '%s' for client '%s'", nodeHost, application.getName());
+        event.client(client).detail(Details.NODE_HOST, nodeHost);
+        logger.debugf("Registering cluster host '%s' for client '%s'", nodeHost, client.getClientId());
 
-        application.registerNode(nodeHost, Time.currentTime());
+        client.registerNode(nodeHost, Time.currentTime());
 
         event.success();
 
@@ -120,7 +118,7 @@ public class ClientsManagementService {
 
 
     /**
-     * URL invoked by adapter to register new application cluster node. Each application cluster node will invoke this URL once it joins cluster
+     * URL invoked by adapter to register new client cluster node. Each application cluster node will invoke this URL once it joins cluster
      *
      * @param authorizationHeader
      * @param formData
@@ -128,7 +126,7 @@ public class ClientsManagementService {
      */
     @Path("unregister-node")
     @POST
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     public Response unregisterNode(@HeaderParam(HttpHeaders.AUTHORIZATION) String authorizationHeader, final MultivaluedMap<String, String> formData) {
         if (!checkSsl()) {
             throw new ForbiddenException("HTTPS required");
@@ -141,20 +139,20 @@ public class ClientsManagementService {
             throw new UnauthorizedException("Realm not enabled");
         }
 
-        ApplicationModel application = authorizeApplication(authorizationHeader, formData);
-        String nodeHost = getApplicationClusterHost(formData);
+        ClientModel client = authorizeClient(authorizationHeader, formData);
+        String nodeHost = getClientClusterHost(formData);
 
-        event.client(application).detail(Details.NODE_HOST, nodeHost);
-        logger.debugf("Unregistering cluster host '%s' for client '%s'", nodeHost, application.getName());
+        event.client(client).detail(Details.NODE_HOST, nodeHost);
+        logger.debugf("Unregistering cluster host '%s' for client '%s'", nodeHost, client.getClientId());
 
-        application.unregisterNode(nodeHost);
+        client.unregisterNode(nodeHost);
 
         event.success();
 
         return Response.noContent().build();
     }
 
-    protected ApplicationModel authorizeApplication(String authorizationHeader, MultivaluedMap<String, String> formData) {
+    protected ClientModel authorizeClient(String authorizationHeader, MultivaluedMap<String, String> formData) {
         ClientModel client = AuthorizeClientUtil.authorizeClient(authorizationHeader, formData, event, realm);
 
         if (client.isPublicClient()) {
@@ -162,31 +160,23 @@ public class ClientsManagementService {
             error.put(OAuth2Constants.ERROR, "invalid_client");
             error.put(OAuth2Constants.ERROR_DESCRIPTION, "Public clients not allowed");
             event.error(Errors.INVALID_CLIENT);
-            throw new BadRequestException("Public clients not allowed", javax.ws.rs.core.Response.status(javax.ws.rs.core.Response.Status.BAD_REQUEST).entity(error).type("application/json").build());
-        }
-
-        if (!(client instanceof ApplicationModel)) {
-            Map<String, String> error = new HashMap<String, String>();
-            error.put(OAuth2Constants.ERROR, "invalid_client");
-            error.put(OAuth2Constants.ERROR_DESCRIPTION, "Just applications are allowed");
-            event.error(Errors.INVALID_CLIENT);
-            throw new BadRequestException("ust applications are allowed", javax.ws.rs.core.Response.status(javax.ws.rs.core.Response.Status.BAD_REQUEST).entity(error).type("application/json").build());
+            throw new BadRequestException("Public clients not allowed", javax.ws.rs.core.Response.status(javax.ws.rs.core.Response.Status.BAD_REQUEST).entity(error).type(MediaType.APPLICATION_JSON_TYPE).build());
         }
 
-        return (ApplicationModel)client;
+        return client;
     }
 
-    protected String getApplicationClusterHost(MultivaluedMap<String, String> formData) {
-        String applicationClusterHost = formData.getFirst(AdapterConstants.APPLICATION_CLUSTER_HOST);
-        if (applicationClusterHost == null || applicationClusterHost.length() == 0) {
+    protected String getClientClusterHost(MultivaluedMap<String, String> formData) {
+        String clientClusterHost = formData.getFirst(AdapterConstants.CLIENT_CLUSTER_HOST);
+        if (clientClusterHost == null || clientClusterHost.length() == 0) {
             Map<String, String> error = new HashMap<String, String>();
             error.put(OAuth2Constants.ERROR, "invalid_request");
-            error.put(OAuth2Constants.ERROR_DESCRIPTION, "application cluster host not specified");
+            error.put(OAuth2Constants.ERROR_DESCRIPTION, "Client cluster host not specified");
             event.error(Errors.INVALID_CODE);
-            throw new BadRequestException("Cluster host not specified", javax.ws.rs.core.Response.status(javax.ws.rs.core.Response.Status.BAD_REQUEST).entity(error).type("application/json").build());
+            throw new BadRequestException("Cluster host not specified", javax.ws.rs.core.Response.status(javax.ws.rs.core.Response.Status.BAD_REQUEST).entity(error).type(MediaType.APPLICATION_JSON_TYPE).build());
         }
 
-        return applicationClusterHost;
+        return clientClusterHost;
     }
 
 
diff --git a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
index 89ce7cc..4098d33 100755
--- a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
+++ b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
@@ -36,7 +36,6 @@ import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.FederatedIdentityModel;
 import org.keycloak.models.IdentityProviderModel;
 import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.UserSessionModel;
@@ -75,7 +74,7 @@ import java.util.Map;
 
 import static org.keycloak.models.AccountRoles.MANAGE_ACCOUNT;
 import static org.keycloak.models.ClientSessionModel.Action.AUTHENTICATE;
-import static org.keycloak.models.Constants.ACCOUNT_MANAGEMENT_APP;
+import static org.keycloak.models.Constants.ACCOUNT_MANAGEMENT_CLIENT_ID;
 import static org.keycloak.models.UserModel.RequiredAction.UPDATE_PROFILE;
 
 /**
@@ -181,7 +180,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
 
             if (authResult != null) {
                 String audience = authResult.getToken().getAudience();
-                ClientModel clientModel = this.realmModel.findClient(audience);
+                ClientModel clientModel = this.realmModel.getClientByClientId(audience);
 
                 if (clientModel == null) {
                     return badRequest("Invalid client.");
@@ -191,7 +190,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
                     return corsResponse(badRequest("Client [" + audience + "] not authorized to retrieve tokens from identity provider [" + providerId + "]."), clientModel);
                 }
 
-                if (OAuthClientModel.class.isInstance(clientModel) && !forceRetrieval) {
+                if (clientModel.isConsentRequired()) {
                     return corsResponse(Flows.forms(this.session, this.realmModel, clientModel, this.uriInfo, headers)
                             .setClientSessionCode(authManager.extractAuthorizationHeaderToken(this.request.getHttpHeaders()))
                             .setAccessRequest("Your information from " + providerId + " identity provider.")
@@ -323,7 +322,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
             return redirectToErrorPage(Messages.ACCOUNT_DISABLED);
         }
 
-        if (!authenticatedUser.hasRole(this.realmModel.getApplicationByName(ACCOUNT_MANAGEMENT_APP).getRole(MANAGE_ACCOUNT))) {
+        if (!authenticatedUser.hasRole(this.realmModel.getClientByClientId(ACCOUNT_MANAGEMENT_CLIENT_ID).getRole(MANAGE_ACCOUNT))) {
             fireErrorEvent(Errors.NOT_ALLOWED);
             return redirectToErrorPage(Messages.INSUFFICIENT_PERMISSION);
         }
@@ -379,7 +378,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
             return clientCode;
         }
 
-        throw new IdentityBrokerException("Invalid code, please login again through your application.");
+        throw new IdentityBrokerException("Invalid code, please login again through your client.");
     }
 
     private AuthenticationRequest createAuthenticationRequest(String providerId, ClientSessionCode clientSessionCode) {
diff --git a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
index 078e408..106be1c 100755
--- a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
+++ b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
@@ -36,7 +36,6 @@ import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.ModelException;
-import org.keycloak.models.PasswordPolicy;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RequiredCredentialModel;
 import org.keycloak.models.UserCredentialModel;
@@ -73,8 +72,6 @@ import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriBuilder;
 import javax.ws.rs.core.UriInfo;
 import javax.ws.rs.ext.Providers;
-
-import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
@@ -320,7 +317,6 @@ public class LoginActionsService {
             event.detail(Details.REMEMBER_ME, "true");
         }
 
-
         ClientModel client = clientSession.getClient();
         if (client == null) {
             event.error(Errors.CLIENT_NOT_FOUND);
diff --git a/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java b/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java
index b4c3284..25beaa5 100755
--- a/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java
@@ -14,6 +14,7 @@ import javax.ws.rs.OPTIONS;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 
@@ -59,7 +60,7 @@ public class PublicRealmResource {
      */
     @GET
     @NoCache
-    @Produces("application/json")
+    @Produces(MediaType.APPLICATION_JSON)
     public PublishedRealmRepresentation getRealm() {
         Cors.add(request).allowedOrigins(Cors.ACCESS_CONTROL_ALLOW_ORIGIN_WILDCARD).auth().build(response);
         return realmRep(realm, uriInfo);
diff --git a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
index daed1e0..571f111 100755
--- a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
@@ -5,7 +5,7 @@ import org.jboss.resteasy.spi.NotFoundException;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
 import org.keycloak.ClientConnection;
 import org.keycloak.events.EventBuilder;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.Constants;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
@@ -157,16 +157,15 @@ public class RealmsResource {
         RealmManager realmManager = new RealmManager(session);
         RealmModel realm = locateRealm(name, realmManager);
 
-        ApplicationModel application = realm.getApplicationNameMap().get(Constants.ACCOUNT_MANAGEMENT_APP);
-        if (application == null || !application.isEnabled()) {
+        ClientModel client = realm.getClientNameMap().get(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
+        if (client == null || !client.isEnabled()) {
             logger.debug("account management not enabled");
             throw new NotFoundException("account management not enabled");
         }
 
         EventBuilder event = new EventBuilder(realm, session, clientConnection);
-        AccountService accountService = new AccountService(realm, application, event);
+        AccountService accountService = new AccountService(realm, client, event);
         ResteasyProviderFactory.getInstance().injectProperties(accountService);
-        //resourceContext.initResource(accountService);
         accountService.init();
         return accountService;
     }
@@ -177,7 +176,6 @@ public class RealmsResource {
         RealmModel realm = locateRealm(name, realmManager);
         PublicRealmResource realmResource = new PublicRealmResource(realm);
         ResteasyProviderFactory.getInstance().injectProperties(realmResource);
-        //resourceContext.initResource(realmResource);
         return realmResource;
     }
 
@@ -188,7 +186,6 @@ public class RealmsResource {
 
         IdentityBrokerService brokerService = new IdentityBrokerService(realm);
         ResteasyProviderFactory.getInstance().injectProperties(brokerService);
-        //resourceContext.initResource(brokerService);
 
         brokerService.init();
 
diff --git a/services/src/main/resources/META-INF/services/org.keycloak.provider.Spi b/services/src/main/resources/META-INF/services/org.keycloak.provider.Spi
index cb01455..e1c0b91 100755
--- a/services/src/main/resources/META-INF/services/org.keycloak.provider.Spi
+++ b/services/src/main/resources/META-INF/services/org.keycloak.provider.Spi
@@ -1,4 +1,4 @@
 org.keycloak.protocol.LoginProtocolSpi
 org.keycloak.protocol.ProtocolMapperSpi
-org.keycloak.exportimport.ApplicationImportSpi
+org.keycloak.exportimport.ClientImportSpi
 org.keycloak.wellknown.WellKnownSpi
\ No newline at end of file
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java
index ce61d33..999fdb8 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java
@@ -25,13 +25,12 @@ import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.ClassRule;
-import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.keycloak.events.Details;
 import org.keycloak.events.Event;
 import org.keycloak.events.EventType;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.PasswordPolicy;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserCredentialModel;
@@ -75,7 +74,7 @@ public class AccountTest {
         public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
             UserModel user = manager.getSession().users().getUserByUsername("test-user@localhost", appRealm);
 
-            ApplicationModel accountApp = appRealm.getApplicationNameMap().get(org.keycloak.models.Constants.ACCOUNT_MANAGEMENT_APP);
+            ClientModel accountApp = appRealm.getClientNameMap().get(org.keycloak.models.Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
 
             UserModel user2 = manager.getSession().users().addUser(appRealm, "test-user-no-access@localhost");
             user2.setEnabled(true);
@@ -157,11 +156,6 @@ public class AccountTest {
         });
     }
 
-    //@Test @Ignore
-    public void runit() throws Exception {
-        Thread.sleep(10000000);
-    }
-
     @Test
     public void returnToAppFromQueryParam() {
         driver.navigate().to(AccountUpdateProfilePage.PATH + "?referrer=test-app");
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java
index 97e2095..44ebaf1 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java
@@ -12,7 +12,6 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.keycloak.OAuth2Constants;
 import org.keycloak.models.AccountRoles;
-import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserCredentialModel;
@@ -54,7 +53,7 @@ public class ProfileTest {
             user.setAttribute("key1", "value1");
             user.setAttribute("key2", "value2");
 
-            ApplicationModel accountApp = appRealm.getApplicationByName(org.keycloak.models.Constants.ACCOUNT_MANAGEMENT_APP);
+            ClientModel accountApp = appRealm.getClientByClientId(org.keycloak.models.Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
 
             UserModel user2 = manager.getSession().users().addUser(appRealm, "test-user-no-access@localhost");
             user2.setEnabled(true);
@@ -66,12 +65,12 @@ public class ProfileTest {
             creds.setValue("password");
             user2.updateCredential(creds);
 
-            ApplicationModel app = appRealm.getApplicationByName("test-app");
+            ClientModel app = appRealm.getClientByClientId("test-app");
             app.addScopeMapping(accountApp.getRole(AccountRoles.VIEW_PROFILE));
             app.addRedirectUri("http://localhost:8081/app/*");
             app.addWebOrigin("http://localtest.me:8081");
 
-            ClientModel thirdParty = appRealm.findClient("third-party");
+            ClientModel thirdParty = appRealm.getClientByClientId("third-party");
             thirdParty.addScopeMapping(accountApp.getRole(AccountRoles.VIEW_PROFILE));
         }
     });
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java
index 8feaac5..ba41ceb 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java
@@ -22,14 +22,13 @@
 package org.keycloak.testsuite.adapter;
 
 import org.junit.Assert;
-import org.junit.Test;
 import org.junit.rules.ExternalResource;
 import org.keycloak.Config;
 import org.keycloak.OAuth2Constants;
 import org.keycloak.Version;
 import org.keycloak.admin.client.Keycloak;
 import org.keycloak.constants.AdapterConstants;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.Constants;
 import org.keycloak.models.KeycloakSession;
@@ -41,7 +40,6 @@ import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.protocol.oidc.TokenManager;
 import org.keycloak.representations.AccessToken;
 import org.keycloak.representations.idm.RealmRepresentation;
-import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.services.managers.ResourceAdminManager;
 import org.keycloak.services.resources.admin.AdminRoot;
@@ -65,7 +63,6 @@ import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriBuilder;
 import java.net.URI;
-import java.util.List;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -139,7 +136,7 @@ public class AdapterTestStrategy extends ExternalResource {
             RealmManager manager = new RealmManager(session);
 
             RealmModel adminRealm = manager.getRealm(Config.getAdminRealm());
-            ApplicationModel adminConsole = adminRealm.getApplicationByName(Constants.ADMIN_CONSOLE_APPLICATION);
+            ClientModel adminConsole = adminRealm.getClientByClientId(Constants.ADMIN_CONSOLE_CLIENT_ID);
             TokenManager tm = new TokenManager();
             UserModel admin = session.users().getUserByUsername("admin", adminRealm);
             ClientSessionModel clientSession = session.sessions().createClientSession(adminRealm, adminConsole);
@@ -152,7 +149,6 @@ public class AdapterTestStrategy extends ExternalResource {
         }
     }
 
-    @Test
     public void testSavedPostRequest() throws Exception {
         // test login to customer-portal which does a bearer request to customer-db
         driver.navigate().to(APP_SERVER_BASE_URL + "/input-portal");
@@ -191,7 +187,6 @@ public class AdapterTestStrategy extends ExternalResource {
     }
 
 
-    @Test
     public void testLoginSSOAndLogout() throws Exception {
         // test login to customer-portal which does a bearer request to customer-db
         driver.navigate().to(APP_SERVER_BASE_URL + "/customer-portal");
@@ -217,7 +212,7 @@ public class AdapterTestStrategy extends ExternalResource {
         Client client = ClientBuilder.newClient();
         UriBuilder authBase = UriBuilder.fromUri(AUTH_SERVER_URL);
         WebTarget adminTarget = client.target(AdminRoot.realmsUrl(authBase)).path("demo");
-        Map<String, Integer> stats = adminTarget.path("application-session-stats").request()
+        Map<String, Integer> stats = adminTarget.path("client-session-stats").request()
                 .header(HttpHeaders.AUTHORIZATION, "Bearer " + adminToken)
                 .get(new GenericType<Map<String, Integer>>() {
                 });
@@ -248,7 +243,6 @@ public class AdapterTestStrategy extends ExternalResource {
 
     }
 
-    @Test
     public void testServletRequestLogout() throws Exception {
         // test login to customer-portal which does a bearer request to customer-db
         driver.navigate().to(APP_SERVER_BASE_URL + "/customer-portal");
@@ -290,7 +284,6 @@ public class AdapterTestStrategy extends ExternalResource {
 
     }
 
-    @Test
     public void testLoginSSOIdle() throws Exception {
         // test login to customer-portal which does a bearer request to customer-db
         driver.navigate().to(APP_SERVER_BASE_URL + "/customer-portal");
@@ -324,7 +317,6 @@ public class AdapterTestStrategy extends ExternalResource {
         session.close();
     }
 
-    @Test
     public void testLoginSSOIdleRemoveExpiredUserSessions() throws Exception {
         // test login to customer-portal which does a bearer request to customer-db
         driver.navigate().to(APP_SERVER_BASE_URL + "/customer-portal");
@@ -366,7 +358,6 @@ public class AdapterTestStrategy extends ExternalResource {
         session.close();
     }
 
-    @Test
     public void testLoginSSOMax() throws Exception {
         // test login to customer-portal which does a bearer request to customer-db
         driver.navigate().to(APP_SERVER_BASE_URL + "/customer-portal");
@@ -404,7 +395,6 @@ public class AdapterTestStrategy extends ExternalResource {
      * KEYCLOAK-518
      * @throws Exception
      */
-    @Test
     public void testNullBearerToken() throws Exception {
         Client client = ClientBuilder.newClient();
         WebTarget target = client.target(APP_SERVER_BASE_URL + "/customer-db/");
@@ -422,7 +412,6 @@ public class AdapterTestStrategy extends ExternalResource {
      * KEYCLOAK-518
      * @throws Exception
      */
-    @Test
     public void testBadUser() throws Exception {
         Client client = ClientBuilder.newClient();
         UriBuilder builder = UriBuilder.fromUri(AUTH_SERVER_URL);
@@ -442,7 +431,6 @@ public class AdapterTestStrategy extends ExternalResource {
 
     }
 
-    @Test
     public void testVersion() throws Exception {
         Client client = ClientBuilder.newClient();
         WebTarget target = client.target(AUTH_SERVER_URL).path("version");
@@ -465,7 +453,6 @@ public class AdapterTestStrategy extends ExternalResource {
 
 
 
-    @Test
     public void testAuthenticated() throws Exception {
         // test login to customer-portal which does a bearer request to customer-db
         driver.navigate().to(APP_SERVER_BASE_URL + "/secure-portal");
@@ -493,7 +480,6 @@ public class AdapterTestStrategy extends ExternalResource {
      *
      * @throws Throwable
      */
-    @Test
     public void testSingleSessionInvalidated() throws Throwable {
         AdapterTestStrategy browser1 = this;
         AdapterTestStrategy browser2 = new AdapterTestStrategy(AUTH_SERVER_URL, APP_SERVER_BASE_URL, keycloakRule);
@@ -531,7 +517,6 @@ public class AdapterTestStrategy extends ExternalResource {
     /**
      * KEYCLOAK-741
      */
-    @Test
     public void testSessionInvalidatedAfterFailedRefresh() throws Throwable {
         final AtomicInteger origTokenLifespan = new AtomicInteger();
 
@@ -539,7 +524,7 @@ public class AdapterTestStrategy extends ExternalResource {
         keycloakRule.update(new KeycloakRule.KeycloakSetup() {
             @Override
             public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel demoRealm) {
-                ApplicationModel sessionPortal = demoRealm.getApplicationByName("session-portal");
+                ClientModel sessionPortal = demoRealm.getClientByClientId("session-portal");
                 sessionPortal.setManagementUrl(null);
 
                 origTokenLifespan.set(demoRealm.getAccessTokenLifespan());
@@ -571,7 +556,7 @@ public class AdapterTestStrategy extends ExternalResource {
 
             @Override
             public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel demoRealm) {
-                ApplicationModel sessionPortal = demoRealm.getApplicationByName("session-portal");
+                ClientModel sessionPortal = demoRealm.getClientByClientId("session-portal");
                 sessionPortal.setManagementUrl(APP_SERVER_BASE_URL + "/session-portal");
 
                 demoRealm.setAccessTokenLifespan(origTokenLifespan.get());
@@ -583,14 +568,13 @@ public class AdapterTestStrategy extends ExternalResource {
     /**
      * KEYCLOAK-942
      */
-    @Test
     public void testAdminApplicationLogout() throws Throwable {
         // login as bburke
         loginAndCheckSession(driver, loginPage);
 
         // logout mposolda with admin client
-        Keycloak keycloakAdmin = Keycloak.getInstance(AUTH_SERVER_URL, "master", "admin", "admin", Constants.ADMIN_CONSOLE_APPLICATION);
-        keycloakAdmin.realm("demo").applications().get("session-portal").logoutUser("mposolda");
+        Keycloak keycloakAdmin = Keycloak.getInstance(AUTH_SERVER_URL, "master", "admin", "admin", Constants.ADMIN_CONSOLE_CLIENT_ID);
+        keycloakAdmin.realm("demo").clients().get("session-portal").logoutUser("mposolda");
 
         // bburke should be still logged with original httpSession in our browser window
         driver.navigate().to(APP_SERVER_BASE_URL + "/session-portal");
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/RelativeUriAdapterTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/RelativeUriAdapterTest.java
index 5c6ed7b..4c22533 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/RelativeUriAdapterTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/RelativeUriAdapterTest.java
@@ -26,7 +26,7 @@ import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
 import org.keycloak.OAuth2Constants;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.Constants;
 import org.keycloak.models.KeycloakSession;
@@ -85,7 +85,7 @@ public class RelativeUriAdapterTest {
             deployApplication("customer-db", "/customer-db", CustomerDatabaseServlet.class, url.getPath(), "user");
             url = getClass().getResource("/adapter-test/product-keycloak-relative.json");
             deployApplication("product-portal", "/product-portal", ProductServlet.class, url.getPath(), "user");
-            ApplicationModel adminConsole = adminRealm.getApplicationByName(Constants.ADMIN_CONSOLE_APPLICATION);
+            ClientModel adminConsole = adminRealm.getClientByClientId(Constants.ADMIN_CONSOLE_CLIENT_ID);
             TokenManager tm = new TokenManager();
             UserModel admin = session.users().getUserByUsername("admin", adminRealm);
             ClientSessionModel clientSession = session.sessions().createClientSession(realm, adminConsole);
@@ -135,7 +135,7 @@ public class RelativeUriAdapterTest {
         Client client = ClientBuilder.newClient();
         UriBuilder authBase = UriBuilder.fromUri("http://localhost:8081/auth");
         WebTarget adminTarget = client.target(AdminRoot.realmsUrl(authBase)).path("demo");
-        Map<String, Integer> stats = adminTarget.path("application-session-stats").request()
+        Map<String, Integer> stats = adminTarget.path("client-session-stats").request()
                 .header(HttpHeaders.AUTHORIZATION, "Bearer " + adminToken)
                 .get(new GenericType<Map<String, Integer>>(){});
 
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AbstractClientTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AbstractClientTest.java
index 4d54909..1a8c554 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AbstractClientTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AbstractClientTest.java
@@ -8,9 +8,8 @@ import org.keycloak.admin.client.resource.RealmResource;
 import org.keycloak.models.Constants;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.representations.idm.ApplicationRepresentation;
+import org.keycloak.representations.idm.ClientRepresentation;
 import org.keycloak.representations.idm.IdentityProviderRepresentation;
-import org.keycloak.representations.idm.OAuthClientRepresentation;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.testsuite.rule.KeycloakRule;
@@ -48,7 +47,7 @@ public abstract class AbstractClientTest {
             }
         });
 
-        keycloak = Keycloak.getInstance("http://localhost:8081/auth", "master", "admin", "admin", Constants.ADMIN_CONSOLE_APPLICATION);
+        keycloak = Keycloak.getInstance("http://localhost:8081/auth", "master", "admin", "admin", Constants.ADMIN_CONSOLE_CLIENT_ID);
         realm = keycloak.realm(REALM_NAME);
     }
 
@@ -97,10 +96,8 @@ public abstract class AbstractClientTest {
     public static String name(Object o1) {
         if (o1 instanceof RealmRepresentation) {
             return ((RealmRepresentation) o1).getRealm();
-        } else if (o1 instanceof ApplicationRepresentation) {
-            return ((ApplicationRepresentation) o1).getName();
-        } else if (o1 instanceof OAuthClientRepresentation) {
-            return ((OAuthClientRepresentation) o1).getName();
+        } else if (o1 instanceof ClientRepresentation) {
+            return ((ClientRepresentation) o1).getClientId();
         } else if (o1 instanceof IdentityProviderRepresentation) {
             return ((IdentityProviderRepresentation) o1).getAlias();
         }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java
index d72664a..b3a7ca6 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java
@@ -25,7 +25,7 @@ import org.junit.Assert;
 import org.junit.ClassRule;
 import org.junit.Test;
 import org.keycloak.Config;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.Constants;
 import org.keycloak.models.KeycloakSession;
@@ -35,7 +35,7 @@ import org.keycloak.models.UserSessionModel;
 import org.keycloak.protocol.oidc.OIDCLoginProtocol;
 import org.keycloak.protocol.oidc.TokenManager;
 import org.keycloak.representations.AccessToken;
-import org.keycloak.representations.idm.ApplicationRepresentation;
+import org.keycloak.representations.idm.ClientRepresentation;
 import org.keycloak.representations.idm.CredentialRepresentation;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.services.managers.RealmManager;
@@ -77,7 +77,7 @@ public class AdminAPITest {
             RealmManager manager = new RealmManager(session);
 
             RealmModel adminRealm = manager.getRealm(Config.getAdminRealm());
-            ApplicationModel adminConsole = adminRealm.getApplicationByName(Constants.ADMIN_CONSOLE_APPLICATION);
+            ClientModel adminConsole = adminRealm.getClientByClientId(Constants.ADMIN_CONSOLE_CLIENT_ID);
             TokenManager tm = new TokenManager();
             UserModel admin = session.users().getUserByUsername("admin", adminRealm);
             ClientSessionModel clientSession = session.sessions().createClientSession(adminRealm, adminConsole);
@@ -125,19 +125,19 @@ public class AdminAPITest {
         storedRealm = realmTarget.request().get(RealmRepresentation.class);
         checkRealmRep(rep, storedRealm);
 
-        if (rep.getApplications() != null) {
+        if (rep.getClients() != null) {
             WebTarget applicationsTarget = realmTarget.path("applications");
-            for (ApplicationRepresentation appRep : rep.getApplications()) {
-                ApplicationRepresentation newApp = new ApplicationRepresentation();
+            for (ClientRepresentation appRep : rep.getClients()) {
+                ClientRepresentation newApp = new ClientRepresentation();
                 if (appRep.getId() != null) newApp.setId(appRep.getId());
-                newApp.setName(appRep.getName());
+                newApp.setClientId(appRep.getClientId());
                 if (appRep.getSecret() != null) {
                     newApp.setSecret(appRep.getSecret());
                 }
                 Response appCreateResponse = applicationsTarget.request().post(Entity.json(newApp));
                 Assert.assertEquals(201, appCreateResponse.getStatus());
                 appCreateResponse.close();
-                WebTarget appTarget = applicationsTarget.path(appRep.getName());
+                WebTarget appTarget = applicationsTarget.path(appRep.getClientId());
                 CredentialRepresentation cred = appTarget.path("client-secret").request().get(CredentialRepresentation.class);
                 if (appRep.getSecret() != null) Assert.assertEquals(appRep.getSecret(), cred.getValue());
                 CredentialRepresentation newCred = appTarget.path("client-secret").request().post(null, CredentialRepresentation.class);
@@ -148,7 +148,7 @@ public class AdminAPITest {
                 appUpdateResponse.close();
 
 
-                ApplicationRepresentation storedApp = appTarget.request().get(ApplicationRepresentation.class);
+                ClientRepresentation storedApp = appTarget.request().get(ClientRepresentation.class);
 
                 checkAppUpdate(appRep, storedApp);
 
@@ -165,8 +165,8 @@ public class AdminAPITest {
         client.close();
     }
 
-    protected void checkAppUpdate(ApplicationRepresentation appRep, ApplicationRepresentation storedApp) {
-        if (appRep.getName() != null) Assert.assertEquals(appRep.getName(), storedApp.getName());
+    protected void checkAppUpdate(ClientRepresentation appRep, ClientRepresentation storedApp) {
+        if (appRep.getClientId() != null) Assert.assertEquals(appRep.getClientId(), storedApp.getClientId());
         if (appRep.isEnabled() != null) Assert.assertEquals(appRep.isEnabled(), storedApp.isEnabled());
         if (appRep.isBearerOnly() != null) Assert.assertEquals(appRep.isBearerOnly(), storedApp.isBearerOnly());
         if (appRep.isPublicClient() != null) Assert.assertEquals(appRep.isPublicClient(), storedApp.isPublicClient());
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java
index 5e757cc..9026ebc 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java
@@ -17,6 +17,11 @@
  */
 package org.keycloak.testsuite.broker;
 
+import org.apache.commons.io.IOUtils;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.DefaultHttpClient;
 import org.codehaus.jackson.map.ObjectMapper;
 import org.junit.After;
 import org.junit.Before;
@@ -24,7 +29,6 @@ import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
 import org.keycloak.OAuth2Constants;
-import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.ClientIdentityProviderMappingModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.FederatedIdentityModel;
@@ -45,7 +49,6 @@ import org.keycloak.testsuite.pages.LoginUpdateProfilePage;
 import org.keycloak.testsuite.pages.OAuthGrantPage;
 import org.keycloak.testsuite.rule.WebResource;
 import org.keycloak.testsuite.rule.WebRule;
-import org.keycloak.testsuite.rule.WebRule.HtmlUnitDriver;
 import org.openqa.selenium.By;
 import org.openqa.selenium.NoSuchElementException;
 import org.openqa.selenium.WebDriver;
@@ -60,18 +63,17 @@ import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 import javax.ws.rs.core.UriBuilder;
-
 import java.io.IOException;
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
 
-import static com.thoughtworks.selenium.SeleneseTestBase.fail;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 /**
  * @author pedroigor
@@ -278,10 +280,10 @@ public abstract class AbstractIdentityProviderTest {
     public void testProviderOnLoginPage() {
         IdentityProviderModel identityProviderModel = getIdentityProviderModel();
         RealmModel realm = getRealm();
-        ApplicationModel applicationModel = realm.getApplicationByName("test-app");
+        ClientModel clientModel = realm.getClientByClientId("test-app");
 
         // This client doesn't have any specific identity providers settings
-        ClientModel client2 = realm.findClient("test-app");
+        ClientModel client2 = realm.getClientByClientId("test-app");
         assertEquals(0, client2.getIdentityProviders().size());
 
         // Provider button is available on login page
@@ -295,7 +297,7 @@ public abstract class AbstractIdentityProviderTest {
         mapping.setIdentityProvider(getProviderId());
         mapping.setRetrieveToken(true);
         appIdentityProviders.add(mapping);
-        applicationModel.updateIdentityProviders(appIdentityProviders);
+        clientModel.updateIdentityProviders(appIdentityProviders);
 
         // Provider button still available on login page
         this.driver.navigate().to("http://localhost:8081/test-app/");
@@ -437,7 +439,7 @@ public abstract class AbstractIdentityProviderTest {
 
         assertNotNull(identityModel.getToken());
 
-        configureRetrieveToken(realm.findClient("test-app"), getProviderId(), false);
+        configureRetrieveToken(realm.getClientByClientId("test-app"), getProviderId(), false);
 
         UserSessionStatus userSessionStatus = retrieveSessionStatus();
         String accessToken = userSessionStatus.getAccessTokenString();
@@ -455,7 +457,7 @@ public abstract class AbstractIdentityProviderTest {
 
         assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
 
-        configureRetrieveToken(getRealm().findClient("test-app"), getProviderId(), true);
+        configureRetrieveToken(getRealm().getClientByClientId("test-app"), getProviderId(), true);
 
         client = ClientBuilder.newBuilder().register(authFilter).build();
         tokenEndpoint = client.target(tokenEndpointUrl);
@@ -505,26 +507,30 @@ public abstract class AbstractIdentityProviderTest {
 
         assertTrue(oauth.getCurrentQuery().containsKey(OAuth2Constants.CODE));
 
-        ClientModel clientModel = getRealm().findClient("third-party");
+        ClientModel clientModel = getRealm().getClientByClientId("third-party");
         assertEquals(0, clientModel.getIdentityProviders().size());
 
         configureRetrieveToken(clientModel, getProviderId(), true);
 
         AccessTokenResponse accessToken = oauth.doAccessTokenRequest(oauth.getCurrentQuery().get(OAuth2Constants.CODE), "password");
-        URI tokenEndpointUrl = Urls.identityProviderRetrieveToken(BASE_URI, getProviderId(), getRealm().getName());
-        String authHeader = "Bearer " + accessToken.getAccessToken();
-        HtmlUnitDriver htmlUnitDriver = (WebRule.HtmlUnitDriver) this.driver;
 
-        htmlUnitDriver.getWebClient().addRequestHeader(HttpHeaders.AUTHORIZATION, authHeader);
+        doTokenRequest(accessToken.getAccessToken());
+    }
 
-        htmlUnitDriver.navigate().to(tokenEndpointUrl.toString());
+    public void doTokenRequest(String token) {
+        try {
+            HttpClient client = new DefaultHttpClient();
+            HttpGet get = new HttpGet(Urls.identityProviderRetrieveToken(BASE_URI, getProviderId(), getRealm().getName()));
 
-        grantPage.assertCurrent();
-        grantPage.accept();
+            get.setHeader("Authorization", "Bearer " + token);
 
-        assertNotNull(driver.getPageSource());
+            HttpResponse response = client.execute(get);
+            assertEquals(200, response.getStatusLine().getStatusCode());
 
-        doAssertTokenRetrieval(driver.getPageSource());
+            assertNotNull(IOUtils.toString(response.getEntity().getContent()));
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
     }
 
     private void configureRetrieveToken(ClientModel clientModel, String providerId, boolean retrieveToken) {
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/ImportIdentityProviderTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/ImportIdentityProviderTest.java
index eda8b69..a1f8245 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/ImportIdentityProviderTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/ImportIdentityProviderTest.java
@@ -30,8 +30,8 @@ import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
 import org.keycloak.broker.saml.SAMLIdentityProvider;
 import org.keycloak.broker.saml.SAMLIdentityProviderConfig;
 import org.keycloak.broker.saml.SAMLIdentityProviderFactory;
-import org.keycloak.models.ClientIdentityProviderMappingModel;
 import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientIdentityProviderMappingModel;
 import org.keycloak.models.IdentityProviderModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.representations.idm.RealmRepresentation;
@@ -122,7 +122,7 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
     public void testApplicationIdentityProviders() throws Exception {
         RealmModel realm = installTestRealm();
 
-        ClientModel client = realm.findClient("test-app-with-allowed-providers");
+        ClientModel client = realm.getClientByClientId("test-app-with-allowed-providers");
         List<ClientIdentityProviderMappingModel> identityProviders = client.getIdentityProviders();
 
         assertEquals(1, identityProviders.size());
@@ -136,7 +136,7 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
 
         client.updateIdentityProviders(identityProviders);
 
-        client = realm.findClientById(client.getId());
+        client = realm.getClientById(client.getId());
         identityProviders = client.getIdentityProviders();
 
         assertEquals(0, identityProviders.size());
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java
index b661d5a..7178f1d 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java
@@ -27,7 +27,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.keycloak.OAuth2Constants;
 import org.keycloak.enums.SslRequired;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
@@ -35,7 +35,7 @@ import org.keycloak.models.UserCredentialModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.representations.AccessToken;
-import org.keycloak.services.managers.ApplicationManager;
+import org.keycloak.services.managers.ClientManager;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.testsuite.ApplicationServlet;
 import org.keycloak.testsuite.OAuthClient;
@@ -85,7 +85,7 @@ public class CompositeRoleTest {
             realmRole1User.updateCredential(UserCredentialModel.password("password"));
             realmRole1User.grantRole(realmRole1);
 
-            final ApplicationModel realmComposite1Application = new ApplicationManager(manager).createApplication(realm, "REALM_COMPOSITE_1_APPLICATION");
+            final ClientModel realmComposite1Application = new ClientManager(manager).createClient(realm, "REALM_COMPOSITE_1_APPLICATION");
             realmComposite1Application.setFullScopeAllowed(false);
             realmComposite1Application.setEnabled(true);
             realmComposite1Application.addScopeMapping(realmComposite1);
@@ -94,7 +94,7 @@ public class CompositeRoleTest {
             realmComposite1Application.setManagementUrl("http://localhost:8081/app/logout");
             realmComposite1Application.setSecret("password");
 
-            final ApplicationModel realmRole1Application = new ApplicationManager(manager).createApplication(realm, "REALM_ROLE_1_APPLICATION");
+            final ClientModel realmRole1Application = new ClientManager(manager).createClient(realm, "REALM_ROLE_1_APPLICATION");
             realmRole1Application.setFullScopeAllowed(false);
             realmRole1Application.setEnabled(true);
             realmRole1Application.addScopeMapping(realmRole1);
@@ -104,7 +104,7 @@ public class CompositeRoleTest {
             realmRole1Application.setSecret("password");
 
 
-            final ApplicationModel appRoleApplication = new ApplicationManager(manager).createApplication(realm, "APP_ROLE_APPLICATION");
+            final ClientModel appRoleApplication = new ClientManager(manager).createClient(realm, "APP_ROLE_APPLICATION");
             appRoleApplication.setFullScopeAllowed(false);
             appRoleApplication.setEnabled(true);
             appRoleApplication.addRedirectUri("http://localhost:8081/app/*");
@@ -127,7 +127,7 @@ public class CompositeRoleTest {
             realmAppRoleUser.updateCredential(UserCredentialModel.password("password"));
             realmAppRoleUser.grantRole(appRole2);
 
-            final ApplicationModel appCompositeApplication = new ApplicationManager(manager).createApplication(realm, "APP_COMPOSITE_APPLICATION");
+            final ClientModel appCompositeApplication = new ClientManager(manager).createClient(realm, "APP_COMPOSITE_APPLICATION");
             appCompositeApplication.setFullScopeAllowed(false);
             appCompositeApplication.setEnabled(true);
             appCompositeApplication.addRedirectUri("http://localhost:8081/app/*");
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/AbstractKerberosTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/AbstractKerberosTest.java
index af994f4..2580242 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/AbstractKerberosTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/AbstractKerberosTest.java
@@ -21,7 +21,7 @@ import org.keycloak.adapters.HttpClientBuilder;
 import org.keycloak.events.Details;
 import org.keycloak.federation.kerberos.CommonKerberosConfig;
 import org.keycloak.constants.KerberosConstants;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.LDAPConstants;
 import org.keycloak.models.ProtocolMapperModel;
@@ -183,7 +183,7 @@ public abstract class AbstractKerberosTest {
                         true, KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME,
                         true, false);
 
-                ApplicationModel kerberosApp = appRealm.getApplicationByName("kerberos-app");
+                ClientModel kerberosApp = appRealm.getClientByClientId("kerberos-app");
                 kerberosApp.addProtocolMapper(protocolMapper);
             }
 
@@ -202,7 +202,7 @@ public abstract class AbstractKerberosTest {
 
             @Override
             public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                ApplicationModel kerberosApp = appRealm.getApplicationByName("kerberos-app");
+                ClientModel kerberosApp = appRealm.getClientByClientId("kerberos-app");
                 ProtocolMapperModel toRemove = kerberosApp.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME);
                 kerberosApp.removeProtocolMapper(toRemove);
             }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/FederationProvidersIntegrationTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/FederationProvidersIntegrationTest.java
index cfaae07..929029e 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/FederationProvidersIntegrationTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/FederationProvidersIntegrationTest.java
@@ -12,6 +12,8 @@ import org.keycloak.OAuth2Constants;
 import org.keycloak.federation.ldap.LDAPFederationProvider;
 import org.keycloak.federation.ldap.LDAPFederationProviderFactory;
 import org.keycloak.federation.ldap.LDAPUtils;
+import org.keycloak.federation.ldap.idm.model.LDAPUser;
+import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.LDAPConstants;
 import org.keycloak.models.ModelReadOnlyException;
@@ -21,7 +23,6 @@ import org.keycloak.models.UserCredentialValueModel;
 import org.keycloak.models.UserFederationProvider;
 import org.keycloak.models.UserFederationProviderModel;
 import org.keycloak.models.UserModel;
-import org.keycloak.picketlink.PartitionManagerProvider;
 import org.keycloak.representations.idm.CredentialRepresentation;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.testsuite.OAuthClient;
@@ -35,8 +36,6 @@ import org.keycloak.testsuite.rule.LDAPRule;
 import org.keycloak.testsuite.rule.WebResource;
 import org.keycloak.testsuite.rule.WebRule;
 import org.openqa.selenium.WebDriver;
-import org.picketlink.idm.PartitionManager;
-import org.picketlink.idm.model.basic.User;
 
 import java.util.Map;
 
@@ -57,19 +56,19 @@ public class FederationProvidersIntegrationTest {
             addUser(manager.getSession(), appRealm, "mary", "mary@test.com", "password-app");
 
             Map<String,String> ldapConfig = ldapRule.getConfig();
-            ldapConfig.put(LDAPFederationProvider.SYNC_REGISTRATIONS, "true");
+            ldapConfig.put(LDAPConstants.SYNC_REGISTRATIONS, "true");
             ldapConfig.put(LDAPConstants.EDIT_MODE, UserFederationProvider.EditMode.WRITABLE.toString());
 
             ldapModel = appRealm.addUserFederationProvider(LDAPFederationProviderFactory.PROVIDER_NAME, ldapConfig, 0, "test-ldap", -1, -1, 0);
 
             // Delete all LDAP users and add some new for testing
-            PartitionManager partitionManager = getPartitionManager(manager.getSession(), ldapModel);
-            LDAPUtils.removeAllUsers(partitionManager);
+            LDAPIdentityStore ldapStore = getLdapIdentityStore(manager.getSession(), ldapModel);
+            LDAPUtils.removeAllUsers(ldapStore);
 
-            User john = LDAPUtils.addUser(partitionManager, "johnkeycloak", "John", "Doe", "john@email.org");
-            LDAPUtils.updatePassword(partitionManager, john, "Password1");
+            LDAPUser john = LDAPUtils.addUser(ldapStore, "johnkeycloak", "John", "Doe", "john@email.org");
+            LDAPUtils.updatePassword(ldapStore, john, "Password1");
 
-            User existing = LDAPUtils.addUser(partitionManager, "existing", "Existing", "Foo", "existing@email.org");
+            LDAPUser existing = LDAPUtils.addUser(ldapStore, "existing", "Existing", "Foo", "existing@email.org");
         }
     });
 
@@ -339,13 +338,13 @@ public class FederationProvidersIntegrationTest {
     @Test
     public void testSearch() {
         KeycloakSession session = keycloakRule.startSession();
-        PartitionManager partitionManager = getPartitionManager(session, ldapModel);
+        LDAPIdentityStore ldapStore = getLdapIdentityStore(session, ldapModel);
         try {
             RealmModel appRealm = session.realms().getRealmByName("test");
-            LDAPUtils.addUser(partitionManager, "username1", "John1", "Doel1", "user1@email.org");
-            LDAPUtils.addUser(partitionManager, "username2", "John2", "Doel2", "user2@email.org");
-            LDAPUtils.addUser(partitionManager, "username3", "John3", "Doel3", "user3@email.org");
-            LDAPUtils.addUser(partitionManager, "username4", "John4", "Doel4", "user4@email.org");
+            LDAPUtils.addUser(ldapStore, "username1", "John1", "Doel1", "user1@email.org");
+            LDAPUtils.addUser(ldapStore, "username2", "John2", "Doel2", "user2@email.org");
+            LDAPUtils.addUser(ldapStore, "username3", "John3", "Doel3", "user3@email.org");
+            LDAPUtils.addUser(ldapStore, "username4", "John4", "Doel4", "user4@email.org");
 
             // Users are not at local store at this moment
             Assert.assertNull(session.userStorage().getUserByUsername("username1", appRealm));
@@ -395,7 +394,7 @@ public class FederationProvidersIntegrationTest {
             Assert.assertTrue(session.users().validCredentials(appRealm, user, cred));
 
             // LDAP password is still unchanged
-            Assert.assertTrue(LDAPUtils.validatePassword(getPartitionManager(session, model), "johnkeycloak", "Password1"));
+            Assert.assertTrue(LDAPUtils.validatePassword(getLdapIdentityStore(session, model), user, "Password1"));
 
             // ATM it's not permitted to delete user in unsynced mode. Should be user deleted just locally instead?
             Assert.assertFalse(session.users().removeUser(appRealm, user));
@@ -412,9 +411,10 @@ public class FederationProvidersIntegrationTest {
         }
     }
 
-    static PartitionManager getPartitionManager(KeycloakSession keycloakSession, UserFederationProviderModel ldapFedModel) {
-        PartitionManagerProvider partitionManagerProvider = keycloakSession.getProvider(PartitionManagerProvider.class);
-        return partitionManagerProvider.getPartitionManager(ldapFedModel);
+    static LDAPIdentityStore getLdapIdentityStore(KeycloakSession keycloakSession, UserFederationProviderModel ldapFedModel) {
+        LDAPFederationProviderFactory ldapProviderFactory = (LDAPFederationProviderFactory) keycloakSession.getKeycloakSessionFactory().getProviderFactory(UserFederationProvider.class, ldapFedModel.getProviderName());
+        LDAPFederationProvider ldapProvider = ldapProviderFactory.getInstance(keycloakSession, ldapFedModel);
+        return ldapProvider.getLdapIdentityStore();
     }
 
 }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/SyncProvidersTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/SyncProvidersTest.java
index 55f68bb..f628519 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/SyncProvidersTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/SyncProvidersTest.java
@@ -7,9 +7,10 @@ import org.junit.Test;
 import org.junit.rules.RuleChain;
 import org.junit.rules.TestRule;
 import org.junit.runners.MethodSorters;
-import org.keycloak.federation.ldap.LDAPFederationProvider;
 import org.keycloak.federation.ldap.LDAPFederationProviderFactory;
 import org.keycloak.federation.ldap.LDAPUtils;
+import org.keycloak.federation.ldap.idm.model.LDAPUser;
+import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
 import org.keycloak.models.LDAPConstants;
@@ -25,8 +26,6 @@ import org.keycloak.testsuite.rule.LDAPRule;
 import org.keycloak.testutils.DummyUserFederationProviderFactory;
 import org.keycloak.timer.TimerProvider;
 import org.keycloak.util.Time;
-import org.picketlink.idm.PartitionManager;
-import org.picketlink.idm.model.basic.User;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -50,26 +49,20 @@ public class SyncProvidersTest {
             Time.setOffset(0);
 
             Map<String,String> ldapConfig = ldapRule.getConfig();
-            ldapConfig.put(LDAPFederationProvider.SYNC_REGISTRATIONS, "false");
+            ldapConfig.put(LDAPConstants.SYNC_REGISTRATIONS, "false");
             ldapConfig.put(LDAPConstants.EDIT_MODE, UserFederationProvider.EditMode.UNSYNCED.toString());
 
             ldapModel = appRealm.addUserFederationProvider(LDAPFederationProviderFactory.PROVIDER_NAME, ldapConfig, 0, "test-ldap",
                     -1, -1, 0);
 
             // Delete all LDAP users and add 5 new users for testing
-            PartitionManager partitionManager = FederationProvidersIntegrationTest.getPartitionManager(manager.getSession(), ldapModel);
-            LDAPUtils.removeAllUsers(partitionManager);
-
-            User user1 = LDAPUtils.addUser(partitionManager, "user1", "User1FN", "User1LN", "user1@email.org");
-            LDAPUtils.updatePassword(partitionManager, user1, "Password1");
-            User user2 = LDAPUtils.addUser(partitionManager, "user2", "User2FN", "User2LN", "user2@email.org");
-            LDAPUtils.updatePassword(partitionManager, user2, "Password2");
-            User user3 = LDAPUtils.addUser(partitionManager, "user3", "User3FN", "User3LN", "user3@email.org");
-            LDAPUtils.updatePassword(partitionManager, user3, "Password3");
-            User user4 = LDAPUtils.addUser(partitionManager, "user4", "User4FN", "User4LN", "user4@email.org");
-            LDAPUtils.updatePassword(partitionManager, user4, "Password4");
-            User user5 = LDAPUtils.addUser(partitionManager, "user5", "User5FN", "User5LN", "user5@email.org");
-            LDAPUtils.updatePassword(partitionManager, user5, "Password5");
+            LDAPIdentityStore ldapStore = FederationProvidersIntegrationTest.getLdapIdentityStore(manager.getSession(), ldapModel);
+            LDAPUtils.removeAllUsers(ldapStore);
+
+            for (int i=1 ; i<6 ; i++) {
+                LDAPUser user = LDAPUtils.addUser(ldapStore, "user" + i, "User" + i + "FN", "User" + i + "LN", "user" + i + "@email.org");
+                LDAPUtils.updatePassword(ldapStore, user, "Password1");
+            }
 
             // Add dummy provider
             dummyModel = appRealm.addUserFederationProvider(DummyUserFederationProviderFactory.PROVIDER_NAME, new HashMap<String, String>(), 1, "test-dummy", -1, 1, 0);
@@ -122,9 +115,9 @@ public class SyncProvidersTest {
             sleep(1000);
 
             // Add user to LDAP and update 'user5' in LDAP
-            PartitionManager partitionManager = FederationProvidersIntegrationTest.getPartitionManager(session, ldapModel);
-            LDAPUtils.addUser(partitionManager, "user6", "User6FN", "User6LN", "user6@email.org");
-            LDAPUtils.updateUser(partitionManager, "user5", "User5FNUpdated", "User5LNUpdated", "user5Updated@email.org");
+            LDAPIdentityStore ldapStore = FederationProvidersIntegrationTest.getLdapIdentityStore(session, ldapModel);
+            LDAPUtils.addUser(ldapStore, "user6", "User6FN", "User6LN", "user6@email.org");
+            LDAPUtils.updateUser(ldapStore, "user5", "User5FNUpdated", "User5LNUpdated", "user5Updated@email.org");
 
             // Assert still old users in local provider
             assertUserImported(userProvider, testRealm, "user5", "User5FN", "User5LN", "user5@email.org");
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/jaxrs/JaxrsBasicAuthTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/jaxrs/JaxrsBasicAuthTest.java
index 252a253..1b5a249 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/jaxrs/JaxrsBasicAuthTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/jaxrs/JaxrsBasicAuthTest.java
@@ -19,10 +19,8 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExternalResource;
 import org.keycloak.adapters.HttpClientBuilder;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserModel;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.testsuite.Constants;
 import org.keycloak.testsuite.rule.KeycloakRule;
@@ -44,7 +42,7 @@ public class JaxrsBasicAuthTest {
 
         @Override
         public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-            ApplicationModel app = appRealm.addApplication("jaxrs-app");
+            ClientModel app = appRealm.addClient("jaxrs-app");
             app.setEnabled(true);
             app.setSecret("password");
             app.setFullScopeAllowed(true);
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/jaxrs/JaxrsFilterTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/jaxrs/JaxrsFilterTest.java
index 2ff046c..5d59735 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/jaxrs/JaxrsFilterTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/jaxrs/JaxrsFilterTest.java
@@ -23,7 +23,7 @@ import org.keycloak.TokenIdGenerator;
 import org.keycloak.adapters.CorsHeaders;
 import org.keycloak.constants.AdapterConstants;
 import org.keycloak.adapters.HttpClientBuilder;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserModel;
@@ -53,7 +53,7 @@ public class JaxrsFilterTest {
 
         @Override
         public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-            ApplicationModel app = appRealm.addApplication("jaxrs-app");
+            ClientModel app = appRealm.addClient("jaxrs-app");
             app.setEnabled(true);
             RoleModel role = app.addRole("jaxrs-app-user");
             UserModel user = manager.getSession().users().getUserByUsername("test-user@localhost", appRealm);
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AdapterTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AdapterTest.java
index a2ebb91..0e48914 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AdapterTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AdapterTest.java
@@ -4,10 +4,9 @@ import org.junit.Assert;
 import org.junit.FixMethodOrder;
 import org.junit.Test;
 import org.junit.runners.MethodSorters;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.FederatedIdentityModel;
 import org.keycloak.models.ModelDuplicateException;
-import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.PasswordPolicy;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RequiredCredentialModel;
@@ -16,7 +15,6 @@ import org.keycloak.models.UserCredentialModel;
 import org.keycloak.models.UserCredentialValueModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.UserProvider;
-import org.keycloak.models.utils.RepresentationToModel;
 import org.keycloak.representations.idm.CredentialRepresentation;
 import org.keycloak.services.managers.RealmManager;
 
@@ -153,15 +151,6 @@ public class AdapterTest extends AbstractModelTest {
     }
 
     @Test
-    public void testOAuthClient() throws Exception {
-        test1CreateRealm();
-
-        RepresentationToModel.createOAuthClient(null, "oauth-client", realmModel);
-        OAuthClientModel oauth = realmModel.getOAuthClient("oauth-client");
-        Assert.assertNotNull(oauth);
-    }
-
-    @Test
     public void testDeleteUser() throws Exception {
         test1CreateRealm();
 
@@ -172,7 +161,7 @@ public class AdapterTest extends AbstractModelTest {
         RoleModel testRole = realmModel.addRole("test");
         user.grantRole(testRole);
 
-        ApplicationModel app = realmModel.addApplication("test-app");
+        ClientModel app = realmModel.addClient("test-app");
         RoleModel appRole = app.addRole("test");
         user.grantRole(appRole);
 
@@ -197,9 +186,9 @@ public class AdapterTest extends AbstractModelTest {
 
         UserModel user = realmManager.getSession().users().addUser(realmModel, "bburke");
 
-        OAuthClientModel client = realmModel.addOAuthClient("client");
+        ClientModel client = realmModel.addClient("client");
 
-        ApplicationModel app = realmModel.addApplication("test-app");
+        ClientModel app = realmModel.addClient("test-app");
 
         RoleModel appRole = app.addRole("test");
         user.grantRole(appRole);
@@ -208,9 +197,9 @@ public class AdapterTest extends AbstractModelTest {
         RoleModel realmRole = realmModel.addRole("test");
         app.addScopeMapping(realmRole);
 
-        Assert.assertTrue(realmModel.removeApplication(app.getId()));
-        Assert.assertFalse(realmModel.removeApplication(app.getId()));
-        assertNull(realmModel.getApplicationById(app.getId()));
+        Assert.assertTrue(realmModel.removeClient(app.getId()));
+        Assert.assertFalse(realmModel.removeClient(app.getId()));
+        assertNull(realmModel.getClientById(app.getId()));
     }
 
 
@@ -225,9 +214,9 @@ public class AdapterTest extends AbstractModelTest {
         cred.setValue("password");
         user.updateCredential(cred);
 
-        OAuthClientModel client = realmModel.addOAuthClient("client");
+        ClientModel client = realmModel.addClient("client");
 
-        ApplicationModel app = realmModel.addApplication("test-app");
+        ClientModel app = realmModel.addClient("test-app");
 
         RoleModel appRole = app.addRole("test");
         user.grantRole(appRole);
@@ -255,9 +244,9 @@ public class AdapterTest extends AbstractModelTest {
 
         UserModel user = realmManager.getSession().users().addUser(realmModel, "bburke");
 
-        OAuthClientModel client = realmModel.addOAuthClient("client");
+        ClientModel client = realmModel.addClient("client");
 
-        ApplicationModel app = realmModel.addApplication("test-app");
+        ClientModel app = realmModel.addClient("test-app");
 
         RoleModel appRole = app.addRole("test");
         user.grantRole(appRole);
@@ -268,7 +257,7 @@ public class AdapterTest extends AbstractModelTest {
 
         commit();
         realmModel = model.getRealm("JUGGLER");
-        app = realmModel.getApplicationByName("test-app");
+        app = realmModel.getClientByClientId("test-app");
 
         Assert.assertTrue(realmModel.removeRoleById(realmRole.getId()));
         Assert.assertFalse(realmModel.removeRoleById(realmRole.getId()));
@@ -458,7 +447,7 @@ public class AdapterTest extends AbstractModelTest {
         assertRolesEquals(found, realmUserRole);
 
         // Test app roles
-        ApplicationModel application = realmModel.addApplication("app1");
+        ClientModel application = realmModel.addClient("app1");
         application.addRole("user");
         application.addRole("bar");
         Set<RoleModel> appRoles = application.getRoles();
@@ -480,7 +469,7 @@ public class AdapterTest extends AbstractModelTest {
         // Role "foo" is default realm role
         Assert.assertTrue(user.hasRole(realmModel.getRole("foo")));
 
-        roles = user.getApplicationRoleMappings(application);
+        roles = user.getClientRoleMappings(application);
         Assert.assertEquals(roles.size(), 2);
         assertRolesContains(application.getRole("user"), roles);
         assertRolesContains(appBarRole, roles);
@@ -506,23 +495,23 @@ public class AdapterTest extends AbstractModelTest {
         test1CreateRealm();
         RoleModel realmRole = realmModel.addRole("realm");
 
-        ApplicationModel app1 = realmModel.addApplication("app1");
+        ClientModel app1 = realmModel.addClient("app1");
         RoleModel appRole = app1.addRole("app");
 
-        ApplicationModel app2 = realmModel.addApplication("app2");
+        ClientModel app2 = realmModel.addClient("app2");
         app2.addScopeMapping(realmRole);
         app2.addScopeMapping(appRole);
 
-        OAuthClientModel client = realmModel.addOAuthClient("client");
+        ClientModel client = realmModel.addClient("client");
         client.addScopeMapping(realmRole);
         client.addScopeMapping(appRole);
 
         commit();
 
         realmModel = model.getRealmByName("JUGGLER");
-        app1 = realmModel.getApplicationByName("app1");
-        app2 = realmModel.getApplicationByName("app2");
-        client = realmModel.getOAuthClient("client");
+        app1 = realmModel.getClientByClientId("app1");
+        app2 = realmModel.getClientByClientId("app2");
+        client = realmModel.getClientByClientId("client");
 
         Set<RoleModel> scopeMappings = app2.getScopeMappings();
         Assert.assertEquals(2, scopeMappings.size());
@@ -565,14 +554,14 @@ public class AdapterTest extends AbstractModelTest {
 
     @Test
     public void testAppNameCollisions() throws Exception {
-        realmManager.createRealm("JUGGLER1").addApplication("app1");
-        realmManager.createRealm("JUGGLER2").addApplication("app1");
+        realmManager.createRealm("JUGGLER1").addClient("app1");
+        realmManager.createRealm("JUGGLER2").addClient("app1");
 
         commit();
 
         // Try to create app with duplicate name
         try {
-            realmManager.getRealmByName("JUGGLER1").addApplication("app1");
+            realmManager.getRealmByName("JUGGLER1").addClient("app1");
             commit();
             Assert.fail("Expected exception");
         } catch (ModelDuplicateException e) {
@@ -580,10 +569,10 @@ public class AdapterTest extends AbstractModelTest {
         commit(true);
 
         // Ty to rename app to duplicate name
-        realmManager.getRealmByName("JUGGLER1").addApplication("app2");
+        realmManager.getRealmByName("JUGGLER1").addClient("app2");
         commit();
         try {
-            realmManager.getRealmByName("JUGGLER1").getApplicationByName("app2").setName("app1");
+            realmManager.getRealmByName("JUGGLER1").getClientByClientId("app2").setClientId("app1");
             commit();
             Assert.fail("Expected exception");
         } catch (ModelDuplicateException e) {
@@ -594,14 +583,14 @@ public class AdapterTest extends AbstractModelTest {
 
     @Test
     public void testClientNameCollisions() throws Exception {
-        realmManager.createRealm("JUGGLER1").addOAuthClient("client1");
-        realmManager.createRealm("JUGGLER2").addOAuthClient("client1");
+        realmManager.createRealm("JUGGLER1").addClient("client1");
+        realmManager.createRealm("JUGGLER2").addClient("client1");
 
         commit();
 
         // Try to create app with duplicate name
         try {
-            realmManager.getRealmByName("JUGGLER1").addOAuthClient("client1");
+            realmManager.getRealmByName("JUGGLER1").addClient("client1");
             commit();
             Assert.fail("Expected exception");
         } catch (ModelDuplicateException e) {
@@ -609,10 +598,10 @@ public class AdapterTest extends AbstractModelTest {
         commit(true);
 
         // Ty to rename app to duplicate name
-        realmManager.getRealmByName("JUGGLER1").addOAuthClient("client2");
+        realmManager.getRealmByName("JUGGLER1").addClient("client2");
         commit();
         try {
-            realmManager.getRealmByName("JUGGLER1").getOAuthClient("client2").setClientId("client1");
+            realmManager.getRealmByName("JUGGLER1").addClient("client2").setClientId("client1");
             commit();
             Assert.fail("Expected exception");
         } catch (ModelDuplicateException e) {
@@ -691,14 +680,14 @@ public class AdapterTest extends AbstractModelTest {
     @Test
     public void testAppRoleCollisions() throws Exception {
         realmManager.createRealm("JUGGLER1").addRole("role1");
-        realmManager.getRealmByName("JUGGLER1").addApplication("app1").addRole("role1");
-        realmManager.getRealmByName("JUGGLER1").addApplication("app2").addRole("role1");
+        realmManager.getRealmByName("JUGGLER1").addClient("app1").addRole("role1");
+        realmManager.getRealmByName("JUGGLER1").addClient("app2").addRole("role1");
 
         commit();
 
         // Try to add role with same name
         try {
-            realmManager.getRealmByName("JUGGLER1").getApplicationByName("app1").addRole("role1");
+            realmManager.getRealmByName("JUGGLER1").getClientByClientId("app1").addRole("role1");
             commit();
             Assert.fail("Expected exception");
         } catch (ModelDuplicateException e) {
@@ -706,10 +695,10 @@ public class AdapterTest extends AbstractModelTest {
         commit(true);
 
         // Ty to rename role to duplicate name
-        realmManager.getRealmByName("JUGGLER1").getApplicationByName("app1").addRole("role2");
+        realmManager.getRealmByName("JUGGLER1").getClientByClientId("app1").addRole("role2");
         commit();
         try {
-            realmManager.getRealmByName("JUGGLER1").getApplicationByName("app1").getRole("role2").setName("role1");
+            realmManager.getRealmByName("JUGGLER1").getClientByClientId("app1").getRole("role2").setName("role1");
             commit();
             Assert.fail("Expected exception");
         } catch (ModelDuplicateException e) {
@@ -721,8 +710,8 @@ public class AdapterTest extends AbstractModelTest {
     @Test
     public void testRealmRoleCollisions() throws Exception {
         realmManager.createRealm("JUGGLER1").addRole("role1");
-        realmManager.getRealmByName("JUGGLER1").addApplication("app1").addRole("role1");
-        realmManager.getRealmByName("JUGGLER1").addApplication("app2").addRole("role1");
+        realmManager.getRealmByName("JUGGLER1").addClient("app1").addRole("role1");
+        realmManager.getRealmByName("JUGGLER1").addClient("app2").addRole("role1");
 
         commit();
 
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CacheTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CacheTest.java
index f565825..1237cfa 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CacheTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CacheTest.java
@@ -3,7 +3,7 @@ package org.keycloak.testsuite.model;
 import org.junit.Assert;
 import org.junit.ClassRule;
 import org.junit.Test;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.testsuite.rule.KeycloakRule;
@@ -23,7 +23,7 @@ public class CacheTest {
             // load up cache
             KeycloakSession session = kc.startSession();
             RealmModel realm = session.realms().getRealmByName("test");
-            ApplicationModel testApp = realm.getApplicationByName("test-app");
+            ClientModel testApp = realm.getClientByClientId("test-app");
             Assert.assertNotNull(testApp);
             appId = testApp.getId();
             Assert.assertTrue(testApp.isEnabled());
@@ -35,7 +35,7 @@ public class CacheTest {
             RealmModel realm = session.realms().getRealmByName("test");
             Assert.assertTrue(realm instanceof org.keycloak.models.cache.RealmAdapter);
             realm.setAccessCodeLifespanLogin(200);
-            ApplicationModel testApp = realm.getApplicationByName("test-app");
+            ClientModel testApp = realm.getClientByClientId("test-app");
             Assert.assertNotNull(testApp);
             testApp.setEnabled(false);
             kc.stopSession(session, true);
@@ -44,7 +44,7 @@ public class CacheTest {
         {
             KeycloakSession session = kc.startSession();
             RealmModel realm = session.realms().getRealmByName("test");
-            ApplicationModel testApp = session.realms().getApplicationById(appId, realm);
+            ClientModel testApp = session.realms().getClientById(appId, realm);
             Assert.assertFalse(testApp.isEnabled());
             kc.stopSession(session, true);
 
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CompositeRolesModelTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CompositeRolesModelTest.java
index b99c310..a23e048 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CompositeRolesModelTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CompositeRolesModelTest.java
@@ -3,7 +3,7 @@ package org.keycloak.testsuite.model;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserModel;
@@ -58,7 +58,7 @@ public class CompositeRolesModelTest extends AbstractModelTest {
 
         RealmModel realm = realmManager.getRealm("TestComposites");
         UserModel user = realmManager.getSession().users().getUserByUsername(username, realm);
-        ApplicationModel application = realm.getApplicationByName(applicationName);
+        ClientModel application = realm.getClientByClientId(applicationName);
 
         Set<RoleModel> roleMappings = user.getRoleMappings();
         Set<RoleModel> scopeMappings = application.getScopeMappings();
@@ -95,7 +95,7 @@ public class CompositeRolesModelTest extends AbstractModelTest {
         if ("realm".equals(appName)) {
             return realm.getRole(roleName);
         }  else {
-            return realm.getApplicationByName(appName).getRole(roleName);
+            return realm.getClientByClientId(appName).getRole(roleName);
         }
     }
 
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ImportTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ImportTest.java
index e4d20f8..54f4cbe 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ImportTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ImportTest.java
@@ -5,7 +5,6 @@ import org.junit.FixMethodOrder;
 import org.junit.Test;
 import org.junit.runners.MethodSorters;
 import org.keycloak.constants.KerberosConstants;
-import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.Constants;
 import org.keycloak.models.FederatedIdentityModel;
@@ -81,26 +80,23 @@ public class ImportTest extends AbstractModelTest {
         Assert.assertNotNull(user);
         Assert.assertEquals(0,  session.users().getFederatedIdentities(user, realm).size());
 
-        List<ApplicationModel> resources = realm.getApplications();
-        for (ApplicationModel app : resources) {
-            System.out.println("app: " + app.getName());
-        }
-        Assert.assertEquals(5, resources.size());
+        List<ClientModel> resources = realm.getClients();
+        Assert.assertEquals(6, resources.size());
 
         // Test applications imported
-        ApplicationModel application = realm.getApplicationByName("Application");
-        ApplicationModel otherApp = realm.getApplicationByName("OtherApp");
-        ApplicationModel accountApp = realm.getApplicationByName(Constants.ACCOUNT_MANAGEMENT_APP);
-        ApplicationModel nonExisting = realm.getApplicationByName("NonExisting");
+        ClientModel application = realm.getClientByClientId("Application");
+        ClientModel otherApp = realm.getClientByClientId("OtherApp");
+        ClientModel accountApp = realm.getClientByClientId(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
+        ClientModel nonExisting = realm.getClientByClientId("NonExisting");
         Assert.assertNotNull(application);
         Assert.assertNotNull(otherApp);
         Assert.assertNull(nonExisting);
-        Map<String, ApplicationModel> apps = realm.getApplicationNameMap();
-        Assert.assertEquals(5, apps.size());
-        Assert.assertTrue(apps.values().contains(application));
-        Assert.assertTrue(apps.values().contains(otherApp));
-        Assert.assertTrue(apps.values().contains(accountApp));
-        realm.getApplications().containsAll(apps.values());
+        Map<String, ClientModel> clients = realm.getClientNameMap();
+        Assert.assertEquals(6, clients.size());
+        Assert.assertTrue(clients.values().contains(application));
+        Assert.assertTrue(clients.values().contains(otherApp));
+        Assert.assertTrue(clients.values().contains(accountApp));
+        realm.getClients().containsAll(clients.values());
 
         Assert.assertEquals(50, application.getNodeReRegistrationTimeout());
         Map<String, Integer> appRegisteredNodes = application.getRegisteredNodes();
@@ -109,8 +105,8 @@ public class ImportTest extends AbstractModelTest {
         Assert.assertTrue(20 == appRegisteredNodes.get("172.10.15.20"));
 
         // Test finding applications by ID
-        Assert.assertNull(realm.getApplicationById("982734"));
-        Assert.assertEquals(application, realm.getApplicationById(application.getId()));
+        Assert.assertNull(realm.getClientById("982734"));
+        Assert.assertEquals(application, realm.getClientById(application.getId()));
 
 
         // Test role mappings
@@ -134,12 +130,12 @@ public class ImportTest extends AbstractModelTest {
         Assert.assertEquals(1, realmRoles.size());
         Assert.assertEquals("admin", realmRoles.iterator().next().getName());
 
-        Set<RoleModel> appRoles = admin.getApplicationRoleMappings(application);
+        Set<RoleModel> appRoles = admin.getClientRoleMappings(application);
         Assert.assertEquals(1, appRoles.size());
         Assert.assertEquals("app-admin", appRoles.iterator().next().getName());
 
         // Test client
-        ClientModel oauthClient = realm.findClient("oauthclient");
+        ClientModel oauthClient = realm.getClientByClientId("oauthclient");
         Assert.assertEquals("clientpassword", oauthClient.getSecret());
         Assert.assertEquals(true, oauthClient.isEnabled());
         Assert.assertNotNull(oauthClient);
@@ -153,7 +149,7 @@ public class ImportTest extends AbstractModelTest {
         Set<RoleModel> realmScopes = oauthClient.getRealmScopeMappings();
         Assert.assertTrue(realmScopes.contains(realm.getRole("admin")));
 
-        Set<RoleModel> appScopes = application.getApplicationScopeMappings(oauthClient);
+        Set<RoleModel> appScopes = application.getClientScopeMappings(oauthClient);
         Assert.assertTrue(appScopes.contains(application.getRole("app-user")));
 
 
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/MultipleRealmsTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/MultipleRealmsTest.java
index 023a6fb..1a4c660 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/MultipleRealmsTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/MultipleRealmsTest.java
@@ -3,8 +3,7 @@ package org.keycloak.testsuite.model;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
-import org.keycloak.models.ApplicationModel;
-import org.keycloak.models.OAuthClientModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserCredentialModel;
@@ -66,17 +65,17 @@ public class MultipleRealmsTest extends AbstractModelTest {
         Assert.assertEquals(realm2, model.getRealm("id2"));
         Assert.assertEquals(realm2, model.getRealmByName("realm2"));
 
-        ApplicationModel r1app1 = realm1.getApplicationByName("app1");
-        ApplicationModel r1app2 = realm1.getApplicationByName("app2");
-        ApplicationModel r2app1 = realm2.getApplicationByName("app1");
-        ApplicationModel r2app2 = realm2.getApplicationByName("app2");
+        ClientModel r1app1 = realm1.getClientByClientId("app1");
+        ClientModel r1app2 = realm1.getClientByClientId("app2");
+        ClientModel r2app1 = realm2.getClientByClientId("app1");
+        ClientModel r2app2 = realm2.getClientByClientId("app2");
 
-        Assert.assertEquals(r1app1, realm1.getApplicationById(r1app1.getId()));
-        Assert.assertNull(realm2.getApplicationById(r1app1.getId()));
+        Assert.assertEquals(r1app1, realm1.getClientById(r1app1.getId()));
+        Assert.assertNull(realm2.getClientById(r1app1.getId()));
 
-        OAuthClientModel r2cl1 = realm2.getOAuthClient("cl1");
-        Assert.assertEquals(r2cl1.getId(), realm2.getOAuthClientById(r2cl1.getId()).getId());
-        Assert.assertNull(realm1.getOAuthClientById(r2cl1.getId()));
+        ClientModel r2cl1 = realm2.getClientByClientId("cl1");
+        Assert.assertEquals(r2cl1.getId(), realm2.getClientById(r2cl1.getId()).getId());
+        Assert.assertNull(realm1.getClientByClientId(r2cl1.getId()));
 
         RoleModel r1App1Role = r1app1.getRole("app1Role1");
         Assert.assertEquals(r1App1Role, realm1.getRoleById(r1App1Role.getId()));
@@ -88,8 +87,8 @@ public class MultipleRealmsTest extends AbstractModelTest {
     }
 
     private void createObjects(RealmModel realm) {
-        ApplicationModel app1 = realm.addApplication("app1");
-        realm.addApplication("app2");
+        ClientModel app1 = realm.addClient("app1");
+        realm.addClient("app2");
 
         realmManager.getSession().users().addUser(realm, "user1");
         realmManager.getSession().users().addUser(realm, "user2");
@@ -100,7 +99,7 @@ public class MultipleRealmsTest extends AbstractModelTest {
         app1.addRole("app1Role1");
         app1.addScopeMapping(realm.getRole("role1"));
 
-        realm.addOAuthClient("cl1");
+        realm.addClient("cl1");
     }
 
 }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserModelTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserModelTest.java
index d01dc7f..b70e3ff 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserModelTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserModelTest.java
@@ -62,7 +62,7 @@ public class UserModelTest extends AbstractModelTest {
     @Test
     public void webOriginSetTest() {
         RealmModel realm = realmManager.createRealm("original");
-        ClientModel client = realm.addApplication("user");
+        ClientModel client = realm.addClient("user");
 
         Assert.assertTrue(client.getWebOrigins().isEmpty());
 
@@ -78,7 +78,7 @@ public class UserModelTest extends AbstractModelTest {
         client.removeWebOrigin("origin-1");
         Assert.assertTrue(client.getWebOrigins().isEmpty());
 
-        client = realm.addOAuthClient("oauthclient2");
+        client = realm.addClient("oauthclient2");
 
         Assert.assertTrue(client.getWebOrigins().isEmpty());
 
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java
index 35cf6fc..b706203 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java
@@ -83,7 +83,7 @@ public class UserSessionProviderTest {
         List<ClientSessionModel> clientSessions = session.sessions().getUserSession(realm, sessions[0].getId()).getClientSessions();
         assertEquals(2, clientSessions.size());
 
-        String client1 = realm.findClient("test-app").getId();
+        String client1 = realm.getClientByClientId("test-app").getId();
 
         ClientSessionModel session1;
 
@@ -94,7 +94,7 @@ public class UserSessionProviderTest {
         }
 
         assertEquals(null, session1.getAction());
-        assertEquals(realm.findClient("test-app").getClientId(), session1.getClient().getClientId());
+        assertEquals(realm.getClientByClientId("test-app").getClientId(), session1.getClient().getClientId());
         assertEquals(sessions[0].getId(), session1.getUserSession().getId());
         assertEquals("http://redirect", session1.getRedirectUri());
         assertEquals("state", session1.getNote(OIDCLoginProtocol.STATE_PARAM));
@@ -220,7 +220,7 @@ public class UserSessionProviderTest {
             }
         }
 
-        session.sessions().onClientRemoved(realm, realm.findClient("third-party"));
+        session.sessions().onClientRemoved(realm, realm.getClientByClientId("third-party"));
         resetSession();
 
         for (String c : clientSessionsRemoved) {
@@ -230,7 +230,7 @@ public class UserSessionProviderTest {
             assertNotNull(session.sessions().getClientSession(realm, c));
         }
 
-        session.sessions().onClientRemoved(realm, realm.findClient("test-app"));
+        session.sessions().onClientRemoved(realm, realm.getClientByClientId("test-app"));
         resetSession();
 
         for (String c : clientSessionsRemoved) {
@@ -244,7 +244,7 @@ public class UserSessionProviderTest {
     @Test
     public void testRemoveUserSessionsByExpired() {
         session.sessions().getUserSessions(realm, session.users().getUserByUsername("user1", realm));
-        ClientModel client = realm.findClient("test-app");
+        ClientModel client = realm.getClientByClientId("test-app");
 
         try {
             Set<String> expired = new HashSet<String>();
@@ -301,7 +301,7 @@ public class UserSessionProviderTest {
             realm.setAccessCodeLifespanLogin(30);
 
             // Login lifespan is largest
-            String clientSessionId = session.sessions().createClientSession(realm, realm.findClient("test-app")).getId();
+            String clientSessionId = session.sessions().createClientSession(realm, realm.getClientByClientId("test-app")).getId();
             resetSession();
 
             Time.setOffset(25);
@@ -320,7 +320,7 @@ public class UserSessionProviderTest {
             realm.setAccessCodeLifespanUserAction(40);
 
             Time.setOffset(0);
-            clientSessionId = session.sessions().createClientSession(realm, realm.findClient("test-app")).getId();
+            clientSessionId = session.sessions().createClientSession(realm, realm.getClientByClientId("test-app")).getId();
             resetSession();
 
             Time.setOffset(35);
@@ -339,7 +339,7 @@ public class UserSessionProviderTest {
             realm.setAccessCodeLifespan(50);
 
             Time.setOffset(0);
-            clientSessionId = session.sessions().createClientSession(realm, realm.findClient("test-app")).getId();
+            clientSessionId = session.sessions().createClientSession(realm, realm.getClientByClientId("test-app")).getId();
             resetSession();
 
             Time.setOffset(45);
@@ -367,8 +367,8 @@ public class UserSessionProviderTest {
     public void testGetByClient() {
         UserSessionModel[] sessions = createSessions();
 
-        assertSessions(session.sessions().getUserSessions(realm, realm.findClient("test-app")), sessions[0], sessions[1], sessions[2]);
-        assertSessions(session.sessions().getUserSessions(realm, realm.findClient("third-party")), sessions[0]);
+        assertSessions(session.sessions().getUserSessions(realm, realm.getClientByClientId("test-app")), sessions[0], sessions[1], sessions[2]);
+        assertSessions(session.sessions().getUserSessions(realm, realm.getClientByClientId("third-party")), sessions[0]);
     }
 
     @Test
@@ -377,7 +377,7 @@ public class UserSessionProviderTest {
             for (int i = 0; i < 25; i++) {
                 Time.setOffset(i);
                 UserSessionModel userSession = session.sessions().createUserSession(realm, session.users().getUserByUsername("user1", realm), "user1", "127.0.0." + i, "form", false, null, null);
-                ClientSessionModel clientSession = session.sessions().createClientSession(realm, realm.findClient("test-app"));
+                ClientSessionModel clientSession = session.sessions().createClientSession(realm, realm.getClientByClientId("test-app"));
                 clientSession.setUserSession(userSession);
                 clientSession.setRedirectUri("http://redirect");
                 clientSession.setRoles(new HashSet<String>());
@@ -390,11 +390,11 @@ public class UserSessionProviderTest {
 
         resetSession();
 
-        assertPaginatedSession(realm, realm.findClient("test-app"), 0, 1, 1);
-        assertPaginatedSession(realm, realm.findClient("test-app"), 0, 10, 10);
-        assertPaginatedSession(realm, realm.findClient("test-app"), 10, 10, 10);
-        assertPaginatedSession(realm, realm.findClient("test-app"), 20, 10, 5);
-        assertPaginatedSession(realm, realm.findClient("test-app"), 30, 10, 0);
+        assertPaginatedSession(realm, realm.getClientByClientId("test-app"), 0, 1, 1);
+        assertPaginatedSession(realm, realm.getClientByClientId("test-app"), 0, 10, 10);
+        assertPaginatedSession(realm, realm.getClientByClientId("test-app"), 10, 10, 10);
+        assertPaginatedSession(realm, realm.getClientByClientId("test-app"), 20, 10, 5);
+        assertPaginatedSession(realm, realm.getClientByClientId("test-app"), 30, 10, 0);
     }
 
     private void assertPaginatedSession(RealmModel realm, ClientModel client, int start, int max, int expectedSize) {
@@ -416,8 +416,8 @@ public class UserSessionProviderTest {
     public void testGetCountByClient() {
         createSessions();
 
-        assertEquals(3, session.sessions().getActiveUserSessions(realm, realm.findClient("test-app")));
-        assertEquals(1, session.sessions().getActiveUserSessions(realm, realm.findClient("third-party")));
+        assertEquals(3, session.sessions().getActiveUserSessions(realm, realm.getClientByClientId("test-app")));
+        assertEquals(1, session.sessions().getActiveUserSessions(realm, realm.getClientByClientId("third-party")));
     }
 
     @Test
@@ -487,14 +487,14 @@ public class UserSessionProviderTest {
         roles.add("one");
         roles.add("two");
 
-        createClientSession(realm.findClient("test-app"), sessions[0], "http://redirect", "state", roles);
-        createClientSession(realm.findClient("third-party"), sessions[0], "http://redirect", "state", new HashSet<String>());
+        createClientSession(realm.getClientByClientId("test-app"), sessions[0], "http://redirect", "state", roles);
+        createClientSession(realm.getClientByClientId("third-party"), sessions[0], "http://redirect", "state", new HashSet<String>());
 
         sessions[1] = session.sessions().createUserSession(realm, session.users().getUserByUsername("user1", realm), "user1", "127.0.0.2", "form", true, null, null);
-        createClientSession(realm.findClient("test-app"), sessions[1], "http://redirect", "state", new HashSet<String>());
+        createClientSession(realm.getClientByClientId("test-app"), sessions[1], "http://redirect", "state", new HashSet<String>());
 
         sessions[2] = session.sessions().createUserSession(realm, session.users().getUserByUsername("user2", realm), "user2", "127.0.0.3", "form", true, null, null);
-        createClientSession(realm.findClient("test-app"), sessions[2], "http://redirect", "state", new HashSet<String>());
+        createClientSession(realm.getClientByClientId("test-app"), sessions[2], "http://redirect", "state", new HashSet<String>());
 
         resetSession();
 
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java
index 7120b36..1fd4528 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java
@@ -32,7 +32,6 @@ import org.keycloak.events.Details;
 import org.keycloak.events.Errors;
 import org.keycloak.events.Event;
 import org.keycloak.jose.jws.JWSInput;
-import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.ProtocolMapperModel;
@@ -41,7 +40,6 @@ import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.protocol.oidc.mappers.AddressMapper;
-import org.keycloak.protocol.oidc.mappers.FullNameMapper;
 import org.keycloak.protocol.oidc.mappers.HardcodedClaim;
 import org.keycloak.protocol.oidc.mappers.HardcodedRole;
 import org.keycloak.protocol.oidc.mappers.RoleNameMapper;
@@ -471,7 +469,7 @@ public class AccessTokenTest {
             {
                 KeycloakSession session = keycloakRule.startSession();
                 RealmModel realm = session.realms().getRealmByName("test");
-                ApplicationModel clientModel = realm.getApplicationByName("test-app");
+                ClientModel clientModel = realm.getClientByClientId("test-app");
                 clientModel.setBearerOnly(true);
                 session.getTransaction().commit();
                 session.close();
@@ -485,7 +483,7 @@ public class AccessTokenTest {
             {
                 KeycloakSession session = keycloakRule.startSession();
                 RealmModel realm = session.realms().getRealmByName("test");
-                ApplicationModel clientModel = realm.getApplicationByName("test-app");
+                ClientModel clientModel = realm.getClientByClientId("test-app");
                 clientModel.setBearerOnly(false);
                 session.getTransaction().commit();
                 session.close();
@@ -521,7 +519,7 @@ public class AccessTokenTest {
             {
                 KeycloakSession session = keycloakRule.startSession();
                 RealmModel realm = session.realms().getRealmByName("test");
-                ClientModel clientModel = realm.findClient("test-app");
+                ClientModel clientModel = realm.getClientByClientId("test-app");
                 clientModel.setEnabled(false);
                 session.getTransaction().commit();
                 session.close();
@@ -535,7 +533,7 @@ public class AccessTokenTest {
             {
                 KeycloakSession session = keycloakRule.startSession();
                 RealmModel realm = session.realms().getRealmByName("test");
-                ClientModel clientModel = realm.findClient("test-app");
+                ClientModel clientModel = realm.getClientByClientId("test-app");
                 clientModel.setEnabled(true);
                 session.getTransaction().commit();
                 session.close();
@@ -624,7 +622,7 @@ public class AccessTokenTest {
             user.setAttribute("postal_code", "02115");
             user.setAttribute("country", "USA");
             user.setAttribute("phone", "617-777-6666");
-            ApplicationModel app = realm.getApplicationByName("test-app");
+            ClientModel app = realm.getClientByClientId("test-app");
             ProtocolMapperModel mapper = AddressMapper.createAddressMapper(true, true);
             app.addProtocolMapper(mapper);
             app.addProtocolMapper(HardcodedClaim.create("hard", "hard", "coded", "String", false, null, true, true));
@@ -687,7 +685,7 @@ public class AccessTokenTest {
         {
             KeycloakSession session = keycloakRule.startSession();
             RealmModel realm = session.realms().getRealmByName("test");
-            ApplicationModel app = realm.getApplicationByName("test-app");
+            ClientModel app = realm.getClientByClientId("test-app");
             for (ProtocolMapperModel model : app.getProtocolMappers()) {
                 if (model.getName().equals("address")
                         || model.getName().equals("hard")
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AuthorizationCodeTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AuthorizationCodeTest.java
index 90a0e29..0a70da0 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AuthorizationCodeTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AuthorizationCodeTest.java
@@ -96,7 +96,7 @@ public class AuthorizationCodeTest {
         keycloakRule.update(new KeycloakRule.KeycloakSetup() {
             @Override
             public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                appRealm.getApplicationNameMap().get("test-app").addRedirectUri(Constants.INSTALLED_APP_URN);
+                appRealm.getClientNameMap().get("test-app").addRedirectUri(Constants.INSTALLED_APP_URN);
             }
         });
         oauth.redirectUri(Constants.INSTALLED_APP_URN);
@@ -115,7 +115,7 @@ public class AuthorizationCodeTest {
         keycloakRule.update(new KeycloakRule.KeycloakSetup() {
             @Override
             public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                appRealm.getApplicationNameMap().get("test-app").removeRedirectUri(Constants.INSTALLED_APP_URN);
+                appRealm.getClientNameMap().get("test-app").removeRedirectUri(Constants.INSTALLED_APP_URN);
             }
         });
     }
@@ -125,7 +125,7 @@ public class AuthorizationCodeTest {
         keycloakRule.update(new KeycloakRule.KeycloakSetup() {
             @Override
             public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                appRealm.getApplicationNameMap().get("test-app").addRedirectUri(Constants.INSTALLED_APP_URN);
+                appRealm.getClientNameMap().get("test-app").addRedirectUri(Constants.INSTALLED_APP_URN);
             }
         });
         oauth.redirectUri(Constants.INSTALLED_APP_URN);
@@ -147,7 +147,7 @@ public class AuthorizationCodeTest {
         keycloakRule.update(new KeycloakRule.KeycloakSetup() {
             @Override
             public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                appRealm.getApplicationNameMap().get("test-app").removeRedirectUri(Constants.INSTALLED_APP_URN);
+                appRealm.getClientNameMap().get("test-app").removeRedirectUri(Constants.INSTALLED_APP_URN);
             }
         });
     }
@@ -157,7 +157,7 @@ public class AuthorizationCodeTest {
         keycloakRule.update(new KeycloakRule.KeycloakSetup() {
             @Override
             public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                appRealm.getApplicationByName("test-app").addRedirectUri(oauth.getRedirectUri());
+                appRealm.getClientByClientId("test-app").addRedirectUri(oauth.getRedirectUri());
             }
         });
 
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/OAuthRedirectUriTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/OAuthRedirectUriTest.java
index 9aa884f..7cefa79 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/OAuthRedirectUriTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/OAuthRedirectUriTest.java
@@ -26,7 +26,7 @@ import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
 import org.keycloak.OAuth2Constants;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.Constants;
 import org.keycloak.models.RealmModel;
 import org.keycloak.services.managers.RealmManager;
@@ -39,8 +39,6 @@ import org.keycloak.testsuite.rule.WebRule;
 import org.openqa.selenium.WebDriver;
 
 import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
 
 /**
  * @author <a href="mailto:vrockai@redhat.com">Viliam Rockai</a>
@@ -51,18 +49,18 @@ public class OAuthRedirectUriTest {
     public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakRule.KeycloakSetup() {
         @Override
         public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-            ApplicationModel installedApp = appRealm.addApplication("test-installed");
+            ClientModel installedApp = appRealm.addClient("test-installed");
             installedApp.setEnabled(true);
             installedApp.addRedirectUri(Constants.INSTALLED_APP_URN);
             installedApp.addRedirectUri(Constants.INSTALLED_APP_URL);
             installedApp.setSecret("password");
 
-            ApplicationModel installedApp2 = appRealm.addApplication("test-installed2");
+            ClientModel installedApp2 = appRealm.addClient("test-installed2");
             installedApp2.setEnabled(true);
             installedApp2.addRedirectUri(Constants.INSTALLED_APP_URL + "/myapp");
             installedApp2.setSecret("password");
 
-            ApplicationModel installedApp3 = appRealm.addApplication("test-wildcard");
+            ClientModel installedApp3 = appRealm.addClient("test-wildcard");
             installedApp3.setEnabled(true);
             installedApp3.addRedirectUri("http://example.com/foo/*");
             installedApp3.addRedirectUri("http://localhost:8081/foo/*");
@@ -99,7 +97,7 @@ public class OAuthRedirectUriTest {
         keycloakRule.update(new KeycloakRule.KeycloakSetup() {
             @Override
             public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                appRealm.getApplicationNameMap().get("test-app").addRedirectUri("http://localhost:8081/app2");
+                appRealm.getClientNameMap().get("test-app").addRedirectUri("http://localhost:8081/app2");
             }
         });
 
@@ -113,7 +111,7 @@ public class OAuthRedirectUriTest {
             keycloakRule.update(new KeycloakRule.KeycloakSetup() {
                 @Override
                 public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                    appRealm.getApplicationNameMap().get("test-app").removeRedirectUri("http://localhost:8081/app2");
+                    appRealm.getClientNameMap().get("test-app").removeRedirectUri("http://localhost:8081/app2");
                 }
             });
         }
@@ -124,7 +122,7 @@ public class OAuthRedirectUriTest {
         keycloakRule.update(new KeycloakRule.KeycloakSetup() {
             @Override
             public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                appRealm.getApplicationNameMap().get("test-app").removeRedirectUri("http://localhost:8081/app/*");
+                appRealm.getClientNameMap().get("test-app").removeRedirectUri("http://localhost:8081/app/*");
             }
         });
 
@@ -138,7 +136,7 @@ public class OAuthRedirectUriTest {
             keycloakRule.update(new KeycloakRule.KeycloakSetup() {
                 @Override
                 public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                    appRealm.getApplicationNameMap().get("test-app").addRedirectUri("http://localhost:8081/app/*");
+                    appRealm.getClientNameMap().get("test-app").addRedirectUri("http://localhost:8081/app/*");
                 }
             });
         }
@@ -149,7 +147,7 @@ public class OAuthRedirectUriTest {
         keycloakRule.update(new KeycloakRule.KeycloakSetup() {
             @Override
             public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                appRealm.getApplicationNameMap().get("test-app").removeRedirectUri("http://localhost:8081/app/*");
+                appRealm.getClientNameMap().get("test-app").removeRedirectUri("http://localhost:8081/app/*");
             }
         });
 
@@ -163,7 +161,7 @@ public class OAuthRedirectUriTest {
             keycloakRule.update(new KeycloakRule.KeycloakSetup() {
                 @Override
                 public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                    appRealm.getApplicationNameMap().get("test-app").addRedirectUri("http://localhost:8081/app/*");
+                    appRealm.getClientNameMap().get("test-app").addRedirectUri("http://localhost:8081/app/*");
                 }
             });
         }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/ResourceOwnerPasswordCredentialsGrantTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/ResourceOwnerPasswordCredentialsGrantTest.java
index 7ab2568..90a88e2 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/ResourceOwnerPasswordCredentialsGrantTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/ResourceOwnerPasswordCredentialsGrantTest.java
@@ -6,7 +6,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.keycloak.events.Details;
 import org.keycloak.events.Errors;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserCredentialModel;
 import org.keycloak.models.UserModel;
@@ -31,7 +31,7 @@ public class ResourceOwnerPasswordCredentialsGrantTest {
     public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakRule.KeycloakSetup() {
         @Override
         public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-            ApplicationModel app = appRealm.addApplication("resource-owner");
+            ClientModel app = appRealm.addClient("resource-owner");
             app.setSecret("secret");
             appRealm.setPasswordCredentialGrantAllowed(true);
 
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlBindingTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlBindingTest.java
index 126c465..e91d58c 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlBindingTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlBindingTest.java
@@ -6,7 +6,7 @@ import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
 import org.keycloak.Config;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.Constants;
 import org.keycloak.models.KeycloakSession;
@@ -259,7 +259,7 @@ public class SamlBindingTest {
         keycloakRule.update(new KeycloakRule.KeycloakSetup() {
             @Override
             public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                ApplicationModel app = appRealm.getApplicationByName("http://localhost:8081/employee/");
+                ClientModel app = appRealm.getClientByClientId("http://localhost:8081/employee/");
                 for (ProtocolMapperModel mapper : app.getProtocolMappers()) {
                     if (mapper.getName().equals("role-list")) {
                         app.removeProtocolMapper(mapper);
@@ -419,7 +419,7 @@ public class SamlBindingTest {
             RealmManager manager = new RealmManager(session);
 
             RealmModel adminRealm = manager.getRealm(Config.getAdminRealm());
-            ApplicationModel adminConsole = adminRealm.getApplicationByName(Constants.ADMIN_CONSOLE_APPLICATION);
+            ClientModel adminConsole = adminRealm.getClientByClientId(Constants.ADMIN_CONSOLE_CLIENT_ID);
             TokenManager tm = new TokenManager();
             UserModel admin = session.users().getUserByUsername("admin", adminRealm);
             ClientSessionModel clientSession = session.sessions().createClientSession(adminRealm, adminConsole);
@@ -466,7 +466,7 @@ public class SamlBindingTest {
         Assert.assertNotNull(is);
         formData.addFormData("file", is, MediaType.APPLICATION_XML_TYPE);
 
-        WebTarget upload = adminRealms.path("demo/application-importers/saml2-entity-descriptor/upload");
+        WebTarget upload = adminRealms.path("demo/client-importers/saml2-entity-descriptor/upload");
         System.out.println(upload.getUri());
         Response response = upload.request().post(Entity.entity(formData, MediaType.MULTIPART_FORM_DATA));
         Assert.assertEquals(204, response.getStatus());
diff --git a/testsuite/integration/src/test/resources/testrealm.json b/testsuite/integration/src/test/resources/testrealm.json
index cedc22d..c9b6708 100755
--- a/testsuite/integration/src/test/resources/testrealm.json
+++ b/testsuite/integration/src/test/resources/testrealm.json
@@ -27,7 +27,7 @@
                   "value" : "password" }
             ],
             "realmRoles": ["user"],
-            "applicationRoles": {
+            "clientRoles": {
                 "test-app": [ "customer-user" ],
                 "account": [ "view-profile", "manage-account" ]
             }
@@ -41,22 +41,12 @@
                     "value" : "password" }
             ],
             "realmRoles": ["user"],
-            "applicationRoles": {
+            "clientRoles": {
                 "test-app": [ "customer-user" ],
                 "account": [ "view-profile", "manage-account" ]
             }
         }
     ],
-    "oauthClients" : [
-        {
-            "name" : "third-party",
-            "enabled": true,
-            "redirectUris": [
-                "http://localhost:8081/app/*"
-            ],
-            "secret": "password"
-        }
-    ],
     "scopeMappings": [
         {
             "client": "third-party",
@@ -67,9 +57,9 @@
             "roles": ["user"]
         }
     ],
-    "applications": [
+    "clients": [
         {
-            "name": "test-app",
+            "clientId": "test-app",
             "enabled": true,
             "baseUrl": "http://localhost:8081/app",
             "redirectUris": [
@@ -77,7 +67,17 @@
             ],
             "adminUrl": "http://localhost:8081/app/logout",
             "secret": "password"
-         }
+        },
+        {
+            "clientId" : "third-party",
+            "enabled": true,
+            "consentRequired": true,
+
+            "redirectUris": [
+                "http://localhost:8081/app/*"
+            ],
+            "secret": "password"
+        }
     ],
     "roles" : {
         "realm" : [
@@ -90,7 +90,7 @@
                 "description": "Have Administrator privileges"
             }
         ],
-        "application" : {
+        "client" : {
             "test-app" : [
                 {
                     "name": "customer-user",
@@ -105,7 +105,7 @@
 
     },
 
-    "applicationScopeMappings": {
+    "clientScopeMappings": {
         "test-app": [
             {
                 "client": "third-party",
diff --git a/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/CreateRealmsWorker.java b/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/CreateRealmsWorker.java
index 14a106c..f913c15 100755
--- a/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/CreateRealmsWorker.java
+++ b/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/CreateRealmsWorker.java
@@ -3,7 +3,7 @@ package org.keycloak.testsuite.performance;
 import org.apache.jmeter.samplers.SampleResult;
 import org.apache.jorphan.logging.LoggingManager;
 import org.apache.log.Logger;
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.utils.RepresentationToModel;
@@ -70,7 +70,7 @@ public class CreateRealmsWorker implements Worker {
 
         // Add applications
         for (int i=1 ; i<=appsPerRealm ; i++) {
-            ApplicationModel application = realm.addApplication(PerfTestUtils.getApplicationName(realmNumber, i));
+            ClientModel application = realm.addClient(PerfTestUtils.getApplicationName(realmNumber, i));
             for (int j=1 ; j<=rolesPerApp ; j++) {
                 application.addRole(PerfTestUtils.getApplicationRoleName(realmNumber, i, j));
             }
diff --git a/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/CreateUsersJob.java b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/CreateUsersJob.java
index 115d5ae..4c1bd01 100755
--- a/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/CreateUsersJob.java
+++ b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/CreateUsersJob.java
@@ -1,6 +1,6 @@
 package org.keycloak.test.tools.jobs;
 
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
@@ -26,7 +26,7 @@ public class CreateUsersJob extends UsersJob {
     }
 
     @Override
-    protected void runIteration(KeycloakSession session, RealmModel realm, Map<String, ApplicationModel> apps, Set<RoleModel> realmRoles, Map<String, Set<RoleModel>> appRoles, int counter) {
+    protected void runIteration(KeycloakSession session, RealmModel realm, Map<String, ClientModel> apps, Set<RoleModel> realmRoles, Map<String, Set<RoleModel>> appRoles, int counter) {
         String username = prefix + "-" + counter;
         UserModel user = session.users().addUser(realm, username);
         user.setEnabled(true);
diff --git a/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/DeleteUsersJob.java b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/DeleteUsersJob.java
index e271108..7e39f94 100755
--- a/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/DeleteUsersJob.java
+++ b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/DeleteUsersJob.java
@@ -1,6 +1,6 @@
 package org.keycloak.test.tools.jobs;
 
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
@@ -31,7 +31,7 @@ public class DeleteUsersJob extends UsersJob {
     }
 
     @Override
-    protected void runIteration(KeycloakSession session, RealmModel realm, Map<String, ApplicationModel> apps, Set<RoleModel> realmRoles, Map<String, Set<RoleModel>> appRoles, int counter) {
+    protected void runIteration(KeycloakSession session, RealmModel realm, Map<String, ClientModel> apps, Set<RoleModel> realmRoles, Map<String, Set<RoleModel>> appRoles, int counter) {
         session.users().removeUser(realm, users.next());
     }
 }
diff --git a/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UpdateUsersJob.java b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UpdateUsersJob.java
index 276b6d8..6068764 100755
--- a/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UpdateUsersJob.java
+++ b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UpdateUsersJob.java
@@ -1,6 +1,6 @@
 package org.keycloak.test.tools.jobs;
 
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
@@ -36,7 +36,7 @@ public class UpdateUsersJob extends UsersJob {
     }
 
     @Override
-    protected void runIteration(KeycloakSession session, RealmModel realm, Map<String, ApplicationModel> apps, Set<RoleModel> realmRoles, Map<String, Set<RoleModel>> appRoles, int counter) {
+    protected void runIteration(KeycloakSession session, RealmModel realm, Map<String, ClientModel> apps, Set<RoleModel> realmRoles, Map<String, Set<RoleModel>> appRoles, int counter) {
         String username = users.next().getUsername();
 
         // Remove all role mappings first
diff --git a/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UsersJob.java b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UsersJob.java
index b58a03b..d2f797a 100755
--- a/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UsersJob.java
+++ b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UsersJob.java
@@ -1,6 +1,6 @@
 package org.keycloak.test.tools.jobs;
 
-import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
 import org.keycloak.models.RealmModel;
@@ -61,11 +61,11 @@ public abstract class UsersJob implements Runnable {
             session.getTransaction().begin();
 
             RealmModel realm = new RealmManager(session).getRealmByName(realmName);
-            Map<String, ApplicationModel> apps = realm.getApplicationNameMap();
+            Map<String, ClientModel> apps = realm.getClientNameMap();
 
             Set<RoleModel> realmRoles = realm.getRoles();
             Map<String, Set<RoleModel>> appRoles = new HashMap<String, Set<RoleModel>>();
-            for (Map.Entry<String, ApplicationModel> appEntry : apps.entrySet()) {
+            for (Map.Entry<String, ClientModel> appEntry : apps.entrySet()) {
                 appRoles.put(appEntry.getKey(), appEntry.getValue().getRoles());
             }
 
@@ -86,7 +86,7 @@ public abstract class UsersJob implements Runnable {
 
     protected abstract void before(KeycloakSession keycloakSession);
 
-    protected abstract void runIteration(KeycloakSession session, RealmModel realm, Map<String, ApplicationModel> apps, Set<RoleModel> realmRoles, Map<String, Set<RoleModel>> appRoles, int counter);
+    protected abstract void runIteration(KeycloakSession session, RealmModel realm, Map<String, ClientModel> apps, Set<RoleModel> realmRoles, Map<String, Set<RoleModel>> appRoles, int counter);
 
     protected RoleModel findRole(Set<RoleModel> roles, String roleName) {
         for (RoleModel role : roles) {