keycloak-memoizeit

Merge pull request #3350 from patriot1burke/master federated

10/18/2016 4:15:25 PM

Changes

Details

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 bcbb02d..11ee08a 100755
--- a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
@@ -95,6 +95,7 @@ public class RealmRepresentation {
     protected Integer otpPolicyPeriod;
 
     protected List<UserRepresentation> users;
+    protected List<UserRepresentation> federatedUsers;
     protected List<ScopeMappingRepresentation> scopeMappings;
     protected Map<String, List<ScopeMappingRepresentation>> clientScopeMappings;
     protected List<ClientRepresentation> clients;
@@ -883,4 +884,11 @@ public class RealmRepresentation {
         return attributes;
     }
 
+    public List<UserRepresentation> getFederatedUsers() {
+        return federatedUsers;
+    }
+
+    public void setFederatedUsers(List<UserRepresentation> federatedUsers) {
+        this.federatedUsers = federatedUsers;
+    }
 }
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java
index cdb79a7..547419e 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java
@@ -475,15 +475,15 @@ public class UserCacheSession implements UserCache {
     }
 
     @Override
-    public void updateConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
-        invalidations.add(getConsentCacheKey(user.getId()));
-        getDelegate().updateConsent(realm, user, consent);
+    public void updateConsent(RealmModel realm, String userId, UserConsentModel consent) {
+        invalidations.add(getConsentCacheKey(userId));
+        getDelegate().updateConsent(realm, userId, consent);
     }
 
     @Override
-    public boolean revokeConsentForClient(RealmModel realm, UserModel user, String clientInternalId) {
-        invalidations.add(getConsentCacheKey(user.getId()));
-        return getDelegate().revokeConsentForClient(realm, user, clientInternalId);
+    public boolean revokeConsentForClient(RealmModel realm, String userId, String clientInternalId) {
+        invalidations.add(getConsentCacheKey(userId));
+        return getDelegate().revokeConsentForClient(realm, userId, clientInternalId);
     }
 
     public String getConsentCacheKey(String userId) {
@@ -492,25 +492,25 @@ public class UserCacheSession implements UserCache {
 
 
     @Override
-    public void addConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
-        invalidations.add(getConsentCacheKey(user.getId()));
-        getDelegate().addConsent(realm, user, consent);
+    public void addConsent(RealmModel realm, String userId, UserConsentModel consent) {
+        invalidations.add(getConsentCacheKey(userId));
+        getDelegate().addConsent(realm, userId, consent);
     }
 
     @Override
-    public UserConsentModel getConsentByClient(RealmModel realm, UserModel user, String clientId) {
-        logger.tracev("getConsentByClient: {0}", user.getUsername());
+    public UserConsentModel getConsentByClient(RealmModel realm, String userId, String clientId) {
+        logger.tracev("getConsentByClient: {0}", userId);
 
-        String cacheKey = getConsentCacheKey(user.getId());
-        if (realmInvalidations.contains(realm.getId()) || invalidations.contains(user.getId()) || invalidations.contains(cacheKey)) {
-            return getDelegate().getConsentByClient(realm, user, clientId);
+        String cacheKey = getConsentCacheKey(userId);
+        if (realmInvalidations.contains(realm.getId()) || invalidations.contains(userId) || invalidations.contains(cacheKey)) {
+            return getDelegate().getConsentByClient(realm, userId, clientId);
         }
 
         CachedUserConsents cached = cache.get(cacheKey, CachedUserConsents.class);
 
         if (cached == null) {
             Long loaded = cache.getCurrentRevision(cacheKey);
-            List<UserConsentModel> consents = getDelegate().getConsents(realm, user);
+            List<UserConsentModel> consents = getDelegate().getConsents(realm, userId);
             cached = new CachedUserConsents(loaded, cacheKey, realm, consents);
             cache.addRevisioned(cached, startupRevision);
         }
@@ -520,19 +520,19 @@ public class UserCacheSession implements UserCache {
     }
 
     @Override
-    public List<UserConsentModel> getConsents(RealmModel realm, UserModel user) {
-        logger.tracev("getConsents: {0}", user.getUsername());
+    public List<UserConsentModel> getConsents(RealmModel realm, String userId) {
+        logger.tracev("getConsents: {0}", userId);
 
-        String cacheKey = getConsentCacheKey(user.getId());
-        if (realmInvalidations.contains(realm.getId()) || invalidations.contains(user.getId()) || invalidations.contains(cacheKey)) {
-            return getDelegate().getConsents(realm, user);
+        String cacheKey = getConsentCacheKey(userId);
+        if (realmInvalidations.contains(realm.getId()) || invalidations.contains(userId) || invalidations.contains(cacheKey)) {
+            return getDelegate().getConsents(realm, userId);
         }
 
         CachedUserConsents cached = cache.get(cacheKey, CachedUserConsents.class);
 
         if (cached == null) {
             Long loaded = cache.getCurrentRevision(cacheKey);
-            List<UserConsentModel> consents = getDelegate().getConsents(realm, user);
+            List<UserConsentModel> consents = getDelegate().getConsents(realm, userId);
             cached = new CachedUserConsents(loaded, cacheKey, realm, consents);
             cache.addRevisioned(cached, startupRevision);
             return consents;
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 3aa71f0..bd03727 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
@@ -194,19 +194,19 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
     }
 
     @Override
-    public void addConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
+    public void addConsent(RealmModel realm, String userId, UserConsentModel consent) {
         String clientId = consent.getClient().getId();
 
-        UserConsentEntity consentEntity = getGrantedConsentEntity(user, clientId);
+        UserConsentEntity consentEntity = getGrantedConsentEntity(userId, clientId);
         if (consentEntity != null) {
-            throw new ModelDuplicateException("Consent already exists for client [" + clientId + "] and user [" + user.getId() + "]");
+            throw new ModelDuplicateException("Consent already exists for client [" + clientId + "] and user [" + userId + "]");
         }
 
         long currentTime = Time.currentTimeMillis();
 
         consentEntity = new UserConsentEntity();
         consentEntity.setId(KeycloakModelUtils.generateId());
-        consentEntity.setUser(em.getReference(UserEntity.class, user.getId()));
+        consentEntity.setUser(em.getReference(UserEntity.class, userId));
         consentEntity.setClientId(clientId);
         consentEntity.setCreatedDate(currentTime);
         consentEntity.setLastUpdatedDate(currentTime);
@@ -217,15 +217,15 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
     }
 
     @Override
-    public UserConsentModel getConsentByClient(RealmModel realm, UserModel user, String clientId) {
-        UserConsentEntity entity = getGrantedConsentEntity(user, clientId);
+    public UserConsentModel getConsentByClient(RealmModel realm, String userId, String clientId) {
+        UserConsentEntity entity = getGrantedConsentEntity(userId, clientId);
         return toConsentModel(realm, entity);
     }
 
     @Override
-    public List<UserConsentModel> getConsents(RealmModel realm, UserModel user) {
+    public List<UserConsentModel> getConsents(RealmModel realm, String userId) {
         TypedQuery<UserConsentEntity> query = em.createNamedQuery("userConsentsByUser", UserConsentEntity.class);
-        query.setParameter("userId", user.getId());
+        query.setParameter("userId", userId);
         List<UserConsentEntity> results = query.getResultList();
 
         List<UserConsentModel> consents = new ArrayList<UserConsentModel>();
@@ -237,19 +237,19 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
     }
 
     @Override
-    public void updateConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
+    public void updateConsent(RealmModel realm, String userId, UserConsentModel consent) {
         String clientId = consent.getClient().getId();
 
-        UserConsentEntity consentEntity = getGrantedConsentEntity(user, clientId);
+        UserConsentEntity consentEntity = getGrantedConsentEntity(userId, clientId);
         if (consentEntity == null) {
-            throw new ModelException("Consent not found for client [" + clientId + "] and user [" + user.getId() + "]");
+            throw new ModelException("Consent not found for client [" + clientId + "] and user [" + userId + "]");
         }
 
         updateGrantedConsentEntity(consentEntity, consent);
     }
 
-    public boolean revokeConsentForClient(RealmModel realm, UserModel user, String clientId) {
-        UserConsentEntity consentEntity = getGrantedConsentEntity(user, clientId);
+    public boolean revokeConsentForClient(RealmModel realm, String userId, String clientId) {
+        UserConsentEntity consentEntity = getGrantedConsentEntity(userId, clientId);
         if (consentEntity == null) return false;
 
         em.remove(consentEntity);
@@ -258,13 +258,13 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
     }
 
 
-    private UserConsentEntity getGrantedConsentEntity(UserModel user, String clientId) {
+    private UserConsentEntity getGrantedConsentEntity(String userId, String clientId) {
         TypedQuery<UserConsentEntity> query = em.createNamedQuery("userConsentByUserAndClient", UserConsentEntity.class);
-        query.setParameter("userId", user.getId());
+        query.setParameter("userId", userId);
         query.setParameter("clientId", clientId);
         List<UserConsentEntity> results = query.getResultList();
         if (results.size() > 1) {
-            throw new ModelException("More results found for user [" + user.getUsername() + "] and client [" + clientId + "]");
+            throw new ModelException("More results found for user [" + userId + "] and client [" + clientId + "]");
         } else if (results.size() == 1) {
             return results.get(0);
         } else {
diff --git a/model/jpa/src/main/java/org/keycloak/storage/jpa/entity/FederatedUser.java b/model/jpa/src/main/java/org/keycloak/storage/jpa/entity/FederatedUser.java
index b5c958c..c74c630 100644
--- a/model/jpa/src/main/java/org/keycloak/storage/jpa/entity/FederatedUser.java
+++ b/model/jpa/src/main/java/org/keycloak/storage/jpa/entity/FederatedUser.java
@@ -31,6 +31,7 @@ import javax.persistence.Table;
  */
 @NamedQueries({
         @NamedQuery(name="getFederatedUserIds", query="select f.id from FederatedUser f where f.realmId=:realmId"),
+        @NamedQuery(name="getFederatedUserCount", query="select count(u) from FederatedUser u where u.realmId = :realmId"),
         @NamedQuery(name="deleteFederatedUserByUser", query="delete from  FederatedUser f where f.id = :userId and f.realmId=:realmId"),
         @NamedQuery(name="deleteFederatedUsersByRealm", query="delete from  FederatedUser f where f.realmId=:realmId"),
         @NamedQuery(name="deleteFederatedUsersByStorageProvider", query="delete from FederatedUser f where f.storageProviderId=:storageProviderId"),
diff --git a/model/jpa/src/main/java/org/keycloak/storage/jpa/JpaUserFederatedStorageProvider.java b/model/jpa/src/main/java/org/keycloak/storage/jpa/JpaUserFederatedStorageProvider.java
index 713447b..e1f2bd4 100644
--- a/model/jpa/src/main/java/org/keycloak/storage/jpa/JpaUserFederatedStorageProvider.java
+++ b/model/jpa/src/main/java/org/keycloak/storage/jpa/JpaUserFederatedStorageProvider.java
@@ -70,12 +70,6 @@ import java.util.Set;
  */
 public class JpaUserFederatedStorageProvider implements
         UserFederatedStorageProvider,
-        UserAttributeFederatedStorage,
-        UserBrokerLinkFederatedStorage,
-        UserConsentFederatedStorage,
-        UserGroupMembershipFederatedStorage,
-        UserRequiredActionsFederatedStorage,
-        UserRoleMappingsFederatedStorage,
         UserCredentialStore {
 
     private final KeycloakSession session;
@@ -95,66 +89,66 @@ public class JpaUserFederatedStorageProvider implements
      * We create an entry so that its easy to iterate over all things in the database.  Specifically useful for export
      *
      */
-    protected void createIndex(RealmModel realm, UserModel user) {
-        if (em.find(FederatedUser.class, user.getId()) == null) {
+    protected void createIndex(RealmModel realm, String userId) {
+        if (em.find(FederatedUser.class, userId) == null) {
             FederatedUser fedUser = new FederatedUser();
-            fedUser.setId(user.getId());
+            fedUser.setId(userId);
             fedUser.setRealmId(realm.getId());
-            fedUser.setStorageProviderId(StorageId.resolveProviderId(user));
+            fedUser.setStorageProviderId(new StorageId(userId).getProviderId());
             em.persist(fedUser);
         }
     }
 
 
     @Override
-    public void setAttribute(RealmModel realm, UserModel user, String name, List<String> values) {
-        createIndex(realm, user);
-        deleteAttribute(realm, user, name);
+    public void setAttribute(RealmModel realm, String userId, String name, List<String> values) {
+        createIndex(realm, userId);
+        deleteAttribute(realm, userId, name);
         em.flush();
         for (String value : values) {
-            persistAttributeValue(realm, user, name, value);
+            persistAttributeValue(realm, userId, name, value);
         }
     }
 
-    private void deleteAttribute(RealmModel realm, UserModel user, String name) {
+    private void deleteAttribute(RealmModel realm, String userId, String name) {
         em.createNamedQuery("deleteUserFederatedAttributesByUserAndName")
-                .setParameter("userId", user.getId())
+                .setParameter("userId", userId)
                 .setParameter("realmId", realm.getId())
                 .setParameter("name", name)
                 .executeUpdate();
     }
 
-    private void persistAttributeValue(RealmModel realm, UserModel user, String name, String value) {
+    private void persistAttributeValue(RealmModel realm, String userId, String name, String value) {
         FederatedUserAttributeEntity attr = new FederatedUserAttributeEntity();
         attr.setId(KeycloakModelUtils.generateId());
         attr.setName(name);
         attr.setValue(value);
-        attr.setUserId(user.getId());
+        attr.setUserId(userId);
         attr.setRealmId(realm.getId());
-        attr.setStorageProviderId(StorageId.resolveProviderId(user));
+        attr.setStorageProviderId(new StorageId(userId).getProviderId());
         em.persist(attr);
     }
 
     @Override
-    public void setSingleAttribute(RealmModel realm, UserModel user, String name, String value) {
-        createIndex(realm, user);
-        deleteAttribute(realm, user, name);
+    public void setSingleAttribute(RealmModel realm, String userId, String name, String value) {
+        createIndex(realm, userId);
+        deleteAttribute(realm, userId, name);
         em.flush();
-        persistAttributeValue(realm, user, name, value);
+        persistAttributeValue(realm, userId, name, value);
     }
 
     @Override
-    public void removeAttribute(RealmModel realm, UserModel user, String name) {
+    public void removeAttribute(RealmModel realm, String userId, String name) {
         //         createIndex(realm, user); don't need to create an index for removal
-        deleteAttribute(realm, user, name);
+        deleteAttribute(realm, userId, name);
         em.flush();
     }
 
     @Override
-    public MultivaluedHashMap<String, String> getAttributes(RealmModel realm, UserModel user) {
+    public MultivaluedHashMap<String, String> getAttributes(RealmModel realm, String userId) {
         TypedQuery<FederatedUserAttributeEntity> query = em.createNamedQuery("getFederatedAttributesByUser", FederatedUserAttributeEntity.class);
         List<FederatedUserAttributeEntity> list = query
-                .setParameter("userId", user.getId())
+                .setParameter("userId", userId)
                 .setParameter("realmId", realm.getId())
                 .getResultList();
         MultivaluedHashMap<String, String> result = new MultivaluedHashMap<>();
@@ -192,31 +186,31 @@ public class JpaUserFederatedStorageProvider implements
     }
 
     @Override
-    public void addFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel link) {
-        createIndex(realm, user);
+    public void addFederatedIdentity(RealmModel realm, String userId, FederatedIdentityModel link) {
+        createIndex(realm, userId);
         BrokerLinkEntity entity = new BrokerLinkEntity();
         entity.setRealmId(realm.getId());
-        entity.setUserId(user.getId());
+        entity.setUserId(userId);
         entity.setBrokerUserId(link.getUserId());
         entity.setIdentityProvider(link.getIdentityProvider());
         entity.setToken(link.getToken());
         entity.setBrokerUserName(link.getUserName());
-        entity.setStorageProviderId(StorageId.resolveProviderId(user));
+        entity.setStorageProviderId(new StorageId(userId).getProviderId());
         em.persist(entity);
 
     }
 
     @Override
-    public boolean removeFederatedIdentity(RealmModel realm, UserModel user, String socialProvider) {
-        BrokerLinkEntity entity = getBrokerLinkEntity(realm, user, socialProvider);
+    public boolean removeFederatedIdentity(RealmModel realm, String userId, String socialProvider) {
+        BrokerLinkEntity entity = getBrokerLinkEntity(realm, userId, socialProvider);
         if (entity == null) return false;
         em.remove(entity);
         return true;
     }
 
-    private BrokerLinkEntity getBrokerLinkEntity(RealmModel realm, UserModel user, String socialProvider) {
+    private BrokerLinkEntity getBrokerLinkEntity(RealmModel realm, String userId, String socialProvider) {
         TypedQuery<BrokerLinkEntity> query = em.createNamedQuery("findBrokerLinkByUserAndProvider", BrokerLinkEntity.class)
-                .setParameter("userId", user.getId())
+                .setParameter("userId", userId)
                 .setParameter("realmId", realm.getId())
                 .setParameter("identityProvider", socialProvider);
         List<BrokerLinkEntity> results = query.getResultList();
@@ -224,9 +218,9 @@ public class JpaUserFederatedStorageProvider implements
     }
 
     @Override
-    public void updateFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel model) {
-        createIndex(realm, user);
-        BrokerLinkEntity entity = getBrokerLinkEntity(realm, user, model.getIdentityProvider());
+    public void updateFederatedIdentity(RealmModel realm, String userId, FederatedIdentityModel model) {
+        createIndex(realm, userId);
+        BrokerLinkEntity entity = getBrokerLinkEntity(realm, userId, model.getIdentityProvider());
         if (entity == null) return;
         entity.setBrokerUserName(model.getUserName());
         entity.setBrokerUserId(model.getUserId());
@@ -237,9 +231,9 @@ public class JpaUserFederatedStorageProvider implements
     }
 
     @Override
-    public Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm) {
+    public Set<FederatedIdentityModel> getFederatedIdentities(String userId, RealmModel realm) {
         TypedQuery<BrokerLinkEntity> query = em.createNamedQuery("findBrokerLinkByUser", BrokerLinkEntity.class)
-                .setParameter("userId", user.getId());
+                .setParameter("userId", userId);
         List<BrokerLinkEntity> results = query.getResultList();
         Set<FederatedIdentityModel> set = new HashSet<>();
         for (BrokerLinkEntity entity : results) {
@@ -250,28 +244,28 @@ public class JpaUserFederatedStorageProvider implements
     }
 
     @Override
-    public FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm) {
-        BrokerLinkEntity entity = getBrokerLinkEntity(realm, user, socialProvider);
+    public FederatedIdentityModel getFederatedIdentity(String userId, String socialProvider, RealmModel realm) {
+        BrokerLinkEntity entity = getBrokerLinkEntity(realm, userId, socialProvider);
         if (entity == null) return null;
         return new FederatedIdentityModel(entity.getIdentityProvider(), entity.getBrokerUserId(), entity.getBrokerUserName(), entity.getToken());
     }
 
     @Override
-    public void addConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
-        createIndex(realm, user);
+    public void addConsent(RealmModel realm, String userId, UserConsentModel consent) {
+        createIndex(realm, userId);
         String clientId = consent.getClient().getId();
 
-        FederatedUserConsentEntity consentEntity = getGrantedConsentEntity(user, clientId);
+        FederatedUserConsentEntity consentEntity = getGrantedConsentEntity(userId, clientId);
         if (consentEntity != null) {
-            throw new ModelDuplicateException("Consent already exists for client [" + clientId + "] and user [" + user.getId() + "]");
+            throw new ModelDuplicateException("Consent already exists for client [" + clientId + "] and user [" + userId + "]");
         }
 
         consentEntity = new FederatedUserConsentEntity();
         consentEntity.setId(KeycloakModelUtils.generateId());
-        consentEntity.setUserId(user.getId());
+        consentEntity.setUserId(userId);
         consentEntity.setClientId(clientId);
         consentEntity.setRealmId(realm.getId());
-        consentEntity.setStorageProviderId(StorageId.resolveProviderId(user));
+        consentEntity.setStorageProviderId(new StorageId(userId).getProviderId());
         em.persist(consentEntity);
         em.flush();
 
@@ -280,15 +274,15 @@ public class JpaUserFederatedStorageProvider implements
     }
 
     @Override
-    public UserConsentModel getConsentByClient(RealmModel realm, UserModel user, String clientInternalId) {
-        FederatedUserConsentEntity entity = getGrantedConsentEntity(user, clientInternalId);
+    public UserConsentModel getConsentByClient(RealmModel realm, String userId, String clientInternalId) {
+        FederatedUserConsentEntity entity = getGrantedConsentEntity(userId, clientInternalId);
         return toConsentModel(realm, entity);
     }
 
     @Override
-    public List<UserConsentModel> getConsents(RealmModel realm, UserModel user) {
+    public List<UserConsentModel> getConsents(RealmModel realm, String userId) {
         TypedQuery<FederatedUserConsentEntity> query = em.createNamedQuery("userFederatedConsentsByUser", FederatedUserConsentEntity.class);
-        query.setParameter("userId", user.getId());
+        query.setParameter("userId", userId);
         List<FederatedUserConsentEntity> results = query.getResultList();
 
         List<UserConsentModel> consents = new ArrayList<UserConsentModel>();
@@ -300,13 +294,13 @@ public class JpaUserFederatedStorageProvider implements
     }
 
     @Override
-    public void updateConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
-        createIndex(realm, user);
+    public void updateConsent(RealmModel realm, String userId, UserConsentModel consent) {
+        createIndex(realm, userId);
         String clientId = consent.getClient().getId();
 
-        FederatedUserConsentEntity consentEntity = getGrantedConsentEntity(user, clientId);
+        FederatedUserConsentEntity consentEntity = getGrantedConsentEntity(userId, clientId);
         if (consentEntity == null) {
-            throw new ModelException("Consent not found for client [" + clientId + "] and user [" + user.getId() + "]");
+            throw new ModelException("Consent not found for client [" + clientId + "] and user [" + userId + "]");
         }
 
         updateGrantedConsentEntity(consentEntity, consent);
@@ -314,8 +308,8 @@ public class JpaUserFederatedStorageProvider implements
     }
 
     @Override
-    public boolean revokeConsentForClient(RealmModel realm, UserModel user, String clientInternalId) {
-        FederatedUserConsentEntity consentEntity = getGrantedConsentEntity(user, clientInternalId);
+    public boolean revokeConsentForClient(RealmModel realm, String userId, String clientInternalId) {
+        FederatedUserConsentEntity consentEntity = getGrantedConsentEntity(userId, clientInternalId);
         if (consentEntity == null) return false;
 
         em.remove(consentEntity);
@@ -323,13 +317,13 @@ public class JpaUserFederatedStorageProvider implements
         return true;
     }
 
-    private FederatedUserConsentEntity getGrantedConsentEntity(UserModel user, String clientId) {
+    private FederatedUserConsentEntity getGrantedConsentEntity(String userId, String clientId) {
         TypedQuery<FederatedUserConsentEntity> query = em.createNamedQuery("userFederatedConsentByUserAndClient", FederatedUserConsentEntity.class);
-        query.setParameter("userId", user.getId());
+        query.setParameter("userId", userId);
         query.setParameter("clientId", clientId);
         List<FederatedUserConsentEntity> results = query.getResultList();
         if (results.size() > 1) {
-            throw new ModelException("More results found for user [" + user.getUsername() + "] and client [" + clientId + "]");
+            throw new ModelException("More results found for user [" + userId + "] and client [" + clientId + "]");
         } else if (results.size() == 1) {
             return results.get(0);
         } else {
@@ -423,10 +417,10 @@ public class JpaUserFederatedStorageProvider implements
 
 
     @Override
-    public Set<GroupModel> getGroups(RealmModel realm, UserModel user) {
+    public Set<GroupModel> getGroups(RealmModel realm, String userId) {
         Set<GroupModel> set = new HashSet<>();
         TypedQuery<FederatedUserGroupMembershipEntity> query = em.createNamedQuery("feduserGroupMembership", FederatedUserGroupMembershipEntity.class);
-        query.setParameter("userId", user.getId());
+        query.setParameter("userId", userId);
         List<FederatedUserGroupMembershipEntity> results = query.getResultList();
         if (results.size() == 0) return set;
         for (FederatedUserGroupMembershipEntity entity : results) {
@@ -437,30 +431,24 @@ public class JpaUserFederatedStorageProvider implements
     }
 
     @Override
-    public void joinGroup(RealmModel realm, UserModel user, GroupModel group) {
-        if (isMemberOf(realm, user, group)) return;
-        createIndex(realm, user);
+    public void joinGroup(RealmModel realm, String userId, GroupModel group) {
+        createIndex(realm, userId);
         FederatedUserGroupMembershipEntity entity = new FederatedUserGroupMembershipEntity();
-        entity.setUserId(user.getId());
-        entity.setStorageProviderId(StorageId.resolveProviderId(user));
+        entity.setUserId(userId);
+        entity.setStorageProviderId(new StorageId(userId).getProviderId());
         entity.setGroupId(group.getId());
         entity.setRealmId(realm.getId());
         em.persist(entity);
 
     }
 
-    public boolean isMemberOf(RealmModel realm, UserModel user, GroupModel group) {
-        Set<GroupModel> roles = user.getGroups();
-        return KeycloakModelUtils.isMember(roles, group);
-    }
-
 
     @Override
-    public void leaveGroup(RealmModel realm, UserModel user, GroupModel group) {
-        if (user == null || group == null) return;
+    public void leaveGroup(RealmModel realm, String userId, GroupModel group) {
+        if (userId == null || group == null) return;
 
         TypedQuery<FederatedUserGroupMembershipEntity> query1 = em.createNamedQuery("feduserMemberOf", FederatedUserGroupMembershipEntity.class);
-        query1.setParameter("userId", user.getId());
+        query1.setParameter("userId", userId);
         query1.setParameter("groupId", group.getId());
         TypedQuery<FederatedUserGroupMembershipEntity> query = query1;
         List<FederatedUserGroupMembershipEntity> results = query.getResultList();
@@ -483,9 +471,9 @@ public class JpaUserFederatedStorageProvider implements
     }
 
     @Override
-    public Set<String> getRequiredActions(RealmModel realm, UserModel user) {
+    public Set<String> getRequiredActions(RealmModel realm, String userId) {
         Set<String> set = new HashSet<>();
-        List<FederatedUserRequiredActionEntity> values = getRequiredActionEntities(realm, user);
+        List<FederatedUserRequiredActionEntity> values = getRequiredActionEntities(realm, userId);
         for (FederatedUserRequiredActionEntity entity : values) {
             set.add(entity.getAction());
         }
@@ -494,29 +482,28 @@ public class JpaUserFederatedStorageProvider implements
 
     }
 
-    private List<FederatedUserRequiredActionEntity> getRequiredActionEntities(RealmModel realm, UserModel user) {
+    private List<FederatedUserRequiredActionEntity> getRequiredActionEntities(RealmModel realm, String userId) {
         TypedQuery<FederatedUserRequiredActionEntity> query = em.createNamedQuery("getFederatedUserRequiredActionsByUser", FederatedUserRequiredActionEntity.class)
-                .setParameter("userId", user.getId())
+                .setParameter("userId", userId)
                 .setParameter("realmId", realm.getId());
         return query.getResultList();
     }
 
     @Override
-    public void addRequiredAction(RealmModel realm, UserModel user, String action) {
-        createIndex(realm, user);
-        if (user.getRequiredActions().contains(action)) return;
+    public void addRequiredAction(RealmModel realm, String userId, String action) {
+        createIndex(realm, userId);
         FederatedUserRequiredActionEntity entity = new FederatedUserRequiredActionEntity();
-        entity.setUserId(user.getId());
+        entity.setUserId(userId);
         entity.setRealmId(realm.getId());
-        entity.setStorageProviderId(StorageId.resolveProviderId(user));
+        entity.setStorageProviderId(new StorageId(userId).getProviderId());
         entity.setAction(action);
         em.persist(entity);
 
     }
 
     @Override
-    public void removeRequiredAction(RealmModel realm, UserModel user, String action) {
-        List<FederatedUserRequiredActionEntity> values = getRequiredActionEntities(realm, user);
+    public void removeRequiredAction(RealmModel realm, String userId, String action) {
+        List<FederatedUserRequiredActionEntity> values = getRequiredActionEntities(realm, userId);
         for (FederatedUserRequiredActionEntity entity : values) {
             if (action.equals(entity.getAction())) em.remove(entity);
         }
@@ -525,12 +512,11 @@ public class JpaUserFederatedStorageProvider implements
     }
 
     @Override
-    public void grantRole(RealmModel realm, UserModel user, RoleModel role) {
-        if (user.hasRole(role)) return;
-        createIndex(realm, user);
+    public void grantRole(RealmModel realm, String userId, RoleModel role) {
+        createIndex(realm, userId);
         FederatedUserRoleMappingEntity entity = new FederatedUserRoleMappingEntity();
-        entity.setUserId(user.getId());
-        entity.setStorageProviderId(StorageId.resolveProviderId(user));
+        entity.setUserId(userId);
+        entity.setStorageProviderId(new StorageId(userId).getProviderId());
         entity.setRealmId(realm.getId());
         entity.setRoleId(role.getId());
         em.persist(entity);
@@ -538,10 +524,10 @@ public class JpaUserFederatedStorageProvider implements
     }
 
     @Override
-    public Set<RoleModel> getRoleMappings(RealmModel realm, UserModel user) {
+    public Set<RoleModel> getRoleMappings(RealmModel realm, String userId) {
         Set<RoleModel> set = new HashSet<>();
         TypedQuery<FederatedUserRoleMappingEntity> query = em.createNamedQuery("feduserRoleMappings", FederatedUserRoleMappingEntity.class);
-        query.setParameter("userId", user.getId());
+        query.setParameter("userId", userId);
         List<FederatedUserRoleMappingEntity> results = query.getResultList();
         if (results.size() == 0) return set;
         for (FederatedUserRoleMappingEntity entity : results) {
@@ -552,9 +538,9 @@ public class JpaUserFederatedStorageProvider implements
     }
 
     @Override
-    public void deleteRoleMapping(RealmModel realm, UserModel user, RoleModel role) {
+    public void deleteRoleMapping(RealmModel realm, String userId, RoleModel role) {
         TypedQuery<FederatedUserRoleMappingEntity> query = em.createNamedQuery("feduserRoleMappings", FederatedUserRoleMappingEntity.class);
-        query.setParameter("userId", user.getId());
+        query.setParameter("userId", userId);
         List<FederatedUserRoleMappingEntity> results = query.getResultList();
         for (FederatedUserRoleMappingEntity entity : results) {
             if (entity.getRoleId().equals(role.getId())) em.remove(entity);
@@ -564,10 +550,10 @@ public class JpaUserFederatedStorageProvider implements
     }
 
     @Override
-    public void updateCredential(RealmModel realm, UserModel user, CredentialModel cred) {
+    public void updateCredential(RealmModel realm, String userId, CredentialModel cred) {
         FederatedUserCredentialEntity entity = em.find(FederatedUserCredentialEntity.class, cred.getId());
         if (entity == null) return;
-        createIndex(realm, user);
+        createIndex(realm, userId);
         entity.setAlgorithm(cred.getAlgorithm());
         entity.setCounter(cred.getCounter());
         entity.setCreatedDate(cred.getCreatedDate());
@@ -618,8 +604,8 @@ public class JpaUserFederatedStorageProvider implements
     }
 
     @Override
-    public CredentialModel createCredential(RealmModel realm, UserModel user, CredentialModel cred) {
-        createIndex(realm, user);
+    public CredentialModel createCredential(RealmModel realm, String userId, CredentialModel cred) {
+        createIndex(realm, userId);
         FederatedUserCredentialEntity entity = new FederatedUserCredentialEntity();
         String id = cred.getId() == null ? KeycloakModelUtils.generateId() : cred.getId();
         entity.setId(id);
@@ -633,9 +619,9 @@ public class JpaUserFederatedStorageProvider implements
         entity.setSalt(cred.getSalt());
         entity.setType(cred.getType());
         entity.setValue(cred.getValue());
-        entity.setUserId(user.getId());
+        entity.setUserId(userId);
         entity.setRealmId(realm.getId());
-        entity.setStorageProviderId(StorageId.resolveProviderId(user));
+        entity.setStorageProviderId(new StorageId(userId).getProviderId());
         em.persist(entity);
         MultivaluedHashMap<String, String> config = cred.getConfig();
         if (config != null && !config.isEmpty()) {
@@ -658,7 +644,7 @@ public class JpaUserFederatedStorageProvider implements
     }
 
     @Override
-    public boolean removeStoredCredential(RealmModel realm, UserModel user, String id) {
+    public boolean removeStoredCredential(RealmModel realm, String userId, String id) {
         FederatedUserCredentialEntity entity = em.find(FederatedUserCredentialEntity.class, id);
         if (entity == null) return false;
         em.remove(entity);
@@ -666,7 +652,7 @@ public class JpaUserFederatedStorageProvider implements
     }
 
     @Override
-    public CredentialModel getStoredCredentialById(RealmModel realm, UserModel user, String id) {
+    public CredentialModel getStoredCredentialById(RealmModel realm, String userId, String id) {
         FederatedUserCredentialEntity entity = em.find(FederatedUserCredentialEntity.class, id);
         if (entity == null) return null;
         CredentialModel model = toModel(entity);
@@ -695,9 +681,9 @@ public class JpaUserFederatedStorageProvider implements
     }
 
     @Override
-    public List<CredentialModel> getStoredCredentials(RealmModel realm, UserModel user) {
+    public List<CredentialModel> getStoredCredentials(RealmModel realm, String userId) {
         TypedQuery<FederatedUserCredentialEntity> query = em.createNamedQuery("federatedUserCredentialByUser", FederatedUserCredentialEntity.class)
-                .setParameter("userId", user.getId());
+                .setParameter("userId", userId);
         List<FederatedUserCredentialEntity> results = query.getResultList();
         List<CredentialModel> rtn = new LinkedList<>();
         for (FederatedUserCredentialEntity entity : results) {
@@ -707,10 +693,10 @@ public class JpaUserFederatedStorageProvider implements
     }
 
     @Override
-    public List<CredentialModel> getStoredCredentialsByType(RealmModel realm, UserModel user, String type) {
+    public List<CredentialModel> getStoredCredentialsByType(RealmModel realm, String userId, String type) {
         TypedQuery<FederatedUserCredentialEntity> query = em.createNamedQuery("federatedUserCredentialByUserAndType", FederatedUserCredentialEntity.class)
                 .setParameter("type", type)
-                .setParameter("userId", user.getId());
+                .setParameter("userId", userId);
         List<FederatedUserCredentialEntity> results = query.getResultList();
         List<CredentialModel> rtn = new LinkedList<>();
         for (FederatedUserCredentialEntity entity : results) {
@@ -720,11 +706,11 @@ public class JpaUserFederatedStorageProvider implements
     }
 
     @Override
-    public CredentialModel getStoredCredentialByNameAndType(RealmModel realm, UserModel user, String name, String type) {
+    public CredentialModel getStoredCredentialByNameAndType(RealmModel realm, String userId, String name, String type) {
         TypedQuery<FederatedUserCredentialEntity> query = em.createNamedQuery("federatedUserCredentialByNameAndType", FederatedUserCredentialEntity.class)
                 .setParameter("type", type)
                 .setParameter("device", name)
-                .setParameter("userId", user.getId());
+                .setParameter("userId", userId);
         List<FederatedUserCredentialEntity> results = query.getResultList();
         if (results.isEmpty()) return null;
         return toModel(results.get(0));
@@ -734,12 +720,55 @@ public class JpaUserFederatedStorageProvider implements
     public List<String> getStoredUsers(RealmModel realm, int first, int max) {
         TypedQuery<String> query = em.createNamedQuery("getFederatedUserIds", String.class)
                 .setParameter("realmId", realm.getId())
-                .setFirstResult(first)
-                .setMaxResults(max);
+                .setFirstResult(first);
+        if (max > 0) query.setMaxResults(max);
         return query.getResultList();
     }
 
     @Override
+    public void updateCredential(RealmModel realm, UserModel user, CredentialModel cred) {
+        updateCredential(realm, user.getId(), cred);
+    }
+
+    @Override
+    public CredentialModel createCredential(RealmModel realm, UserModel user, CredentialModel cred) {
+        return createCredential(realm, user.getId(), cred);
+    }
+
+    @Override
+    public boolean removeStoredCredential(RealmModel realm, UserModel user, String id) {
+        return removeStoredCredential(realm, user.getId(), id);
+    }
+
+    @Override
+    public CredentialModel getStoredCredentialById(RealmModel realm, UserModel user, String id) {
+        return getStoredCredentialById(realm, user.getId(), id);
+    }
+
+    @Override
+    public List<CredentialModel> getStoredCredentials(RealmModel realm, UserModel user) {
+        return getStoredCredentials(realm, user.getId());
+    }
+
+    @Override
+    public List<CredentialModel> getStoredCredentialsByType(RealmModel realm, UserModel user, String type) {
+        return getStoredCredentialsByType(realm, user.getId(), type);
+    }
+
+    @Override
+    public CredentialModel getStoredCredentialByNameAndType(RealmModel realm, UserModel user, String name, String type) {
+        return getStoredCredentialByNameAndType(realm, user.getId(), name, type);
+    }
+
+    @Override
+    public int getStoredUsersCount(RealmModel realm) {
+        Object count = em.createNamedQuery("getFederatedUserCount")
+                .setParameter("realmId", realm.getId())
+                .getSingleResult();
+        return ((Number)count).intValue();
+    }
+
+    @Override
     public void preRemove(RealmModel realm) {
         int num = em.createNamedQuery("deleteFederatedUserConsentRolesByRealm")
                 .setParameter("realmId", realm.getId()).executeUpdate();
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 af1b6be..7b46c0c 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
@@ -519,16 +519,16 @@ public class MongoUserProvider implements UserProvider, UserCredentialStore {
     }
 
     @Override
-    public void addConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
+    public void addConsent(RealmModel realm, String userId, UserConsentModel consent) {
         String clientId = consent.getClient().getId();
-        if (getConsentEntityByClientId(user, clientId) != null) {
-            throw new ModelDuplicateException("Consent already exists for client [" + clientId + "] and user [" + user.getId() + "]");
+        if (getConsentEntityByClientId(userId, clientId) != null) {
+            throw new ModelDuplicateException("Consent already exists for client [" + clientId + "] and user [" + userId + "]");
         }
 
         long currentTime = Time.currentTimeMillis();
 
         MongoUserConsentEntity consentEntity = new MongoUserConsentEntity();
-        consentEntity.setUserId(user.getId());
+        consentEntity.setUserId(userId);
         consentEntity.setClientId(clientId);
         consentEntity.setCreatedDate(currentTime);
         consentEntity.setLastUpdatedDate(currentTime);
@@ -537,17 +537,17 @@ public class MongoUserProvider implements UserProvider, UserCredentialStore {
     }
 
     @Override
-    public UserConsentModel getConsentByClient(RealmModel realm, UserModel user, String clientId) {
-        UserConsentEntity consentEntity = getConsentEntityByClientId(user, clientId);
+    public UserConsentModel getConsentByClient(RealmModel realm, String userId, String clientId) {
+        UserConsentEntity consentEntity = getConsentEntityByClientId(userId, clientId);
         return consentEntity!=null ? toConsentModel(realm, consentEntity) : null;
     }
 
     @Override
-    public List<UserConsentModel> getConsents(RealmModel realm, UserModel user) {
+    public List<UserConsentModel> getConsents(RealmModel realm, String userId) {
         List<UserConsentModel> result = new ArrayList<UserConsentModel>();
 
         DBObject query = new QueryBuilder()
-                .and("userId").is(user.getId())
+                .and("userId").is(userId)
                 .get();
         List<MongoUserConsentEntity> grantedConsents = getMongoStore().loadEntities(MongoUserConsentEntity.class, query, invocationContext);
 
@@ -559,9 +559,9 @@ public class MongoUserProvider implements UserProvider, UserCredentialStore {
         return result;
     }
 
-    private MongoUserConsentEntity getConsentEntityByClientId(UserModel user, String clientId) {
+    private MongoUserConsentEntity getConsentEntityByClientId(String userId, String clientId) {
         DBObject query = new QueryBuilder()
-                .and("userId").is(user.getId())
+                .and("userId").is(userId)
                 .and("clientId").is(clientId)
                 .get();
         return getMongoStore().loadSingleEntity(MongoUserConsentEntity.class, query, invocationContext);
@@ -607,11 +607,11 @@ public class MongoUserProvider implements UserProvider, UserCredentialStore {
     }
 
     @Override
-    public void updateConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
+    public void updateConsent(RealmModel realm, String userId, UserConsentModel consent) {
         String clientId = consent.getClient().getId();
-        MongoUserConsentEntity consentEntity = getConsentEntityByClientId(user, clientId);
+        MongoUserConsentEntity consentEntity = getConsentEntityByClientId(userId, clientId);
         if (consentEntity == null) {
-            throw new ModelException("Consent not found for client [" + clientId + "] and user [" + user.getId() + "]");
+            throw new ModelException("Consent not found for client [" + clientId + "] and user [" + userId + "]");
         } else {
             fillEntityFromModel(consent, consentEntity);
             getMongoStore().updateEntity(consentEntity, invocationContext);
@@ -619,8 +619,8 @@ public class MongoUserProvider implements UserProvider, UserCredentialStore {
     }
 
     @Override
-    public boolean revokeConsentForClient(RealmModel realm, UserModel user, String clientId) {
-        MongoUserConsentEntity entity = getConsentEntityByClientId(user, clientId);
+    public boolean revokeConsentForClient(RealmModel realm, String userId, String clientId) {
+        MongoUserConsentEntity entity = getConsentEntityByClientId(userId, clientId);
         if (entity == null) {
             return false;
         }
diff --git a/model/mongo/src/main/java/org/keycloak/storage/mongo/MongoUserFederatedStorageProvider.java b/model/mongo/src/main/java/org/keycloak/storage/mongo/MongoUserFederatedStorageProvider.java
index ec970bf..adc681e 100644
--- a/model/mongo/src/main/java/org/keycloak/storage/mongo/MongoUserFederatedStorageProvider.java
+++ b/model/mongo/src/main/java/org/keycloak/storage/mongo/MongoUserFederatedStorageProvider.java
@@ -64,12 +64,6 @@ import java.util.Set;
  */
 public class MongoUserFederatedStorageProvider implements
         UserFederatedStorageProvider,
-        UserAttributeFederatedStorage,
-        UserBrokerLinkFederatedStorage,
-        UserConsentFederatedStorage,
-        UserGroupMembershipFederatedStorage,
-        UserRequiredActionsFederatedStorage,
-        UserRoleMappingsFederatedStorage,
         UserCredentialStore {
 
     private final MongoStoreInvocationContext invocationContext;
@@ -108,8 +102,8 @@ public class MongoUserFederatedStorageProvider implements
 
 
     @Override
-    public boolean removeStoredCredential(RealmModel realm, UserModel user, String id) {
-        FederatedUser userEntity = getUserById(user.getId());
+    public boolean removeStoredCredential(RealmModel realm, String userId, String id) {
+        FederatedUser userEntity = getUserById(userId);
         if (userEntity == null) return false;
         CredentialEntity ce = getCredentialEntity(id, userEntity);
         if (ce != null) return getMongoStore().pullItemFromList(userEntity, "credentials", ce, invocationContext);
@@ -153,7 +147,7 @@ public class MongoUserFederatedStorageProvider implements
     }
 
     @Override
-    public CredentialModel getStoredCredentialById(RealmModel realm, UserModel user, String id) {
+    public CredentialModel getStoredCredentialById(RealmModel realm, String userId, String id) {
         FederatedUser userEntity = getUserById(id);
         if (userEntity != null && userEntity.getCredentials() != null) {
             for (CredentialEntity credentialEntity : userEntity.getCredentials()) {
@@ -167,8 +161,8 @@ public class MongoUserFederatedStorageProvider implements
     }
 
     @Override
-    public List<CredentialModel> getStoredCredentials(RealmModel realm, UserModel user) {
-        FederatedUser userEntity = getUserById(user.getId());
+    public List<CredentialModel> getStoredCredentials(RealmModel realm, String userId) {
+        FederatedUser userEntity = getUserById(userId);
         if (userEntity != null && userEntity.getCredentials() != null) {
             List<CredentialModel> list = new LinkedList<>();
             for (CredentialEntity credentialEntity : userEntity.getCredentials()) {
@@ -180,8 +174,8 @@ public class MongoUserFederatedStorageProvider implements
     }
 
     @Override
-    public List<CredentialModel> getStoredCredentialsByType(RealmModel realm, UserModel user, String type) {
-        FederatedUser userEntity = getUserById(user.getId());
+    public List<CredentialModel> getStoredCredentialsByType(RealmModel realm, String userId, String type) {
+        FederatedUser userEntity = getUserById(userId);
         if (userEntity != null && userEntity.getCredentials() != null) {
             List<CredentialModel> list = new LinkedList<>();
             for (CredentialEntity credentialEntity : userEntity.getCredentials()) {
@@ -193,8 +187,8 @@ public class MongoUserFederatedStorageProvider implements
     }
 
     @Override
-    public CredentialModel getStoredCredentialByNameAndType(RealmModel realm, UserModel user, String name, String type) {
-        FederatedUser userEntity = getUserById(user.getId());
+    public CredentialModel getStoredCredentialByNameAndType(RealmModel realm, String userId, String name, String type) {
+        FederatedUser userEntity = getUserById(userId);
         if (userEntity != null && userEntity.getCredentials() != null) {
             for (CredentialEntity credentialEntity : userEntity.getCredentials()) {
                 if (credentialEntity.getDevice().equals(name) && type.equals(credentialEntity.getType())) {
@@ -285,8 +279,8 @@ public class MongoUserFederatedStorageProvider implements
     }
 
     @Override
-    public void setSingleAttribute(RealmModel realm, UserModel user, String name, String value) {
-        FederatedUser userEntity = findOrCreate(realm, user.getId());
+    public void setSingleAttribute(RealmModel realm, String userId, String name, String value) {
+        FederatedUser userEntity = findOrCreate(realm, userId);
         if (userEntity.getAttributes() == null) {
             userEntity.setAttributes(new HashMap<>());
         }
@@ -298,8 +292,8 @@ public class MongoUserFederatedStorageProvider implements
     }
 
     @Override
-    public void setAttribute(RealmModel realm, UserModel user, String name, List<String> values) {
-        FederatedUser userEntity = findOrCreate(realm, user.getId());
+    public void setAttribute(RealmModel realm, String userId, String name, List<String> values) {
+        FederatedUser userEntity = findOrCreate(realm, userId);
         if (userEntity.getAttributes() == null) {
             userEntity.setAttributes(new HashMap<>());
         }
@@ -310,8 +304,8 @@ public class MongoUserFederatedStorageProvider implements
     }
 
     @Override
-    public void removeAttribute(RealmModel realm, UserModel user, String name) {
-        FederatedUser userEntity = getUserById(user.getId());
+    public void removeAttribute(RealmModel realm, String userId, String name) {
+        FederatedUser userEntity = getUserById(userId);
         if (userEntity == null || userEntity.getAttributes() == null) return;
 
         userEntity.getAttributes().remove(name);
@@ -319,8 +313,8 @@ public class MongoUserFederatedStorageProvider implements
     }
 
     @Override
-    public MultivaluedHashMap<String, String> getAttributes(RealmModel realm, UserModel user) {
-        FederatedUser userEntity = getUserById(user.getId());
+    public MultivaluedHashMap<String, String> getAttributes(RealmModel realm, String userId) {
+        FederatedUser userEntity = getUserById(userId);
         if (userEntity == null || userEntity.getAttributes() == null) return new MultivaluedHashMap<>();
         MultivaluedHashMap<String, String> result = new MultivaluedHashMap<>();
         result.putAll(userEntity.getAttributes());
@@ -351,8 +345,8 @@ public class MongoUserFederatedStorageProvider implements
     }
 
     @Override
-    public void addFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel socialLink) {
-        FederatedUser userEntity = findOrCreate(realm, user.getId());
+    public void addFederatedIdentity(RealmModel realm, String userId, FederatedIdentityModel socialLink) {
+        FederatedUser userEntity = findOrCreate(realm, userId);
         FederatedIdentityEntity federatedIdentityEntity = new FederatedIdentityEntity();
         federatedIdentityEntity.setIdentityProvider(socialLink.getIdentityProvider());
         federatedIdentityEntity.setUserId(socialLink.getUserId());
@@ -363,8 +357,8 @@ public class MongoUserFederatedStorageProvider implements
     }
 
     @Override
-    public boolean removeFederatedIdentity(RealmModel realm, UserModel user, String socialProvider) {
-        FederatedUser userEntity = getUserById(user.getId());
+    public boolean removeFederatedIdentity(RealmModel realm, String userId, String socialProvider) {
+        FederatedUser userEntity = getUserById(userId);
         if (userEntity == null) return false;
 
         FederatedIdentityEntity federatedIdentityEntity = findFederatedIdentityLink(userEntity, socialProvider);
@@ -388,8 +382,8 @@ public class MongoUserFederatedStorageProvider implements
     }
 
     @Override
-    public void updateFederatedIdentity(RealmModel realm, UserModel federatedUser, FederatedIdentityModel federatedIdentityModel) {
-        FederatedUser userEntity = getUserById(federatedUser.getId());
+    public void updateFederatedIdentity(RealmModel realm, String userId, FederatedIdentityModel federatedIdentityModel) {
+        FederatedUser userEntity = getUserById(userId);
         if (userEntity == null) return;
         FederatedIdentityEntity federatedIdentityEntity = findFederatedIdentityLink(userEntity, federatedIdentityModel.getIdentityProvider());
         if (federatedIdentityEntity == null) return;
@@ -401,8 +395,8 @@ public class MongoUserFederatedStorageProvider implements
     }
 
     @Override
-    public Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm) {
-        FederatedUser userEntity = getUserById(user.getId());
+    public Set<FederatedIdentityModel> getFederatedIdentities(String userId, RealmModel realm) {
+        FederatedUser userEntity = getUserById(userId);
         if (userEntity == null) return Collections.EMPTY_SET;
         List<FederatedIdentityEntity> linkEntities = userEntity.getFederatedIdentities();
 
@@ -420,8 +414,8 @@ public class MongoUserFederatedStorageProvider implements
     }
 
     @Override
-    public FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm) {
-        FederatedUser userEntity = getUserById(user.getId());
+    public FederatedIdentityModel getFederatedIdentity(String userId, String socialProvider, RealmModel realm) {
+        FederatedUser userEntity = getUserById(userId);
         if (userEntity == null) return null;
         FederatedIdentityEntity federatedIdentityEntity = findFederatedIdentityLink(userEntity, socialProvider);
 
@@ -430,35 +424,35 @@ public class MongoUserFederatedStorageProvider implements
     }
 
     @Override
-    public void addConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
-        session.userLocalStorage().addConsent(realm, user, consent);
+    public void addConsent(RealmModel realm, String userId, UserConsentModel consent) {
+        session.userLocalStorage().addConsent(realm, userId, consent);
 
     }
 
     @Override
-    public UserConsentModel getConsentByClient(RealmModel realm, UserModel user, String clientInternalId) {
-        return session.userLocalStorage().getConsentByClient(realm, user, clientInternalId);
+    public UserConsentModel getConsentByClient(RealmModel realm, String userId, String clientInternalId) {
+        return session.userLocalStorage().getConsentByClient(realm, userId, clientInternalId);
     }
 
     @Override
-    public List<UserConsentModel> getConsents(RealmModel realm, UserModel user) {
-        return session.userLocalStorage().getConsents(realm, user);
+    public List<UserConsentModel> getConsents(RealmModel realm, String userId) {
+        return session.userLocalStorage().getConsents(realm, userId);
     }
 
     @Override
-    public void updateConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
-        session.userLocalStorage().updateConsent(realm, user, consent);
+    public void updateConsent(RealmModel realm, String userId, UserConsentModel consent) {
+        session.userLocalStorage().updateConsent(realm, userId, consent);
 
     }
 
     @Override
-    public boolean revokeConsentForClient(RealmModel realm, UserModel user, String clientInternalId) {
-        return session.userLocalStorage().revokeConsentForClient(realm, user, clientInternalId);
+    public boolean revokeConsentForClient(RealmModel realm, String userId, String clientInternalId) {
+        return session.userLocalStorage().revokeConsentForClient(realm, userId, clientInternalId);
     }
 
     @Override
-    public void updateCredential(RealmModel realm, UserModel user, CredentialModel cred) {
-        FederatedUser userEntity = getUserById(user.getId());
+    public void updateCredential(RealmModel realm, String userId, CredentialModel cred) {
+        FederatedUser userEntity = getUserById(userId);
         if (userEntity == null) return;
         CredentialEntity entity = getCredentialEntity(cred.getId(), userEntity);
         if (entity == null) return;
@@ -489,8 +483,8 @@ public class MongoUserFederatedStorageProvider implements
     }
 
     @Override
-    public CredentialModel createCredential(RealmModel realm, UserModel user, CredentialModel cred) {
-        FederatedUser userEntity = findOrCreate(realm, user.getId());
+    public CredentialModel createCredential(RealmModel realm, String userId, CredentialModel cred) {
+        FederatedUser userEntity = findOrCreate(realm, userId);
         CredentialEntity entity = new CredentialEntity();
         entity.setId(KeycloakModelUtils.generateId());
         toEntity(cred, entity);
@@ -500,8 +494,8 @@ public class MongoUserFederatedStorageProvider implements
     }
 
     @Override
-    public Set<GroupModel> getGroups(RealmModel realm, UserModel user) {
-        FederatedUser userEntity = getUserById(user.getId());
+    public Set<GroupModel> getGroups(RealmModel realm, String userId) {
+        FederatedUser userEntity = getUserById(userId);
         if (userEntity == null || userEntity.getGroupIds() == null || userEntity.getGroupIds().isEmpty()) return Collections.EMPTY_SET;
         Set<GroupModel> groups = new HashSet<>();
         for (String groupId : userEntity.getGroupIds()) {
@@ -513,16 +507,16 @@ public class MongoUserFederatedStorageProvider implements
     }
 
     @Override
-    public void joinGroup(RealmModel realm, UserModel user, GroupModel group) {
-        FederatedUser userEntity = findOrCreate(realm, user.getId());
+    public void joinGroup(RealmModel realm, String userId, GroupModel group) {
+        FederatedUser userEntity = findOrCreate(realm, userId);
         getMongoStore().pushItemToList(userEntity, "groupIds", group.getId(), true, invocationContext);
 
 
     }
 
     @Override
-    public void leaveGroup(RealmModel realm, UserModel user, GroupModel group) {
-        FederatedUser userEntity = getUserById(user.getId());
+    public void leaveGroup(RealmModel realm, String userId, GroupModel group) {
+        FederatedUser userEntity = getUserById(userId);
         if (userEntity == null || group == null) return;
         getMongoStore().pullItemFromList(userEntity, "groupIds", group.getId(), invocationContext);
 
@@ -542,8 +536,8 @@ public class MongoUserFederatedStorageProvider implements
     }
 
     @Override
-    public Set<String> getRequiredActions(RealmModel realm, UserModel user) {
-        FederatedUser userEntity = getUserById(user.getId());
+    public Set<String> getRequiredActions(RealmModel realm, String userId) {
+        FederatedUser userEntity = getUserById(userId);
         if (userEntity == null || userEntity.getRequiredActions() == null || userEntity.getRequiredActions().isEmpty()) return Collections.EMPTY_SET;
         Set<String> set = new HashSet<>();
         set.addAll(userEntity.getRequiredActions());
@@ -551,30 +545,30 @@ public class MongoUserFederatedStorageProvider implements
     }
 
     @Override
-    public void addRequiredAction(RealmModel realm, UserModel user, String action) {
-        FederatedUser userEntity = findOrCreate(realm, user.getId());
+    public void addRequiredAction(RealmModel realm, String userId, String action) {
+        FederatedUser userEntity = findOrCreate(realm, userId);
         getMongoStore().pushItemToList(userEntity, "requiredActions", action, true, invocationContext);
 
     }
 
     @Override
-    public void removeRequiredAction(RealmModel realm, UserModel user, String action) {
-        FederatedUser userEntity = getUserById(user.getId());
+    public void removeRequiredAction(RealmModel realm, String userId, String action) {
+        FederatedUser userEntity = getUserById(userId);
         if (userEntity == null || userEntity.getRequiredActions() == null || userEntity.getRequiredActions().isEmpty()) return;
         getMongoStore().pullItemFromList(userEntity, "requiredActions", action, invocationContext);
 
     }
 
     @Override
-    public void grantRole(RealmModel realm, UserModel user, RoleModel role) {
-        FederatedUser userEntity = findOrCreate(realm, user.getId());
+    public void grantRole(RealmModel realm, String userId, RoleModel role) {
+        FederatedUser userEntity = findOrCreate(realm, userId);
         getMongoStore().pushItemToList(userEntity, "roleIds", role.getId(), true, invocationContext);
 
     }
 
     @Override
-    public Set<RoleModel> getRoleMappings(RealmModel realm, UserModel user) {
-        FederatedUser userEntity = getUserById(user.getId());
+    public Set<RoleModel> getRoleMappings(RealmModel realm, String userId) {
+        FederatedUser userEntity = getUserById(userId);
         if (userEntity == null || userEntity.getRoleIds() == null || userEntity.getRoleIds().isEmpty()) return Collections.EMPTY_SET;
         Set<RoleModel> roles = new HashSet<>();
         for (String roleId : userEntity.getRoleIds()) {
@@ -585,10 +579,53 @@ public class MongoUserFederatedStorageProvider implements
     }
 
     @Override
-    public void deleteRoleMapping(RealmModel realm, UserModel user, RoleModel role) {
-        FederatedUser userEntity = getUserById(user.getId());
+    public void deleteRoleMapping(RealmModel realm, String userId, RoleModel role) {
+        FederatedUser userEntity = getUserById(userId);
         if (userEntity == null || userEntity.getRoleIds() == null || userEntity.getRoleIds().isEmpty()) return;
         getMongoStore().pullItemFromList(userEntity, "roleIds", role.getId(), invocationContext);
 
     }
+
+    @Override
+    public void updateCredential(RealmModel realm, UserModel user, CredentialModel cred) {
+        updateCredential(realm, user.getId(), cred);
+    }
+
+    @Override
+    public CredentialModel createCredential(RealmModel realm, UserModel user, CredentialModel cred) {
+        return createCredential(realm, user.getId(), cred);
+    }
+
+    @Override
+    public boolean removeStoredCredential(RealmModel realm, UserModel user, String id) {
+        return removeStoredCredential(realm, user.getId(), id);
+    }
+
+    @Override
+    public CredentialModel getStoredCredentialById(RealmModel realm, UserModel user, String id) {
+        return getStoredCredentialById(realm, user.getId(), id);
+    }
+
+    @Override
+    public List<CredentialModel> getStoredCredentials(RealmModel realm, UserModel user) {
+        return getStoredCredentials(realm, user.getId());
+    }
+
+    @Override
+    public List<CredentialModel> getStoredCredentialsByType(RealmModel realm, UserModel user, String type) {
+        return getStoredCredentialsByType(realm, user.getId(), type);
+    }
+
+    @Override
+    public CredentialModel getStoredCredentialByNameAndType(RealmModel realm, UserModel user, String name, String type) {
+        return getStoredCredentialByNameAndType(realm, user.getId(), name, type);
+    }
+
+    @Override
+    public int getStoredUsersCount(RealmModel realm) {
+        DBObject query = new QueryBuilder()
+                .and("realmId").is(realm.getId())
+                .get();
+        return getMongoStore().countEntities(FederatedUser.class, query, invocationContext);
+    }
 }
diff --git a/server-spi/src/main/java/org/keycloak/models/UserFederationManager.java b/server-spi/src/main/java/org/keycloak/models/UserFederationManager.java
index c722aa4..1765bad 100755
--- a/server-spi/src/main/java/org/keycloak/models/UserFederationManager.java
+++ b/server-spi/src/main/java/org/keycloak/models/UserFederationManager.java
@@ -175,35 +175,30 @@ public class UserFederationManager implements UserProvider {
     }
 
     @Override
-    public void addConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
-        validateUser(realm, user);
-        session.userStorage().addConsent(realm, user, consent);
+    public void addConsent(RealmModel realm, String userId, UserConsentModel consent) {
+        session.userStorage().addConsent(realm, userId, consent);
 
     }
 
     @Override
-    public UserConsentModel getConsentByClient(RealmModel realm, UserModel user, String clientInternalId) {
-        validateUser(realm, user);
-        return session.userStorage().getConsentByClient(realm, user, clientInternalId);
+    public UserConsentModel getConsentByClient(RealmModel realm, String userId, String clientInternalId) {
+        return session.userStorage().getConsentByClient(realm, userId, clientInternalId);
     }
 
     @Override
-    public List<UserConsentModel> getConsents(RealmModel realm, UserModel user) {
-        validateUser(realm, user);
-        return session.userStorage().getConsents(realm, user);
+    public List<UserConsentModel> getConsents(RealmModel realm, String userId) {
+        return session.userStorage().getConsents(realm, userId);
     }
 
     @Override
-    public void updateConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
-        validateUser(realm, user);
-        session.userStorage().updateConsent(realm, user, consent);
+    public void updateConsent(RealmModel realm, String userId, UserConsentModel consent) {
+        session.userStorage().updateConsent(realm, userId, consent);
 
     }
 
     @Override
-    public boolean revokeConsentForClient(RealmModel realm, UserModel user, String clientInternalId) {
-        validateUser(realm, user);
-        return session.userStorage().revokeConsentForClient(realm, user, clientInternalId);
+    public boolean revokeConsentForClient(RealmModel realm, String userId, String clientInternalId) {
+        return session.userStorage().revokeConsentForClient(realm, userId, clientInternalId);
     }
 
     @Override
diff --git a/server-spi/src/main/java/org/keycloak/models/UserProvider.java b/server-spi/src/main/java/org/keycloak/models/UserProvider.java
index 3c796b5..b8b240e 100755
--- a/server-spi/src/main/java/org/keycloak/models/UserProvider.java
+++ b/server-spi/src/main/java/org/keycloak/models/UserProvider.java
@@ -43,11 +43,11 @@ public interface UserProvider extends Provider,
     FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm);
     UserModel getUserByFederatedIdentity(FederatedIdentityModel socialLink, RealmModel realm);
 
-    void addConsent(RealmModel realm, UserModel user, UserConsentModel consent);
-    UserConsentModel getConsentByClient(RealmModel realm, UserModel user, String clientInternalId);
-    List<UserConsentModel> getConsents(RealmModel realm, UserModel user);
-    void updateConsent(RealmModel realm, UserModel user, UserConsentModel consent);
-    boolean revokeConsentForClient(RealmModel realm, UserModel user, String clientInternalId);
+    void addConsent(RealmModel realm, String userId, UserConsentModel consent);
+    UserConsentModel getConsentByClient(RealmModel realm, String userId, String clientInternalId);
+    List<UserConsentModel> getConsents(RealmModel realm, String userId);
+    void updateConsent(RealmModel realm, String userId, UserConsentModel consent);
+    boolean revokeConsentForClient(RealmModel realm, String userId, String clientInternalId);
 
 
     UserModel getServiceAccount(ClientModel client);
diff --git a/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index c5e55a5..f1e4ea7 100755
--- a/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -101,6 +101,7 @@ import org.keycloak.representations.idm.authorization.ResourceOwnerRepresentatio
 import org.keycloak.representations.idm.authorization.ResourceRepresentation;
 import org.keycloak.representations.idm.authorization.ResourceServerRepresentation;
 import org.keycloak.representations.idm.authorization.ScopeRepresentation;
+import org.keycloak.storage.federated.UserFederatedStorageProvider;
 import org.keycloak.util.JsonSerialization;
 
 import java.io.IOException;
@@ -355,6 +356,13 @@ public class RepresentationToModel {
             }
         }
 
+        if (rep.getFederatedUsers() != null) {
+            for (UserRepresentation userRep : rep.getFederatedUsers()) {
+                importFederatedUser(session, newRealm, userRep);
+
+            }
+        }
+
         if(rep.isInternationalizationEnabled() != null){
             newRealm.setInternationalizationEnabled(rep.isInternationalizationEnabled());
         }
@@ -1363,7 +1371,7 @@ public class RepresentationToModel {
         if (userRep.getClientConsents() != null) {
             for (UserConsentRepresentation consentRep : userRep.getClientConsents()) {
                 UserConsentModel consentModel = toModel(newRealm, consentRep);
-                session.userStorage().addConsent(newRealm, user, consentModel);
+                session.userStorage().addConsent(newRealm, user.getId(), consentModel);
             }
         }
         if (userRep.getServiceAccountClientId() != null) {
@@ -1451,6 +1459,32 @@ public class RepresentationToModel {
         return credential;
     }
 
+    public static CredentialModel toModel(CredentialRepresentation cred) {
+        CredentialModel model = new CredentialModel();
+        model.setHashIterations(cred.getHashIterations());
+        model.setCreatedDate(cred.getCreatedDate());
+        model.setType(cred.getType());
+        model.setDigits(cred.getDigits());
+        model.setConfig(cred.getConfig());
+        model.setDevice(cred.getDevice());
+        model.setAlgorithm(cred.getAlgorithm());
+        model.setCounter(cred.getCounter());
+        model.setPeriod(cred.getPeriod());
+        if (cred.getSalt() != null) {
+            try {
+                model.setSalt(Base64.decode(cred.getSalt()));
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+        model.setValue(cred.getValue());
+        if (cred.getHashedSaltedValue() != null) {
+            model.setValue(cred.getHashedSaltedValue());
+        }
+        return model;
+
+    }
+
     // Role mappings
 
     public static void createRoleMappings(UserRepresentation userRep, UserModel user, RealmModel realm) {
@@ -2188,4 +2222,99 @@ public class RepresentationToModel {
 
         return model;
     }
+
+    public static void importFederatedUser(KeycloakSession session, RealmModel newRealm, UserRepresentation userRep) {
+        UserFederatedStorageProvider federatedStorage = session.userFederatedStorage();
+        if (userRep.getAttributes() != null) {
+            for (Map.Entry<String, Object> entry : userRep.getAttributes().entrySet()) {
+                String key = entry.getKey();
+                Object value = entry.getValue();
+                if (value == null) continue;
+
+                if (value instanceof Collection) {
+                    Collection<String> colVal = (Collection<String>) value;
+                    List<String> list = new LinkedList<>();
+                    list.addAll(colVal);
+                    federatedStorage.setAttribute(newRealm, userRep.getId(), key, list);
+                } else if (value instanceof String) {
+                    // TODO: This is here just for backwards compatibility with KC 1.3 and earlier
+                    String stringVal = (String) value;
+                    federatedStorage.setSingleAttribute(newRealm, userRep.getId(), key, stringVal);
+                }
+            }
+        }
+        if (userRep.getRequiredActions() != null) {
+            for (String action: userRep.getRequiredActions()) {
+                federatedStorage.addRequiredAction(newRealm, userRep.getId(), action);
+            }
+        }
+        if (userRep.getCredentials() != null) {
+            for (CredentialRepresentation cred : userRep.getCredentials()) {
+                federatedStorage.createCredential(newRealm, userRep.getId(), toModel(cred));
+            }
+        }
+        createFederatedRoleMappings(federatedStorage, userRep, newRealm);
+
+        if (userRep.getGroups() != null) {
+            for (String path : userRep.getGroups()) {
+                GroupModel group = KeycloakModelUtils.findGroupByPath(newRealm, path);
+                if (group == null) {
+                    throw new RuntimeException("Unable to find group specified by path: " + path);
+
+                }
+                federatedStorage.joinGroup(newRealm, userRep.getId(), group);
+            }
+        }
+
+        if (userRep.getFederatedIdentities() != null) {
+            for (FederatedIdentityRepresentation identity : userRep.getFederatedIdentities()) {
+                FederatedIdentityModel mappingModel = new FederatedIdentityModel(identity.getIdentityProvider(), identity.getUserId(), identity.getUserName());
+                federatedStorage.addFederatedIdentity(newRealm, userRep.getId(), mappingModel);
+            }
+        }
+        if (userRep.getClientConsents() != null) {
+            for (UserConsentRepresentation consentRep : userRep.getClientConsents()) {
+                UserConsentModel consentModel = toModel(newRealm, consentRep);
+                federatedStorage.addConsent(newRealm, userRep.getId(), consentModel);
+            }
+        }
+
+
+    }
+
+    public static void createFederatedRoleMappings(UserFederatedStorageProvider federatedStorage, UserRepresentation userRep, RealmModel realm) {
+        if (userRep.getRealmRoles() != null) {
+            for (String roleString : userRep.getRealmRoles()) {
+                RoleModel role = realm.getRole(roleString.trim());
+                if (role == null) {
+                    role = realm.addRole(roleString.trim());
+                }
+                federatedStorage.grantRole(realm, userRep.getId(), role);
+            }
+        }
+        if (userRep.getClientRoles() != null) {
+            for (Map.Entry<String, List<String>> entry : userRep.getClientRoles().entrySet()) {
+                ClientModel client = realm.getClientByClientId(entry.getKey());
+                if (client == null) {
+                    throw new RuntimeException("Unable to find client role mappings for client: " + entry.getKey());
+                }
+                createFederatedClientRoleMappings(federatedStorage, realm, client, userRep, entry.getValue());
+            }
+        }
+    }
+
+    public static void createFederatedClientRoleMappings(UserFederatedStorageProvider federatedStorage, RealmModel realm, ClientModel clientModel, UserRepresentation userRep, List<String> roleNames) {
+        if (userRep == null) {
+            throw new RuntimeException("User not found");
+        }
+
+        for (String roleName : roleNames) {
+            RoleModel role = clientModel.getRole(roleName.trim());
+            if (role == null) {
+                role = clientModel.addRole(roleName.trim());
+            }
+            federatedStorage.grantRole(realm, userRep.getId(), role);
+
+        }
+    }
 }
diff --git a/server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapterFederatedStorage.java b/server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapterFederatedStorage.java
index ed8759b..865f454 100644
--- a/server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapterFederatedStorage.java
+++ b/server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapterFederatedStorage.java
@@ -70,30 +70,30 @@ public abstract class AbstractUserAdapterFederatedStorage implements UserModel {
 
     @Override
     public Set<String> getRequiredActions() {
-        return getFederatedStorage().getRequiredActions(realm, this);
+        return getFederatedStorage().getRequiredActions(realm, this.getId());
     }
 
     @Override
     public void addRequiredAction(String action) {
-        getFederatedStorage().addRequiredAction(realm, this, action);
+        getFederatedStorage().addRequiredAction(realm, this.getId(), action);
 
     }
 
     @Override
     public void removeRequiredAction(String action) {
-        getFederatedStorage().removeRequiredAction(realm, this, action);
+        getFederatedStorage().removeRequiredAction(realm, this.getId(), action);
 
     }
 
     @Override
     public void addRequiredAction(RequiredAction action) {
-        getFederatedStorage().addRequiredAction(realm, this, action.name());
+        getFederatedStorage().addRequiredAction(realm, this.getId(), action.name());
 
     }
 
     @Override
     public void removeRequiredAction(RequiredAction action) {
-        getFederatedStorage().removeRequiredAction(realm, this, action.name());
+        getFederatedStorage().removeRequiredAction(realm, this.getId(), action.name());
     }
 
     /**
@@ -119,7 +119,7 @@ public abstract class AbstractUserAdapterFederatedStorage implements UserModel {
     @Override
     public Set<GroupModel> getGroups() {
         Set<GroupModel> set = new HashSet<>();
-        set.addAll(getFederatedStorage().getGroups(realm, this));
+        set.addAll(getFederatedStorage().getGroups(realm, this.getId()));
         if (appendDefaultGroups()) set.addAll(realm.getDefaultGroups());
         set.addAll(getGroupsInternal());
         return set;
@@ -127,13 +127,13 @@ public abstract class AbstractUserAdapterFederatedStorage implements UserModel {
 
     @Override
     public void joinGroup(GroupModel group) {
-        getFederatedStorage().joinGroup(realm, this, group);
+        getFederatedStorage().joinGroup(realm, this.getId(), group);
 
     }
 
     @Override
     public void leaveGroup(GroupModel group) {
-        getFederatedStorage().leaveGroup(realm, this, group);
+        getFederatedStorage().leaveGroup(realm, this.getId(), group);
 
     }
 
@@ -183,7 +183,7 @@ public abstract class AbstractUserAdapterFederatedStorage implements UserModel {
 
     @Override
     public void grantRole(RoleModel role) {
-        getFederatedStorage().grantRole(realm, this, role);
+        getFederatedStorage().grantRole(realm, this.getId(), role);
 
     }
 
@@ -212,12 +212,12 @@ public abstract class AbstractUserAdapterFederatedStorage implements UserModel {
     }
 
     protected Set<RoleModel> getFederatedRoleMappings() {
-        return getFederatedStorage().getRoleMappings(realm, this);
+        return getFederatedStorage().getRoleMappings(realm, this.getId());
     }
 
     @Override
     public void deleteRoleMapping(RoleModel role) {
-        getFederatedStorage().deleteRoleMapping(realm, this, role);
+        getFederatedStorage().deleteRoleMapping(realm, this.getId(), role);
 
     }
 
@@ -307,35 +307,35 @@ public abstract class AbstractUserAdapterFederatedStorage implements UserModel {
 
     @Override
     public void setSingleAttribute(String name, String value) {
-        getFederatedStorage().setSingleAttribute(realm, this, name, value);
+        getFederatedStorage().setSingleAttribute(realm, this.getId(), name, value);
 
     }
 
     @Override
     public void removeAttribute(String name) {
-        getFederatedStorage().removeAttribute(realm, this, name);
+        getFederatedStorage().removeAttribute(realm, this.getId(), name);
 
     }
 
     @Override
     public void setAttribute(String name, List<String> values) {
-        getFederatedStorage().setAttribute(realm, this, name, values);
+        getFederatedStorage().setAttribute(realm, this.getId(), name, values);
 
     }
 
     @Override
     public String getFirstAttribute(String name) {
-        return getFederatedStorage().getAttributes(realm, this).getFirst(name);
+        return getFederatedStorage().getAttributes(realm, this.getId()).getFirst(name);
     }
 
     @Override
     public Map<String, List<String>> getAttributes() {
-        return getFederatedStorage().getAttributes(realm, this);
+        return getFederatedStorage().getAttributes(realm, this.getId());
     }
 
     @Override
     public List<String> getAttribute(String name) {
-        return getFederatedStorage().getAttributes(realm, this).get(name);
+        return getFederatedStorage().getAttributes(realm, this.getId()).get(name);
     }
 
     @Override
diff --git a/server-spi/src/main/java/org/keycloak/storage/federated/UserAttributeFederatedStorage.java b/server-spi/src/main/java/org/keycloak/storage/federated/UserAttributeFederatedStorage.java
index 6c04521..28ab594 100644
--- a/server-spi/src/main/java/org/keycloak/storage/federated/UserAttributeFederatedStorage.java
+++ b/server-spi/src/main/java/org/keycloak/storage/federated/UserAttributeFederatedStorage.java
@@ -27,9 +27,9 @@ import java.util.List;
  * @version $Revision: 1 $
  */
 public interface UserAttributeFederatedStorage {
-    void setSingleAttribute(RealmModel realm, UserModel user, String name, String value);
-    void setAttribute(RealmModel realm, UserModel user, String name, List<String> values);
-    void removeAttribute(RealmModel realm, UserModel user, String name);
-    MultivaluedHashMap<String, String> getAttributes(RealmModel realm, UserModel user);
+    void setSingleAttribute(RealmModel realm, String userId, String name, String value);
+    void setAttribute(RealmModel realm, String userId, String name, List<String> values);
+    void removeAttribute(RealmModel realm, String userId, String name);
+    MultivaluedHashMap<String, String> getAttributes(RealmModel realm, String userId);
     List<String> getUsersByUserAttribute(RealmModel realm, String name, String value);
 }
diff --git a/server-spi/src/main/java/org/keycloak/storage/federated/UserBrokerLinkFederatedStorage.java b/server-spi/src/main/java/org/keycloak/storage/federated/UserBrokerLinkFederatedStorage.java
index 6fcbabf..5624061 100644
--- a/server-spi/src/main/java/org/keycloak/storage/federated/UserBrokerLinkFederatedStorage.java
+++ b/server-spi/src/main/java/org/keycloak/storage/federated/UserBrokerLinkFederatedStorage.java
@@ -28,9 +28,9 @@ import java.util.Set;
  */
 public interface UserBrokerLinkFederatedStorage {
     String getUserByFederatedIdentity(FederatedIdentityModel socialLink, RealmModel realm);
-    public void addFederatedIdentity(RealmModel realm, UserModel user, FederatedIdentityModel socialLink);
-    public boolean removeFederatedIdentity(RealmModel realm, UserModel user, String socialProvider);
-    void updateFederatedIdentity(RealmModel realm, UserModel federatedUser, FederatedIdentityModel federatedIdentityModel);
-    Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm);
-    FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm);
+    public void addFederatedIdentity(RealmModel realm, String userId, FederatedIdentityModel socialLink);
+    public boolean removeFederatedIdentity(RealmModel realm, String userId, String socialProvider);
+    void updateFederatedIdentity(RealmModel realm, String userId, FederatedIdentityModel federatedIdentityModel);
+    Set<FederatedIdentityModel> getFederatedIdentities(String userId, RealmModel realm);
+    FederatedIdentityModel getFederatedIdentity(String userId, String socialProvider, RealmModel realm);
 }
diff --git a/server-spi/src/main/java/org/keycloak/storage/federated/UserConsentFederatedStorage.java b/server-spi/src/main/java/org/keycloak/storage/federated/UserConsentFederatedStorage.java
index 7a14b14..21e79ca 100644
--- a/server-spi/src/main/java/org/keycloak/storage/federated/UserConsentFederatedStorage.java
+++ b/server-spi/src/main/java/org/keycloak/storage/federated/UserConsentFederatedStorage.java
@@ -27,9 +27,9 @@ import java.util.List;
  * @version $Revision: 1 $
  */
 public interface UserConsentFederatedStorage {
-    void addConsent(RealmModel realm, UserModel user, UserConsentModel consent);
-    UserConsentModel getConsentByClient(RealmModel realm, UserModel user, String clientInternalId);
-    List<UserConsentModel> getConsents(RealmModel realm, UserModel user);
-    void updateConsent(RealmModel realm, UserModel user, UserConsentModel consent);
-    boolean revokeConsentForClient(RealmModel realm, UserModel user, String clientInternalId);
+    void addConsent(RealmModel realm, String userId, UserConsentModel consent);
+    UserConsentModel getConsentByClient(RealmModel realm, String userId, String clientInternalId);
+    List<UserConsentModel> getConsents(RealmModel realm, String userId);
+    void updateConsent(RealmModel realm, String userId, UserConsentModel consent);
+    boolean revokeConsentForClient(RealmModel realm, String userId, String clientInternalId);
 }
diff --git a/server-spi/src/main/java/org/keycloak/storage/federated/UserFederatedStorageProvider.java b/server-spi/src/main/java/org/keycloak/storage/federated/UserFederatedStorageProvider.java
index b8d4e35..12847bc 100755
--- a/server-spi/src/main/java/org/keycloak/storage/federated/UserFederatedStorageProvider.java
+++ b/server-spi/src/main/java/org/keycloak/storage/federated/UserFederatedStorageProvider.java
@@ -39,9 +39,11 @@ public interface UserFederatedStorageProvider extends Provider,
         UserConsentFederatedStorage,
         UserGroupMembershipFederatedStorage,
         UserRequiredActionsFederatedStorage,
-        UserRoleMappingsFederatedStorage {
+        UserRoleMappingsFederatedStorage,
+        UserFederatedUserCredentialStore {
 
     List<String> getStoredUsers(RealmModel realm, int first, int max);
+    int getStoredUsersCount(RealmModel realm);
 
     void preRemove(RealmModel realm);
 
diff --git a/server-spi/src/main/java/org/keycloak/storage/federated/UserFederatedUserCredentialStore.java b/server-spi/src/main/java/org/keycloak/storage/federated/UserFederatedUserCredentialStore.java
new file mode 100644
index 0000000..0df895b
--- /dev/null
+++ b/server-spi/src/main/java/org/keycloak/storage/federated/UserFederatedUserCredentialStore.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.storage.federated;
+
+import org.keycloak.credential.CredentialModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.provider.Provider;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface UserFederatedUserCredentialStore extends Provider {
+    void updateCredential(RealmModel realm, String userId, CredentialModel cred);
+    CredentialModel createCredential(RealmModel realm, String userId, CredentialModel cred);
+    boolean removeStoredCredential(RealmModel realm, String userId, String id);
+    CredentialModel getStoredCredentialById(RealmModel realm, String userId, String id);
+    List<CredentialModel> getStoredCredentials(RealmModel realm, String userId);
+    List<CredentialModel> getStoredCredentialsByType(RealmModel realm, String userId, String type);
+    CredentialModel getStoredCredentialByNameAndType(RealmModel realm, String userId, String name, String type);
+}
diff --git a/server-spi/src/main/java/org/keycloak/storage/federated/UserGroupMembershipFederatedStorage.java b/server-spi/src/main/java/org/keycloak/storage/federated/UserGroupMembershipFederatedStorage.java
index dad2399..696ff84 100644
--- a/server-spi/src/main/java/org/keycloak/storage/federated/UserGroupMembershipFederatedStorage.java
+++ b/server-spi/src/main/java/org/keycloak/storage/federated/UserGroupMembershipFederatedStorage.java
@@ -28,9 +28,9 @@ import java.util.Set;
  * @version $Revision: 1 $
  */
 public interface UserGroupMembershipFederatedStorage {
-    Set<GroupModel> getGroups(RealmModel realm, UserModel user);
-    void joinGroup(RealmModel realm,UserModel user, GroupModel group);
-    void leaveGroup(RealmModel realm,UserModel user, GroupModel group);
+    Set<GroupModel> getGroups(RealmModel realm, String userId);
+    void joinGroup(RealmModel realm, String userId, GroupModel group);
+    void leaveGroup(RealmModel realm, String userId, GroupModel group);
     List<String> getMembership(RealmModel realm, GroupModel group, int firstResult, int max);
 
 }
diff --git a/server-spi/src/main/java/org/keycloak/storage/federated/UserRequiredActionsFederatedStorage.java b/server-spi/src/main/java/org/keycloak/storage/federated/UserRequiredActionsFederatedStorage.java
index 1e14f78..e58c0a0 100644
--- a/server-spi/src/main/java/org/keycloak/storage/federated/UserRequiredActionsFederatedStorage.java
+++ b/server-spi/src/main/java/org/keycloak/storage/federated/UserRequiredActionsFederatedStorage.java
@@ -26,7 +26,7 @@ import java.util.Set;
  * @version $Revision: 1 $
  */
 public interface UserRequiredActionsFederatedStorage {
-    Set<String> getRequiredActions(RealmModel realm, UserModel user);
-    void addRequiredAction(RealmModel realm,UserModel user, String action);
-    void removeRequiredAction(RealmModel realm,UserModel user, String action);
+    Set<String> getRequiredActions(RealmModel realm, String userId);
+    void addRequiredAction(RealmModel realm, String userId, String action);
+    void removeRequiredAction(RealmModel realm, String userId, String action);
 }
diff --git a/server-spi/src/main/java/org/keycloak/storage/federated/UserRoleMappingsFederatedStorage.java b/server-spi/src/main/java/org/keycloak/storage/federated/UserRoleMappingsFederatedStorage.java
index f63d9ec..446898b 100644
--- a/server-spi/src/main/java/org/keycloak/storage/federated/UserRoleMappingsFederatedStorage.java
+++ b/server-spi/src/main/java/org/keycloak/storage/federated/UserRoleMappingsFederatedStorage.java
@@ -28,9 +28,9 @@ import java.util.Set;
  */
 public interface UserRoleMappingsFederatedStorage {
 
-    void grantRole(RealmModel realm,UserModel user, RoleModel role);
+    void grantRole(RealmModel realm, String userId, RoleModel role);
 
-    Set<RoleModel> getRoleMappings(RealmModel realm,UserModel user);
+    Set<RoleModel> getRoleMappings(RealmModel realm,String userId);
 
-    void deleteRoleMapping(RealmModel realm, UserModel user, RoleModel role);
+    void deleteRoleMapping(RealmModel realm, String userId, RoleModel role);
 }
diff --git a/server-spi/src/main/java/org/keycloak/storage/StorageId.java b/server-spi/src/main/java/org/keycloak/storage/StorageId.java
index e7ada01..97bbc74 100644
--- a/server-spi/src/main/java/org/keycloak/storage/StorageId.java
+++ b/server-spi/src/main/java/org/keycloak/storage/StorageId.java
@@ -75,6 +75,9 @@ public class StorageId implements Serializable {
     public static boolean isLocalStorage(UserModel user) {
         return new StorageId(user.getId()).getProviderId() == null;
     }
+    public static boolean isLocalStorage(String userId) {
+        return new StorageId(userId).getProviderId() == null;
+    }
 
     public String getId() {
         return id;
diff --git a/services/src/main/java/org/keycloak/exportimport/dir/DirExportProvider.java b/services/src/main/java/org/keycloak/exportimport/dir/DirExportProvider.java
index 906d246..7efd3f3 100755
--- a/services/src/main/java/org/keycloak/exportimport/dir/DirExportProvider.java
+++ b/services/src/main/java/org/keycloak/exportimport/dir/DirExportProvider.java
@@ -86,6 +86,13 @@ public class DirExportProvider extends MultipleStepsExportProvider {
     }
 
     @Override
+    protected void writeFederatedUsers(String fileName, KeycloakSession session, RealmModel realm, List<String> users) throws IOException {
+        File file = new File(this.rootDirectory, fileName);
+        FileOutputStream os = new FileOutputStream(file);
+        ExportUtils.exportFederatedUsersToStream(session, realm, users, JsonSerialization.prettyMapper, os);
+    }
+
+    @Override
     public void close() {
     }
 }
diff --git a/services/src/main/java/org/keycloak/exportimport/dir/DirImportProvider.java b/services/src/main/java/org/keycloak/exportimport/dir/DirImportProvider.java
index 391d9a6..0555218 100755
--- a/services/src/main/java/org/keycloak/exportimport/dir/DirImportProvider.java
+++ b/services/src/main/java/org/keycloak/exportimport/dir/DirImportProvider.java
@@ -115,6 +115,13 @@ public class DirImportProvider implements ImportProvider {
                 return name.matches(realmName + "-users-[0-9]+\\.json");
             }
         });
+        File[] federatedUserFiles = this.rootDirectory.listFiles(new FilenameFilter() {
+
+            @Override
+            public boolean accept(File dir, String name) {
+                return name.matches(realmName + "-federated-users-[0-9]+\\.json");
+            }
+        });
 
         // Import realm first
         FileInputStream is = new FileInputStream(realmFile);
@@ -143,6 +150,16 @@ public class DirImportProvider implements ImportProvider {
                     }
                 });
             }
+            for (final File userFile : federatedUserFiles) {
+                final FileInputStream fis = new FileInputStream(userFile);
+                KeycloakModelUtils.runJobInTransaction(factory, new ExportImportSessionTask() {
+                    @Override
+                    protected void runExportImportTask(KeycloakSession session) throws IOException {
+                        ImportUtils.importFederatedUsersFromStream(session, realmName, JsonSerialization.mapper, fis);
+                        logger.infof("Imported federated users from %s", userFile.getAbsolutePath());
+                    }
+                });
+            }
         }
     }
 
diff --git a/services/src/main/java/org/keycloak/exportimport/util/ExportUtils.java b/services/src/main/java/org/keycloak/exportimport/util/ExportUtils.java
index ffdec2f..96d514c 100755
--- a/services/src/main/java/org/keycloak/exportimport/util/ExportUtils.java
+++ b/services/src/main/java/org/keycloak/exportimport/util/ExportUtils.java
@@ -213,7 +213,7 @@ public class ExportUtils {
         // Finally users if needed
         if (includeUsers) {
             List<UserModel> allUsers = session.users().getUsers(realm, true);
-            List<UserRepresentation> users = new ArrayList<UserRepresentation>();
+            List<UserRepresentation> users = new LinkedList<>();
             for (UserModel user : allUsers) {
                 UserRepresentation userRep = exportUser(session, realm, user);
                 users.add(userRep);
@@ -222,6 +222,16 @@ public class ExportUtils {
             if (users.size() > 0) {
                 rep.setUsers(users);
             }
+
+            List<UserRepresentation> federatedUsers = new LinkedList<>();
+            for (String userId : session.userFederatedStorage().getStoredUsers(realm, 0, -1)) {
+                UserRepresentation userRep = exportFederatedUser(session, realm, userId);
+                federatedUsers.add(userRep);
+            }
+            if (federatedUsers.size() > 0) {
+                rep.setFederatedUsers(federatedUsers);
+            }
+
         }
 
         // components
@@ -510,7 +520,7 @@ public class ExportUtils {
         userRep.setFederationLink(user.getFederationLink());
 
         // Grants
-        List<UserConsentModel> consents = session.users().getConsents(realm, user);
+        List<UserConsentModel> consents = session.users().getConsents(realm, user.getId());
         LinkedList<UserConsentRepresentation> consentReps = new LinkedList<UserConsentRepresentation>();
         for (UserConsentModel consent : consents) {
             UserConsentRepresentation consentRep = ModelToRepresentation.toRepresentation(consent);
@@ -558,6 +568,7 @@ public class ExportUtils {
         credRep.setDigits(userCred.getDigits());
         credRep.setCreatedDate(userCred.getCreatedDate());
         credRep.setConfig(userCred.getConfig());
+        credRep.setPeriod(userCred.getPeriod());
         return credRep;
     }
 
@@ -587,4 +598,122 @@ public class ExportUtils {
             generator.close();
         }
     }
+
+    public static void exportFederatedUsersToStream(KeycloakSession session, RealmModel realm, List<String> usersToExport, ObjectMapper mapper, OutputStream os) throws IOException {
+        JsonFactory factory = mapper.getFactory();
+        JsonGenerator generator = factory.createGenerator(os, JsonEncoding.UTF8);
+        try {
+            if (mapper.isEnabled(SerializationFeature.INDENT_OUTPUT)) {
+                generator.useDefaultPrettyPrinter();
+            }
+            generator.writeStartObject();
+            generator.writeStringField("realm", realm.getName());
+            // generator.writeStringField("strategy", strategy.toString());
+            generator.writeFieldName("federatedUsers");
+            generator.writeStartArray();
+
+            for (String userId : usersToExport) {
+                UserRepresentation userRep = ExportUtils.exportFederatedUser(session, realm, userId);
+                generator.writeObject(userRep);
+            }
+
+            generator.writeEndArray();
+            generator.writeEndObject();
+        } finally {
+            generator.close();
+        }
+    }
+
+    /**
+     * Full export of user data stored in federated storage (including role mappings and credentials)
+     *
+     * @param id
+     * @return fully exported user representation
+     */
+    public static UserRepresentation exportFederatedUser(KeycloakSession session, RealmModel realm, String id) {
+        UserRepresentation userRep = new UserRepresentation();
+        userRep.setId(id);
+        MultivaluedHashMap<String, String> attributes = session.userFederatedStorage().getAttributes(realm, id);
+        if (attributes.size() > 0) {
+            Map<String, Object> attrs = new HashMap<>();
+            attrs.putAll(attributes);
+            userRep.setAttributes(attrs);
+        }
+
+        Set<String> requiredActions = session.userFederatedStorage().getRequiredActions(realm, id);
+        if (requiredActions.size() > 0) {
+            List<String> actions = new LinkedList<>();
+            actions.addAll(requiredActions);
+            userRep.setRequiredActions(actions);
+        }
+
+
+        // Social links
+        Set<FederatedIdentityModel> socialLinks = session.userFederatedStorage().getFederatedIdentities(id, realm);
+        List<FederatedIdentityRepresentation> socialLinkReps = new ArrayList<FederatedIdentityRepresentation>();
+        for (FederatedIdentityModel socialLink : socialLinks) {
+            FederatedIdentityRepresentation socialLinkRep = exportSocialLink(socialLink);
+            socialLinkReps.add(socialLinkRep);
+        }
+        if (socialLinkReps.size() > 0) {
+            userRep.setFederatedIdentities(socialLinkReps);
+        }
+
+        // Role mappings
+        Set<RoleModel> roles = session.userFederatedStorage().getRoleMappings(realm, id);
+        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 {
+                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);
+                }
+
+                currentClientRoles.add(role.getName());
+            }
+        }
+
+        if (realmRoleNames.size() > 0) {
+            userRep.setRealmRoles(realmRoleNames);
+        }
+        if (clientRoleNames.size() > 0) {
+            userRep.setClientRoles(clientRoleNames);
+        }
+
+        // Credentials
+        List<CredentialModel> creds = session.userFederatedStorage().getStoredCredentials(realm, id);
+        List<CredentialRepresentation> credReps = new ArrayList<CredentialRepresentation>();
+        for (CredentialModel cred : creds) {
+            CredentialRepresentation credRep = exportCredential(cred);
+            credReps.add(credRep);
+        }
+        userRep.setCredentials(credReps);
+
+        // Grants
+        List<UserConsentModel> consents = session.users().getConsents(realm, id);
+        LinkedList<UserConsentRepresentation> consentReps = new LinkedList<UserConsentRepresentation>();
+        for (UserConsentModel consent : consents) {
+            UserConsentRepresentation consentRep = ModelToRepresentation.toRepresentation(consent);
+            consentReps.add(consentRep);
+        }
+        if (consentReps.size() > 0) {
+            userRep.setClientConsents(consentReps);
+        }
+
+
+        List<String> groups = new LinkedList<>();
+        for (GroupModel group : session.userFederatedStorage().getGroups(realm, id)) {
+            groups.add(ModelToRepresentation.buildGroupPath(group));
+        }
+        userRep.setGroups(groups);
+
+        return userRep;
+    }
+
 }
diff --git a/services/src/main/java/org/keycloak/exportimport/util/ImportUtils.java b/services/src/main/java/org/keycloak/exportimport/util/ImportUtils.java
index 044e89c..1ea4092 100755
--- a/services/src/main/java/org/keycloak/exportimport/util/ImportUtils.java
+++ b/services/src/main/java/org/keycloak/exportimport/util/ImportUtils.java
@@ -215,6 +215,48 @@ public class ImportUtils {
         }
     }
 
+    // Assuming that it's invoked inside transaction
+    public static void importFederatedUsersFromStream(KeycloakSession session, String realmName, ObjectMapper mapper, InputStream is) throws IOException {
+        RealmProvider model = session.realms();
+        JsonFactory factory = mapper.getJsonFactory();
+        JsonParser parser = factory.createJsonParser(is);
+        try {
+            parser.nextToken();
+
+            while (parser.nextToken() == JsonToken.FIELD_NAME) {
+                if ("realm".equals(parser.getText())) {
+                    parser.nextToken();
+                    String currRealmName = parser.getText();
+                    if (!currRealmName.equals(realmName)) {
+                        throw new IllegalStateException("Trying to import users into invalid realm. Realm name: " + realmName + ", Expected realm name: " + currRealmName);
+                    }
+                } else if ("federatedUsers".equals(parser.getText())) {
+                    parser.nextToken();
+
+                    if (parser.getCurrentToken() == JsonToken.START_ARRAY) {
+                        parser.nextToken();
+                    }
+
+                    // TODO: support for more transactions per single users file (if needed)
+                    List<UserRepresentation> userReps = new ArrayList<UserRepresentation>();
+                    while (parser.getCurrentToken() == JsonToken.START_OBJECT) {
+                        UserRepresentation user = parser.readValueAs(UserRepresentation.class);
+                        userReps.add(user);
+                        parser.nextToken();
+                    }
+
+                    importFederatedUsers(session, model, realmName, userReps);
+
+                    if (parser.getCurrentToken() == JsonToken.END_ARRAY) {
+                        parser.nextToken();
+                    }
+                }
+            }
+        } finally {
+            parser.close();
+        }
+    }
+
     private static void importUsers(KeycloakSession session, RealmProvider model, String realmName, List<UserRepresentation> userReps) {
         RealmModel realm = model.getRealmByName(realmName);
         for (UserRepresentation user : userReps) {
@@ -222,4 +264,13 @@ public class ImportUtils {
         }
     }
 
+
+    private static void importFederatedUsers(KeycloakSession session, RealmProvider model, String realmName, List<UserRepresentation> userReps) {
+        RealmModel realm = model.getRealmByName(realmName);
+        for (UserRepresentation user : userReps) {
+            RepresentationToModel.importFederatedUser(session, realm, user);
+        }
+    }
+
+
 }
diff --git a/services/src/main/java/org/keycloak/exportimport/util/MultipleStepsExportProvider.java b/services/src/main/java/org/keycloak/exportimport/util/MultipleStepsExportProvider.java
index 4537169..e1038c1 100755
--- a/services/src/main/java/org/keycloak/exportimport/util/MultipleStepsExportProvider.java
+++ b/services/src/main/java/org/keycloak/exportimport/util/MultipleStepsExportProvider.java
@@ -68,6 +68,7 @@ public abstract class MultipleStepsExportProvider implements ExportProvider {
         final int usersPerFile = ExportImportConfig.getUsersPerFile();
         final UsersHolder usersHolder = new UsersHolder();
         final boolean exportUsersIntoRealmFile = usersExportStrategy == UsersExportStrategy.REALM_FILE;
+        FederatedUsersHolder federatedUsersHolder = new FederatedUsersHolder();
 
         KeycloakModelUtils.runJobInTransaction(factory, new ExportImportSessionTask() {
 
@@ -81,6 +82,7 @@ public abstract class MultipleStepsExportProvider implements ExportProvider {
                 // Count total number of users
                 if (!exportUsersIntoRealmFile) {
                     usersHolder.totalCount = session.users().getUsersCount(realm);
+                    federatedUsersHolder.totalCount = session.userFederatedStorage().getStoredUsersCount(realm);
                 }
             }
 
@@ -117,11 +119,43 @@ public abstract class MultipleStepsExportProvider implements ExportProvider {
                 usersHolder.currentPageStart = usersHolder.currentPageEnd;
             }
         }
+        if (usersExportStrategy != UsersExportStrategy.SKIP && !exportUsersIntoRealmFile) {
+            // We need to export users now
+            federatedUsersHolder.currentPageStart = 0;
+
+            // usersExportStrategy==SAME_FILE  means exporting all users into single file (but separate to realm)
+            final int countPerPage = (usersExportStrategy == UsersExportStrategy.SAME_FILE) ? federatedUsersHolder.totalCount : usersPerFile;
+
+            while (federatedUsersHolder.currentPageStart < federatedUsersHolder.totalCount) {
+                if (federatedUsersHolder.currentPageStart + countPerPage < federatedUsersHolder.totalCount) {
+                    federatedUsersHolder.currentPageEnd = federatedUsersHolder.currentPageStart + countPerPage;
+                } else {
+                    federatedUsersHolder.currentPageEnd = federatedUsersHolder.totalCount;
+                }
+
+                KeycloakModelUtils.runJobInTransaction(factory, new ExportImportSessionTask() {
+
+                    @Override
+                    protected void runExportImportTask(KeycloakSession session) throws IOException {
+                        RealmModel realm = session.realms().getRealmByName(realmName);
+                        federatedUsersHolder.users = session.userFederatedStorage().getStoredUsers(realm, federatedUsersHolder.currentPageStart, federatedUsersHolder.currentPageEnd - federatedUsersHolder.currentPageStart);
+
+                        writeFederatedUsers(realmName + "-federated-users-" + (federatedUsersHolder.currentPageStart / countPerPage) + ".json", session, realm, federatedUsersHolder.users);
+
+                        logger.info("Users " + federatedUsersHolder.currentPageStart + "-" + (federatedUsersHolder.currentPageEnd -1) + " exported");
+                    }
+
+                });
+
+                federatedUsersHolder.currentPageStart = federatedUsersHolder.currentPageEnd;
+            }
+        }
     }
 
     protected abstract void writeRealm(String fileName, RealmRepresentation rep) throws IOException;
 
     protected abstract void writeUsers(String fileName, KeycloakSession session, RealmModel realm, List<UserModel> users) throws IOException;
+    protected abstract void writeFederatedUsers(String fileName, KeycloakSession session, RealmModel realm, List<String> users) throws IOException;
 
     public static class RealmsHolder {
         List<RealmModel> realms;
@@ -134,4 +168,10 @@ public abstract class MultipleStepsExportProvider implements ExportProvider {
         int currentPageStart;
         int currentPageEnd;
     }
+    public static class FederatedUsersHolder {
+        List<String> users;
+        int totalCount;
+        int currentPageStart;
+        int currentPageEnd;
+    }
 }
diff --git a/services/src/main/java/org/keycloak/forms/account/freemarker/model/ApplicationsBean.java b/services/src/main/java/org/keycloak/forms/account/freemarker/model/ApplicationsBean.java
index 82d7fb3..de5fd93 100755
--- a/services/src/main/java/org/keycloak/forms/account/freemarker/model/ApplicationsBean.java
+++ b/services/src/main/java/org/keycloak/forms/account/freemarker/model/ApplicationsBean.java
@@ -64,7 +64,7 @@ public class ApplicationsBean {
             MultivaluedHashMap<String, ClientRoleEntry> resourceRolesGranted = new MultivaluedHashMap<String, ClientRoleEntry>();
             List<String> claimsGranted = new LinkedList<String>();
             if (client.isConsentRequired()) {
-                UserConsentModel consent = session.users().getConsentByClient(realm, user, client.getId());
+                UserConsentModel consent = session.users().getConsentByClient(realm, user.getId(), client.getId());
 
                 if (consent != null) {
                     processRoles(consent.getGrantedRoles(), realmRolesGranted, resourceRolesGranted);
diff --git a/services/src/main/java/org/keycloak/services/DefaultKeycloakContext.java b/services/src/main/java/org/keycloak/services/DefaultKeycloakContext.java
index f58f4ca..99f2559 100755
--- a/services/src/main/java/org/keycloak/services/DefaultKeycloakContext.java
+++ b/services/src/main/java/org/keycloak/services/DefaultKeycloakContext.java
@@ -61,6 +61,7 @@ public class DefaultKeycloakContext implements KeycloakContext {
     @Override
     public String getContextPath() {
         KeycloakApplication app = getContextObject(KeycloakApplication.class);
+        if (app == null) return null;
         return app.getContextPath();
     }
 
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 35636ea..d0eb66b 100755
--- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
@@ -491,7 +491,7 @@ public class AuthenticationManager {
 
         if (client.isConsentRequired()) {
 
-            UserConsentModel grantedConsent = session.users().getConsentByClient(realm, user, client.getId());
+            UserConsentModel grantedConsent = session.users().getConsentByClient(realm, user.getId(), client.getId());
 
             ClientSessionCode accessCode = new ClientSessionCode(session, realm, clientSession);
             for (RoleModel r : accessCode.getRequestedRoles()) {
@@ -545,7 +545,7 @@ public class AuthenticationManager {
 
         if (client.isConsentRequired()) {
 
-            UserConsentModel grantedConsent = session.users().getConsentByClient(realm, user, client.getId());
+            UserConsentModel grantedConsent = session.users().getConsentByClient(realm, user.getId(), client.getId());
 
             List<RoleModel> realmRoles = new LinkedList<>();
             MultivaluedMap<String, RoleModel> resourceRoles = new MultivaluedMapImpl<>();
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 bb3bb11..2684483 100755
--- a/services/src/main/java/org/keycloak/services/resources/AccountService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java
@@ -496,7 +496,7 @@ public class AccountService extends AbstractSecuredLocalService {
 
         // Revoke grant in UserModel
         UserModel user = auth.getUser();
-        session.users().revokeConsentForClient(realm, user, client.getId());
+        session.users().revokeConsentForClient(realm, user.getId(), client.getId());
         new UserSessionManager(session).revokeOfflineToken(user, client);
 
         // Logout clientSessions for this user and client
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 9ef005d..f76761f 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
@@ -525,7 +525,7 @@ public class UsersResource {
         Set<ClientModel> offlineClients = new UserSessionManager(session).findClientsWithOfflineToken(realm, user);
 
         for (ClientModel client : realm.getClients()) {
-            UserConsentModel consent = session.users().getConsentByClient(realm, user, client.getId());
+            UserConsentModel consent = session.users().getConsentByClient(realm, user.getId(), client.getId());
             boolean hasOfflineToken = offlineClients.contains(client);
 
             if (consent == null && !hasOfflineToken) {
@@ -576,7 +576,7 @@ public class UsersResource {
         }
 
         ClientModel client = realm.getClientByClientId(clientId);
-        boolean revokedConsent = session.users().revokeConsentForClient(realm, user, client.getId());
+        boolean revokedConsent = session.users().revokeConsentForClient(realm, user.getId(), client.getId());
         boolean revokedOfflineToken = new UserSessionManager(session).revokeOfflineToken(user, client);
 
         if (revokedConsent) {
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 b22e792..2e2641c 100755
--- a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
+++ b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
@@ -667,10 +667,10 @@ public class LoginActionsService {
             return response;
         }
 
-        UserConsentModel grantedConsent = session.users().getConsentByClient(realm, user, client.getId());
+        UserConsentModel grantedConsent = session.users().getConsentByClient(realm, user.getId(), client.getId());
         if (grantedConsent == null) {
             grantedConsent = new UserConsentModel(client);
-            session.users().addConsent(realm, user, grantedConsent);
+            session.users().addConsent(realm, user.getId(), grantedConsent);
         }
         for (RoleModel role : accessCode.getRequestedRoles()) {
             grantedConsent.addGrantedRole(role);
@@ -680,7 +680,7 @@ public class LoginActionsService {
                 grantedConsent.addGrantedProtocolMapper(protocolMapper);
             }
         }
-        session.users().updateConsent(realm, user, grantedConsent);
+        session.users().updateConsent(realm, user.getId(), grantedConsent);
 
         event.detail(Details.CONSENT, Details.CONSENT_VALUE_CONSENT_GRANTED);
         event.success();
diff --git a/services/src/main/java/org/keycloak/storage/UserStorageManager.java b/services/src/main/java/org/keycloak/storage/UserStorageManager.java
index 995043a..8394bbb 100755
--- a/services/src/main/java/org/keycloak/storage/UserStorageManager.java
+++ b/services/src/main/java/org/keycloak/storage/UserStorageManager.java
@@ -157,7 +157,7 @@ public class UserStorageManager implements UserProvider, OnUserCache {
         if (StorageId.isLocalStorage(user)) {
             localStorage().addFederatedIdentity(realm, user, socialLink);
         } else {
-            getFederatedStorage().addFederatedIdentity(realm, user, socialLink);
+            getFederatedStorage().addFederatedIdentity(realm, user.getId(), socialLink);
         }
     }
 
@@ -166,7 +166,7 @@ public class UserStorageManager implements UserProvider, OnUserCache {
             localStorage().updateFederatedIdentity(realm, federatedUser, federatedIdentityModel);
 
         } else {
-            getFederatedStorage().updateFederatedIdentity(realm, federatedUser, federatedIdentityModel);
+            getFederatedStorage().updateFederatedIdentity(realm, federatedUser.getId(), federatedIdentityModel);
         }
     }
 
@@ -175,55 +175,55 @@ public class UserStorageManager implements UserProvider, OnUserCache {
         if (StorageId.isLocalStorage(user)) {
             return localStorage().removeFederatedIdentity(realm, user, socialProvider);
         } else {
-            return getFederatedStorage().removeFederatedIdentity(realm, user, socialProvider);
+            return getFederatedStorage().removeFederatedIdentity(realm, user.getId(), socialProvider);
         }
     }
 
     @Override
-    public void addConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
-        if (StorageId.isLocalStorage(user)) {
-            localStorage().addConsent(realm, user, consent);
+    public void addConsent(RealmModel realm, String userId, UserConsentModel consent) {
+        if (StorageId.isLocalStorage(userId)) {
+            localStorage().addConsent(realm, userId, consent);
         } else {
-            getFederatedStorage().addConsent(realm, user, consent);
+            getFederatedStorage().addConsent(realm, userId, consent);
         }
 
     }
 
     @Override
-    public UserConsentModel getConsentByClient(RealmModel realm, UserModel user, String clientInternalId) {
-        if (StorageId.isLocalStorage(user)) {
-            return localStorage().getConsentByClient(realm, user, clientInternalId);
+    public UserConsentModel getConsentByClient(RealmModel realm, String userId, String clientInternalId) {
+        if (StorageId.isLocalStorage(userId)) {
+            return localStorage().getConsentByClient(realm, userId, clientInternalId);
         } else {
-            return getFederatedStorage().getConsentByClient(realm, user, clientInternalId);
+            return getFederatedStorage().getConsentByClient(realm, userId, clientInternalId);
         }
     }
 
     @Override
-    public List<UserConsentModel> getConsents(RealmModel realm, UserModel user) {
-        if (StorageId.isLocalStorage(user)) {
-            return localStorage().getConsents(realm, user);
+    public List<UserConsentModel> getConsents(RealmModel realm, String userId) {
+        if (StorageId.isLocalStorage(userId)) {
+            return localStorage().getConsents(realm, userId);
 
         } else {
-            return getFederatedStorage().getConsents(realm, user);
+            return getFederatedStorage().getConsents(realm, userId);
         }
     }
 
     @Override
-    public void updateConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
-        if (StorageId.isLocalStorage(user)) {
-            localStorage().updateConsent(realm, user, consent);
+    public void updateConsent(RealmModel realm, String userId, UserConsentModel consent) {
+        if (StorageId.isLocalStorage(userId)) {
+            localStorage().updateConsent(realm, userId, consent);
         } else {
-            getFederatedStorage().updateConsent(realm, user, consent);
+            getFederatedStorage().updateConsent(realm, userId, consent);
         }
 
     }
 
     @Override
-    public boolean revokeConsentForClient(RealmModel realm, UserModel user, String clientInternalId) {
-        if (StorageId.isLocalStorage(user)) {
-            return localStorage().revokeConsentForClient(realm, user, clientInternalId);
+    public boolean revokeConsentForClient(RealmModel realm, String userId, String clientInternalId) {
+        if (StorageId.isLocalStorage(userId)) {
+            return localStorage().revokeConsentForClient(realm, userId, clientInternalId);
         } else {
-            return getFederatedStorage().revokeConsentForClient(realm, user, clientInternalId);
+            return getFederatedStorage().revokeConsentForClient(realm, userId, clientInternalId);
         }
     }
 
@@ -466,7 +466,7 @@ public class UserStorageManager implements UserProvider, OnUserCache {
         if (StorageId.isLocalStorage(user)) {
             set.addAll(localStorage().getFederatedIdentities(user, realm));
         }
-        if (getFederatedStorage() != null) set.addAll(getFederatedStorage().getFederatedIdentities(user, realm));
+        if (getFederatedStorage() != null) set.addAll(getFederatedStorage().getFederatedIdentities(user.getId(), realm));
         return set;
     }
 
@@ -477,7 +477,7 @@ public class UserStorageManager implements UserProvider, OnUserCache {
             FederatedIdentityModel model = localStorage().getFederatedIdentity(user, socialProvider, realm);
             if (model != null) return model;
         }
-        if (getFederatedStorage() != null) return getFederatedStorage().getFederatedIdentity(user, socialProvider, realm);
+        if (getFederatedStorage() != null) return getFederatedStorage().getFederatedIdentity(user.getId(), socialProvider, realm);
         else return null;
     }
 
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/FederatedStorageExportImportTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/FederatedStorageExportImportTest.java
new file mode 100644
index 0000000..2591c77
--- /dev/null
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/FederatedStorageExportImportTest.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.testsuite.federation.storage;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.keycloak.OAuth2Constants;
+import org.keycloak.common.util.MultivaluedHashMap;
+import org.keycloak.component.ComponentModel;
+import org.keycloak.credential.CredentialModel;
+import org.keycloak.credential.hash.PasswordHashProvider;
+import org.keycloak.exportimport.ExportImportConfig;
+import org.keycloak.exportimport.ExportImportManager;
+import org.keycloak.exportimport.UsersExportStrategy;
+import org.keycloak.exportimport.dir.DirExportProviderFactory;
+import org.keycloak.exportimport.singlefile.SingleFileExportProviderFactory;
+import org.keycloak.models.GroupModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.PasswordPolicy;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.cache.infinispan.UserAdapter;
+import org.keycloak.policy.HashAlgorithmPasswordPolicyProviderFactory;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.storage.StorageId;
+import org.keycloak.storage.UserStorageProviderModel;
+import org.keycloak.testsuite.OAuthClient;
+import org.keycloak.testsuite.pages.AppPage;
+import org.keycloak.testsuite.pages.LoginPage;
+import org.keycloak.testsuite.rule.KeycloakRule;
+import org.keycloak.testsuite.rule.WebResource;
+import org.keycloak.testsuite.rule.WebRule;
+import org.openqa.selenium.WebDriver;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class FederatedStorageExportImportTest {
+    public static ComponentModel memoryProvider = null;
+    public static ComponentModel writableProvider = null;
+    @ClassRule
+    public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakRule.KeycloakSetup() {
+
+        @Override
+        public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+
+        }
+    });
+
+    public static String basePath = null;
+
+    @BeforeClass
+    public static void setDirs() {
+        basePath = new File(System.getProperty("project.build.directory", "target")).getAbsolutePath();
+
+    }
+
+    protected PasswordHashProvider getHashProvider(KeycloakSession session, PasswordPolicy policy) {
+        PasswordHashProvider hash = session.getProvider(PasswordHashProvider.class, policy.getHashAlgorithm());
+        if (hash == null) {
+            return session.getProvider(PasswordHashProvider.class, HashAlgorithmPasswordPolicyProviderFactory.DEFAULT_VALUE);
+        }
+        return hash;
+    }
+
+
+    @Test
+    public void testSingleFile() throws Exception {
+        clearExportImportProperties();
+        KeycloakSession session = keycloakRule.startSession();
+        RealmModel realm = new RealmManager(session).createRealm("exported");
+        String realmId = realm.getId();
+        RoleModel role = realm.addRole("test-role");
+        GroupModel group = realm.createGroup("test-group");
+        String groupId = group.getId();
+        String userId = "f:1:path";
+        List<String> attrValues = new LinkedList<>();
+        attrValues.add("1");
+        attrValues.add("2");
+        session.userFederatedStorage().setSingleAttribute(realm, userId, "single1", "value1");
+        session.userFederatedStorage().setAttribute(realm, userId, "list1", attrValues);
+        session.userFederatedStorage().addRequiredAction(realm, userId, "UPDATE_PASSWORD");
+        CredentialModel credential = new CredentialModel();
+        getHashProvider(session, realm.getPasswordPolicy()).encode("password", realm.
+                getPasswordPolicy(), credential);
+        session.userFederatedStorage().createCredential(realm, userId, credential);
+        session.userFederatedStorage().grantRole(realm, userId, role);
+        session.userFederatedStorage().joinGroup(realm, userId, group);
+        keycloakRule.stopSession(session, true);
+
+
+
+
+        String targetFilePath = basePath + File.separator + "singleFile-full.json";
+        System.out.println("export file: " + targetFilePath);
+        session = keycloakRule.startSession();
+        ExportImportConfig.setProvider(SingleFileExportProviderFactory.PROVIDER_ID);
+        ExportImportConfig.setFile(targetFilePath);
+        ExportImportConfig.setRealmName("exported");
+        ExportImportConfig.setAction(ExportImportConfig.ACTION_EXPORT);
+        new ExportImportManager(session).runExport();
+        session.realms().removeRealm(realmId);
+        keycloakRule.stopSession(session, true);
+
+        session = keycloakRule.startSession();
+        Assert.assertNull(session.realms().getRealmByName("exported"));
+        ExportImportConfig.setAction(ExportImportConfig.ACTION_IMPORT);
+        new ExportImportManager(session).runImport();
+        realm = session.realms().getRealmByName("exported");
+        Assert.assertNotNull(realm);
+        role = realm.getRole("test-role");
+        group = realm.getGroupById(groupId);
+
+        Assert.assertEquals(1, session.userFederatedStorage().getStoredUsersCount(realm));
+        MultivaluedHashMap<String, String> attributes = session.userFederatedStorage().getAttributes(realm, userId);
+        Assert.assertEquals(2, attributes.size());
+        Assert.assertEquals("value1", attributes.getFirst("single1"));
+        Assert.assertTrue(attributes.getList("list1").contains("1"));
+        Assert.assertTrue(attributes.getList("list1").contains("2"));
+        Assert.assertTrue(session.userFederatedStorage().getRequiredActions(realm, userId).contains("UPDATE_PASSWORD"));
+        Assert.assertTrue(session.userFederatedStorage().getRoleMappings(realm, userId).contains(role));
+        Assert.assertTrue(session.userFederatedStorage().getGroups(realm, userId).contains(group));
+        List<CredentialModel> creds = session.userFederatedStorage().getStoredCredentials(realm, userId);
+        Assert.assertEquals(1, creds.size());
+        Assert.assertTrue(getHashProvider(session, realm.getPasswordPolicy()).verify("password", creds.get(0)));
+        session.realms().removeRealm(realmId);
+        keycloakRule.stopSession(session, true);
+
+    }
+
+    @Test
+    public void testDir() throws Exception {
+        clearExportImportProperties();
+        KeycloakSession session = keycloakRule.startSession();
+        RealmModel realm = new RealmManager(session).createRealm("exported");
+        String realmId = realm.getId();
+        RoleModel role = realm.addRole("test-role");
+        GroupModel group = realm.createGroup("test-group");
+        String groupId = group.getId();
+        String userId = "f:1:path";
+        List<String> attrValues = new LinkedList<>();
+        attrValues.add("1");
+        attrValues.add("2");
+        session.userFederatedStorage().setSingleAttribute(realm, userId, "single1", "value1");
+        session.userFederatedStorage().setAttribute(realm, userId, "list1", attrValues);
+        session.userFederatedStorage().addRequiredAction(realm, userId, "UPDATE_PASSWORD");
+        CredentialModel credential = new CredentialModel();
+        getHashProvider(session, realm.getPasswordPolicy()).encode("password", realm.
+                getPasswordPolicy(), credential);
+        session.userFederatedStorage().createCredential(realm, userId, credential);
+        session.userFederatedStorage().grantRole(realm, userId, role);
+        session.userFederatedStorage().joinGroup(realm, userId, group);
+        keycloakRule.stopSession(session, true);
+
+
+
+
+        String targetFilePath = basePath + File.separator + "dirExport";
+        session = keycloakRule.startSession();
+        ExportImportConfig.setProvider(DirExportProviderFactory.PROVIDER_ID);
+        ExportImportConfig.setDir(targetFilePath);
+        ExportImportConfig.setRealmName("exported");
+        ExportImportConfig.setAction(ExportImportConfig.ACTION_EXPORT);
+        new ExportImportManager(session).runExport();
+        session.realms().removeRealm(realmId);
+        keycloakRule.stopSession(session, true);
+
+        session = keycloakRule.startSession();
+        Assert.assertNull(session.realms().getRealmByName("exported"));
+        ExportImportConfig.setAction(ExportImportConfig.ACTION_IMPORT);
+        new ExportImportManager(session).runImport();
+        realm = session.realms().getRealmByName("exported");
+        Assert.assertNotNull(realm);
+        role = realm.getRole("test-role");
+        group = realm.getGroupById(groupId);
+
+        Assert.assertEquals(1, session.userFederatedStorage().getStoredUsersCount(realm));
+        MultivaluedHashMap<String, String> attributes = session.userFederatedStorage().getAttributes(realm, userId);
+        Assert.assertEquals(2, attributes.size());
+        Assert.assertEquals("value1", attributes.getFirst("single1"));
+        Assert.assertTrue(attributes.getList("list1").contains("1"));
+        Assert.assertTrue(attributes.getList("list1").contains("2"));
+        Assert.assertTrue(session.userFederatedStorage().getRequiredActions(realm, userId).contains("UPDATE_PASSWORD"));
+        Assert.assertTrue(session.userFederatedStorage().getRoleMappings(realm, userId).contains(role));
+        Assert.assertTrue(session.userFederatedStorage().getGroups(realm, userId).contains(group));
+        List<CredentialModel> creds = session.userFederatedStorage().getStoredCredentials(realm, userId);
+        Assert.assertEquals(1, creds.size());
+        Assert.assertTrue(getHashProvider(session, realm.getPasswordPolicy()).verify("password", creds.get(0)));
+        session.realms().removeRealm(realmId);
+        keycloakRule.stopSession(session, true);
+
+    }
+
+    public void clearExportImportProperties() {
+        // Clear export/import properties after test
+        Properties systemProps = System.getProperties();
+        Set<String> propsToRemove = new HashSet<String>();
+
+        for (Object key : systemProps.keySet()) {
+            if (key.toString().startsWith(ExportImportConfig.PREFIX)) {
+                propsToRemove.add(key.toString());
+            }
+        }
+
+        for (String propToRemove : propsToRemove) {
+            systemProps.remove(propToRemove);
+        }
+    }
+
+
+
+
+}
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 dedc8d1..98c7437 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
@@ -357,15 +357,15 @@ public class ImportTest extends AbstractModelTest {
 
         // Test user consents
         admin =  session.users().getUserByUsername("admin", realm);
-        Assert.assertEquals(2, session.users().getConsents(realm, admin).size());
+        Assert.assertEquals(2, session.users().getConsents(realm, admin.getId()).size());
 
-        UserConsentModel appAdminConsent = session.users().getConsentByClient(realm, admin, application.getId());
+        UserConsentModel appAdminConsent = session.users().getConsentByClient(realm, admin.getId(), application.getId());
         Assert.assertEquals(2, appAdminConsent.getGrantedRoles().size());
         Assert.assertTrue(appAdminConsent.getGrantedProtocolMappers() == null || appAdminConsent.getGrantedProtocolMappers().isEmpty());
         Assert.assertTrue(appAdminConsent.isRoleGranted(realm.getRole("admin")));
         Assert.assertTrue(appAdminConsent.isRoleGranted(application.getRole("app-admin")));
 
-        UserConsentModel otherAppAdminConsent = session.users().getConsentByClient(realm, admin, otherApp.getId());
+        UserConsentModel otherAppAdminConsent = session.users().getConsentByClient(realm, admin.getId(), otherApp.getId());
         Assert.assertEquals(1, otherAppAdminConsent.getGrantedRoles().size());
         Assert.assertEquals(1, otherAppAdminConsent.getGrantedProtocolMappers().size());
         Assert.assertTrue(otherAppAdminConsent.isRoleGranted(realm.getRole("admin")));
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserConsentModelTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserConsentModelTest.java
index c65fee1..9fe49f2 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserConsentModelTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserConsentModelTest.java
@@ -67,7 +67,7 @@ public class UserConsentModelTest extends AbstractModelTest {
         johnFooGrant.addGrantedRole(realmRole);
         johnFooGrant.addGrantedRole(barClientRole);
         johnFooGrant.addGrantedProtocolMapper(fooMapper);
-        realmManager.getSession().users().addConsent(realm, john, johnFooGrant);
+        realmManager.getSession().users().addConsent(realm, john.getId(), johnFooGrant);
 
         UserConsentModel johnBarGrant = new UserConsentModel(barClient);
         johnBarGrant.addGrantedProtocolMapper(barMapper);
@@ -75,17 +75,17 @@ public class UserConsentModelTest extends AbstractModelTest {
 
         // Update should fail as grant doesn't yet exists
         try {
-            realmManager.getSession().users().updateConsent(realm, john, johnBarGrant);
+            realmManager.getSession().users().updateConsent(realm, john.getId(), johnBarGrant);
             Assert.fail("Not expected to end here");
         } catch (ModelException expected) {
         }
 
-        realmManager.getSession().users().addConsent(realm, john, johnBarGrant);
+        realmManager.getSession().users().addConsent(realm, john.getId(), johnBarGrant);
 
         UserConsentModel maryFooGrant = new UserConsentModel(fooClient);
         maryFooGrant.addGrantedRole(realmRole);
         maryFooGrant.addGrantedProtocolMapper(fooMapper);
-        realmManager.getSession().users().addConsent(realm, mary, maryFooGrant);
+        realmManager.getSession().users().addConsent(realm, mary.getId(), maryFooGrant);
 
         commit();
     }
@@ -99,7 +99,7 @@ public class UserConsentModelTest extends AbstractModelTest {
         UserModel john = session.users().getUserByUsername("john", realm);
         UserModel mary = session.users().getUserByUsername("mary", realm);
 
-        UserConsentModel johnFooConsent = realmManager.getSession().users().getConsentByClient(realm, john, fooClient.getId());
+        UserConsentModel johnFooConsent = realmManager.getSession().users().getConsentByClient(realm, john.getId(), fooClient.getId());
         Assert.assertEquals(johnFooConsent.getGrantedRoles().size(), 2);
         Assert.assertEquals(johnFooConsent.getGrantedProtocolMappers().size(), 1);
         Assert.assertTrue(isRoleGranted(realm, "realm-role", johnFooConsent));
@@ -108,7 +108,7 @@ public class UserConsentModelTest extends AbstractModelTest {
         Assert.assertNotNull("Created Date should be set", johnFooConsent.getCreatedDate());
         Assert.assertNotNull("Last Updated Date should be set", johnFooConsent.getLastUpdatedDate());
 
-        UserConsentModel johnBarConsent = realmManager.getSession().users().getConsentByClient(realm, john, barClient.getId());
+        UserConsentModel johnBarConsent = realmManager.getSession().users().getConsentByClient(realm, john.getId(), barClient.getId());
         Assert.assertEquals(johnBarConsent.getGrantedRoles().size(), 1);
         Assert.assertEquals(johnBarConsent.getGrantedProtocolMappers().size(), 1);
         Assert.assertTrue(isRoleGranted(realm, "realm-role", johnBarConsent));
@@ -116,7 +116,7 @@ public class UserConsentModelTest extends AbstractModelTest {
         Assert.assertNotNull("Created Date should be set", johnBarConsent.getCreatedDate());
         Assert.assertNotNull("Last Updated Date should be set", johnBarConsent.getLastUpdatedDate());
 
-        UserConsentModel maryConsent = realmManager.getSession().users().getConsentByClient(realm, mary, fooClient.getId());
+        UserConsentModel maryConsent = realmManager.getSession().users().getConsentByClient(realm, mary.getId(), fooClient.getId());
         Assert.assertEquals(maryConsent.getGrantedRoles().size(), 1);
         Assert.assertEquals(maryConsent.getGrantedProtocolMappers().size(), 1);
         Assert.assertTrue(isRoleGranted(realm, "realm-role", maryConsent));
@@ -125,7 +125,7 @@ public class UserConsentModelTest extends AbstractModelTest {
         Assert.assertNotNull("Created Date should be set", maryConsent.getCreatedDate());
         Assert.assertNotNull("Last Updated Date should be set", maryConsent.getLastUpdatedDate());
 
-        Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, mary, barClient.getId()));
+        Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, mary.getId(), barClient.getId()));
     }
 
     @Test
@@ -136,10 +136,10 @@ public class UserConsentModelTest extends AbstractModelTest {
         UserModel john = session.users().getUserByUsername("john", realm);
         UserModel mary = session.users().getUserByUsername("mary", realm);
 
-        List<UserConsentModel> johnConsents = realmManager.getSession().users().getConsents(realm, john);
+        List<UserConsentModel> johnConsents = realmManager.getSession().users().getConsents(realm, john.getId());
         Assert.assertEquals(2, johnConsents.size());
 
-        List<UserConsentModel> maryConsents = realmManager.getSession().users().getConsents(realm, mary);
+        List<UserConsentModel> maryConsents = realmManager.getSession().users().getConsents(realm, mary.getId());
         Assert.assertEquals(1, maryConsents.size());
         UserConsentModel maryConsent = maryConsents.get(0);
         Assert.assertEquals(maryConsent.getClient().getId(), fooClient.getId());
@@ -155,7 +155,7 @@ public class UserConsentModelTest extends AbstractModelTest {
         ClientModel fooClient = realm.getClientByClientId("foo-client");
         UserModel john = session.users().getUserByUsername("john", realm);
 
-        UserConsentModel johnConsent = realmManager.getSession().users().getConsentByClient(realm, john, fooClient.getId());
+        UserConsentModel johnConsent = realmManager.getSession().users().getConsentByClient(realm, john.getId(), fooClient.getId());
 
         // Remove foo protocol mapper from johnConsent
         ProtocolMapperModel protMapperModel = fooClient.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, "foo");
@@ -168,14 +168,14 @@ public class UserConsentModelTest extends AbstractModelTest {
         RoleModel newRealmRole = realm.addRole("new-realm-role");
         johnConsent.addGrantedRole(newRealmRole);
 
-        realmManager.getSession().users().updateConsent(realm, john, johnConsent);
+        realmManager.getSession().users().updateConsent(realm, john.getId(), johnConsent);
 
         commit();
 
         realm = realmManager.getRealm("original");
         fooClient = realm.getClientByClientId("foo-client");
         john = session.users().getUserByUsername("john", realm);
-        johnConsent = realmManager.getSession().users().getConsentByClient(realm, john, fooClient.getId());
+        johnConsent = realmManager.getSession().users().getConsentByClient(realm, john.getId(), fooClient.getId());
 
         Assert.assertEquals(johnConsent.getGrantedRoles().size(), 2);
         Assert.assertEquals(johnConsent.getGrantedProtocolMappers().size(), 0);
@@ -191,13 +191,13 @@ public class UserConsentModelTest extends AbstractModelTest {
         ClientModel fooClient = realm.getClientByClientId("foo-client");
         UserModel john = session.users().getUserByUsername("john", realm);
 
-        realmManager.getSession().users().revokeConsentForClient(realm, john, fooClient.getId());
+        realmManager.getSession().users().revokeConsentForClient(realm, john.getId(), fooClient.getId());
 
         commit();
 
         realm = realmManager.getRealm("original");
         john = session.users().getUserByUsername("john", realm);
-        Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, john, fooClient.getId()));
+        Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, john.getId(), fooClient.getId()));
     }
 
     @Test
@@ -220,7 +220,7 @@ public class UserConsentModelTest extends AbstractModelTest {
         realm = realmManager.getRealm("original");
         fooClient = realm.getClientByClientId("foo-client");
         UserModel john = session.users().getUserByUsername("john", realm);
-        UserConsentModel johnConsent = realmManager.getSession().users().getConsentByClient(realm, john, fooClient.getId());
+        UserConsentModel johnConsent = realmManager.getSession().users().getConsentByClient(realm, john.getId(), fooClient.getId());
 
         Assert.assertEquals(johnConsent.getGrantedRoles().size(), 2);
         Assert.assertEquals(johnConsent.getGrantedProtocolMappers().size(), 0);
@@ -239,7 +239,7 @@ public class UserConsentModelTest extends AbstractModelTest {
         ClientModel fooClient = realm.getClientByClientId("foo-client");
         ClientModel barClient = realm.getClientByClientId("bar-client");
         UserModel john = session.users().getUserByUsername("john", realm);
-        UserConsentModel johnConsent = realmManager.getSession().users().getConsentByClient(realm, john, fooClient.getId());
+        UserConsentModel johnConsent = realmManager.getSession().users().getConsentByClient(realm, john.getId(), fooClient.getId());
 
         Assert.assertEquals(johnConsent.getGrantedRoles().size(), 1);
         Assert.assertEquals(johnConsent.getGrantedProtocolMappers().size(), 1);
@@ -261,13 +261,13 @@ public class UserConsentModelTest extends AbstractModelTest {
 
         UserModel john = session.users().getUserByUsername("john", realm);
 
-        UserConsentModel johnFooConsent = realmManager.getSession().users().getConsentByClient(realm, john, fooClient.getId());
+        UserConsentModel johnFooConsent = realmManager.getSession().users().getConsentByClient(realm, john.getId(), fooClient.getId());
         Assert.assertEquals(johnFooConsent.getGrantedRoles().size(), 1);
         Assert.assertEquals(johnFooConsent.getGrantedProtocolMappers().size(), 1);
         Assert.assertTrue(isRoleGranted(realm, "realm-role", johnFooConsent));
         Assert.assertTrue(isMapperGranted(fooClient, "foo", johnFooConsent));
 
-        Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, john, barClient.getId()));
+        Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, john.getId(), barClient.getId()));
     }
 
     private boolean isRoleGranted(RoleContainerModel roleContainer, String roleName, UserConsentModel consentModel) {