keycloak-memoizeit

Merge pull request #3541 from patriot1burke/master port

11/22/2016 5:47:34 PM

Changes

Details

diff --git a/federation/kerberos/pom.xml b/federation/kerberos/pom.xml
index 5913c2d..a169fe2 100755
--- a/federation/kerberos/pom.xml
+++ b/federation/kerberos/pom.xml
@@ -28,6 +28,10 @@
     <artifactId>keycloak-kerberos-federation</artifactId>
     <name>Keycloak Kerberos Federation</name>
     <description />
+    <properties>
+        <maven.compiler.target>1.8</maven.compiler.target>
+        <maven.compiler.source>1.8</maven.compiler.source>
+    </properties>
 
     <dependencies>
         <dependency>
diff --git a/federation/kerberos/src/main/java/org/keycloak/federation/kerberos/CommonKerberosConfig.java b/federation/kerberos/src/main/java/org/keycloak/federation/kerberos/CommonKerberosConfig.java
index ed6c495..4689190 100644
--- a/federation/kerberos/src/main/java/org/keycloak/federation/kerberos/CommonKerberosConfig.java
+++ b/federation/kerberos/src/main/java/org/keycloak/federation/kerberos/CommonKerberosConfig.java
@@ -19,7 +19,6 @@ package org.keycloak.federation.kerberos;
 
 import org.keycloak.common.constants.KerberosConstants;
 import org.keycloak.component.ComponentModel;
-import org.keycloak.models.UserFederationProviderModel;
 
 import java.util.Map;
 
@@ -30,45 +29,32 @@ import java.util.Map;
  */
 public abstract class CommonKerberosConfig {
 
-    protected UserFederationProviderModel providerModel;
     protected ComponentModel componentModel;
 
-    public CommonKerberosConfig(UserFederationProviderModel userFederationProvider) {
-        this.providerModel = userFederationProvider;
-    }
-
     public CommonKerberosConfig(ComponentModel componentModel) {
         this.componentModel = componentModel;
     }
 
     // Should be always true for KerberosFederationProvider
     public boolean isAllowKerberosAuthentication() {
-        if (providerModel != null) return Boolean.valueOf(getConfig().get(KerberosConstants.ALLOW_KERBEROS_AUTHENTICATION));
-        else return Boolean.valueOf(componentModel.getConfig().getFirst(KerberosConstants.ALLOW_KERBEROS_AUTHENTICATION));
+        return Boolean.valueOf(componentModel.getConfig().getFirst(KerberosConstants.ALLOW_KERBEROS_AUTHENTICATION));
     }
 
     public String getKerberosRealm() {
-        if (providerModel != null) return getConfig().get(KerberosConstants.KERBEROS_REALM);
-        else return componentModel.getConfig().getFirst(KerberosConstants.KERBEROS_REALM);
+        return componentModel.getConfig().getFirst(KerberosConstants.KERBEROS_REALM);
     }
 
     public String getServerPrincipal() {
-        if (providerModel != null) return getConfig().get(KerberosConstants.SERVER_PRINCIPAL);
-        else return componentModel.getConfig().getFirst(KerberosConstants.SERVER_PRINCIPAL);
+        return componentModel.getConfig().getFirst(KerberosConstants.SERVER_PRINCIPAL);
     }
 
     public String getKeyTab() {
-        if (providerModel != null) return getConfig().get(KerberosConstants.KEYTAB);
-        else return componentModel.getConfig().getFirst(KerberosConstants.KEYTAB);
+        return componentModel.getConfig().getFirst(KerberosConstants.KEYTAB);
     }
 
     public boolean isDebug() {
-        if (providerModel != null) return Boolean.valueOf(getConfig().get(KerberosConstants.DEBUG));
-        else return Boolean.valueOf(componentModel.getConfig().getFirst(KerberosConstants.DEBUG));
+        return Boolean.valueOf(componentModel.getConfig().getFirst(KerberosConstants.DEBUG));
     }
 
-    protected Map<String, String> getConfig() {
-        return providerModel.getConfig();
-    }
 
 }
diff --git a/federation/kerberos/src/main/java/org/keycloak/federation/kerberos/KerberosConfig.java b/federation/kerberos/src/main/java/org/keycloak/federation/kerberos/KerberosConfig.java
index 1b771c3..83b9837 100644
--- a/federation/kerberos/src/main/java/org/keycloak/federation/kerberos/KerberosConfig.java
+++ b/federation/kerberos/src/main/java/org/keycloak/federation/kerberos/KerberosConfig.java
@@ -18,9 +18,12 @@
 package org.keycloak.federation.kerberos;
 
 import org.keycloak.common.constants.KerberosConstants;
+import org.keycloak.component.ComponentModel;
 import org.keycloak.models.LDAPConstants;
 import org.keycloak.models.UserFederationProvider;
 import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.storage.UserStorageProvider;
+import org.keycloak.storage.UserStorageProvider.EditMode;
 
 /**
  * Configuration specific to {@link KerberosFederationProvider}
@@ -29,25 +32,25 @@ import org.keycloak.models.UserFederationProviderModel;
  */
 public class KerberosConfig extends CommonKerberosConfig {
 
-    public KerberosConfig(UserFederationProviderModel userFederationProvider) {
-        super(userFederationProvider);
+    public KerberosConfig(ComponentModel component) {
+        super(component);
     }
 
-    public UserFederationProvider.EditMode getEditMode() {
-        String editModeString = getConfig().get(LDAPConstants.EDIT_MODE);
+    public EditMode getEditMode() {
+        String editModeString = componentModel.getConfig().getFirst(LDAPConstants.EDIT_MODE);
         if (editModeString == null) {
-            return UserFederationProvider.EditMode.UNSYNCED;
+            return EditMode.UNSYNCED;
         } else {
-            return UserFederationProvider.EditMode.valueOf(editModeString);
+            return EditMode.valueOf(editModeString);
         }
     }
 
     public boolean isAllowPasswordAuthentication() {
-        return Boolean.valueOf(getConfig().get(KerberosConstants.ALLOW_PASSWORD_AUTHENTICATION));
+        return Boolean.valueOf(componentModel.getConfig().getFirst(KerberosConstants.ALLOW_PASSWORD_AUTHENTICATION));
     }
 
     public boolean isUpdateProfileFirstLogin() {
-        return Boolean.valueOf(getConfig().get(KerberosConstants.UPDATE_PROFILE_FIRST_LOGIN));
+        return Boolean.valueOf(componentModel.getConfig().getFirst(KerberosConstants.UPDATE_PROFILE_FIRST_LOGIN));
     }
 
 }
diff --git a/federation/kerberos/src/main/java/org/keycloak/federation/kerberos/KerberosFederationProvider.java b/federation/kerberos/src/main/java/org/keycloak/federation/kerberos/KerberosFederationProvider.java
index b5f4709..c0ce941 100755
--- a/federation/kerberos/src/main/java/org/keycloak/federation/kerberos/KerberosFederationProvider.java
+++ b/federation/kerberos/src/main/java/org/keycloak/federation/kerberos/KerberosFederationProvider.java
@@ -19,7 +19,10 @@ package org.keycloak.federation.kerberos;
 
 import org.jboss.logging.Logger;
 import org.keycloak.common.constants.KerberosConstants;
+import org.keycloak.credential.CredentialAuthentication;
 import org.keycloak.credential.CredentialInput;
+import org.keycloak.credential.CredentialInputUpdater;
+import org.keycloak.credential.CredentialInputValidator;
 import org.keycloak.credential.CredentialModel;
 import org.keycloak.federation.kerberos.impl.KerberosUsernamePasswordAuthenticator;
 import org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator;
@@ -34,6 +37,10 @@ import org.keycloak.models.UserFederationProvider;
 import org.keycloak.models.UserFederationProviderModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.UserManager;
+import org.keycloak.storage.UserStorageProvider;
+import org.keycloak.storage.UserStorageProviderModel;
+import org.keycloak.storage.user.ImportedUserValidation;
+import org.keycloak.storage.user.UserLookupProvider;
 
 import java.util.Collections;
 import java.util.HashMap;
@@ -45,17 +52,22 @@ import java.util.Set;
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
  */
-public class KerberosFederationProvider implements UserFederationProvider {
+public class KerberosFederationProvider implements UserStorageProvider,
+        UserLookupProvider,
+        CredentialInputValidator,
+        CredentialInputUpdater,
+        CredentialAuthentication,
+        ImportedUserValidation {
 
     private static final Logger logger = Logger.getLogger(KerberosFederationProvider.class);
     public static final String KERBEROS_PRINCIPAL = "KERBEROS_PRINCIPAL";
 
     protected KeycloakSession session;
-    protected UserFederationProviderModel model;
+    protected UserStorageProviderModel model;
     protected KerberosConfig kerberosConfig;
     protected KerberosFederationProviderFactory factory;
 
-    public KerberosFederationProvider(KeycloakSession session,UserFederationProviderModel model, KerberosFederationProviderFactory factory) {
+    public KerberosFederationProvider(KeycloakSession session, UserStorageProviderModel model, KerberosFederationProviderFactory factory) {
         this.session = session;
         this.model = model;
         this.kerberosConfig = new KerberosConfig(model);
@@ -63,35 +75,20 @@ public class KerberosFederationProvider implements UserFederationProvider {
     }
 
     @Override
-    public UserModel validateAndProxy(RealmModel realm, UserModel local) {
-        if (!isValid(realm, local)) {
+    public UserModel validate(RealmModel realm, UserModel user) {
+        if (!isValid(realm, user)) {
             return null;
         }
 
         if (kerberosConfig.getEditMode() == EditMode.READ_ONLY) {
-            return new ReadOnlyKerberosUserModelDelegate(local, this);
+            return new ReadOnlyKerberosUserModelDelegate(user, this);
         } else {
-            return local;
+            return user;
         }
     }
 
     @Override
-    public boolean synchronizeRegistrations() {
-        return false;
-    }
-
-    @Override
-    public UserModel register(RealmModel realm, UserModel user) {
-        return null;
-    }
-
-    @Override
-    public boolean removeUser(RealmModel realm, UserModel user) {
-        return true;
-    }
-
-    @Override
-    public UserModel getUserByUsername(RealmModel realm, String username) {
+    public UserModel getUserByUsername(String username, RealmModel realm) {
         KerberosUsernamePasswordAuthenticator authenticator = factory.createKerberosUsernamePasswordAuthenticator(kerberosConfig);
         if (authenticator.isUserAvailable(username)) {
             // Case when method was called with username including kerberos realm like john@REALM.ORG . Authenticator already checked that kerberos realm was correct
@@ -106,18 +103,13 @@ public class KerberosFederationProvider implements UserFederationProvider {
     }
 
     @Override
-    public UserModel getUserByEmail(RealmModel realm, String email) {
+    public UserModel getUserByEmail(String email, RealmModel realm) {
         return null;
     }
 
     @Override
-    public List<UserModel> searchByAttributes(Map<String, String> attributes, RealmModel realm, int maxResults) {
-        return Collections.emptyList();
-    }
-
-    @Override
-    public List<UserModel> getGroupMembers(RealmModel realm, GroupModel group, int firstResult, int maxResults) {
-        return Collections.emptyList();
+    public UserModel getUserById(String id, RealmModel realm) {
+        return null;
     }
 
     @Override
@@ -135,7 +127,6 @@ public class KerberosFederationProvider implements UserFederationProvider {
 
     }
 
-    @Override
     public boolean isValid(RealmModel realm, UserModel local) {
         // KerberosUsernamePasswordAuthenticator.isUserAvailable is an overhead, so avoid it for now
 
@@ -144,13 +135,6 @@ public class KerberosFederationProvider implements UserFederationProvider {
     }
 
     @Override
-    public Set<String> getSupportedCredentialTypes() {
-        Set<String> supportedCredTypes = new HashSet<String>();
-        supportedCredTypes.add(UserCredentialModel.KERBEROS);
-        return supportedCredTypes;
-    }
-
-    @Override
     public boolean updateCredential(RealmModel realm, UserModel user, CredentialInput input) {
         if (!(input instanceof UserCredentialModel) || !CredentialModel.PASSWORD.equals(input.getType())) return false;
         if (kerberosConfig.getEditMode() == EditMode.READ_ONLY) {
@@ -175,6 +159,11 @@ public class KerberosFederationProvider implements UserFederationProvider {
     }
 
     @Override
+    public boolean supportsCredentialAuthenticationFor(String type) {
+        return CredentialModel.KERBEROS.equals(type);
+    }
+
+    @Override
     public boolean isConfiguredFor(RealmModel realm, UserModel user, String credentialType) {
         return supportsCredentialType(credentialType);
     }
@@ -199,7 +188,9 @@ public class KerberosFederationProvider implements UserFederationProvider {
     }
 
     @Override
-    public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel credential) {
+    public CredentialValidationOutput authenticate(RealmModel realm, CredentialInput input) {
+        if (!(input instanceof UserCredentialModel)) return null;
+        UserCredentialModel credential = (UserCredentialModel)input;
         if (credential.getType().equals(UserCredentialModel.KERBEROS)) {
             String spnegoToken = credential.getValue();
             SPNEGOAuthenticator spnegoAuthenticator = factory.createSPNEGOAuthenticator(spnegoToken, kerberosConfig);
@@ -226,7 +217,7 @@ public class KerberosFederationProvider implements UserFederationProvider {
             }
 
         } else {
-            return CredentialValidationOutput.failed();
+            return null;
         }
     }
 
@@ -243,22 +234,23 @@ public class KerberosFederationProvider implements UserFederationProvider {
      * @return user if found or successfully created. Null if user with same username already exists, but is not linked to this provider
      */
     protected UserModel findOrCreateAuthenticatedUser(RealmModel realm, String username) {
-        UserModel user = session.userStorage().getUserByUsername(username, realm);
+        UserModel user = session.userLocalStorage().getUserByUsername(username, realm);
         if (user != null) {
+            user = session.users().getUserById(user.getId(), realm);  // make sure we get a cached instance
             logger.debug("Kerberos authenticated user " + username + " found in Keycloak storage");
 
             if (!model.getId().equals(user.getFederationLink())) {
-                logger.warn("User with username " + username + " already exists, but is not linked to provider [" + model.getDisplayName() + "]");
+                logger.warn("User with username " + username + " already exists, but is not linked to provider [" + model.getName() + "]");
                 return null;
             } else {
-                UserModel proxied = validateAndProxy(realm, user);
+                UserModel proxied = validate(realm, user);
                 if (proxied != null) {
                     return proxied;
                 } else {
-                    logger.warn("User with username " + username + " already exists and is linked to provider [" + model.getDisplayName() +
+                    logger.warn("User with username " + username + " already exists and is linked to provider [" + model.getName() +
                             "] but kerberos principal is not correct. Kerberos principal on user is: " + user.getFirstAttribute(KERBEROS_PRINCIPAL));
                     logger.warn("Will re-create user");
-                    new UserManager(session).removeUser(realm, user, session.userStorage());
+                    new UserManager(session).removeUser(realm, user, session.userLocalStorage());
                 }
             }
         }
@@ -272,7 +264,7 @@ public class KerberosFederationProvider implements UserFederationProvider {
         String email = username + "@" + kerberosConfig.getKerberosRealm().toLowerCase();
 
         logger.debugf("Creating kerberos user: %s, email: %s to local Keycloak storage", username, email);
-        UserModel user = session.userStorage().addUser(realm, username);
+        UserModel user = session.userLocalStorage().addUser(realm, username);
         user.setEnabled(true);
         user.setEmail(email);
         user.setFederationLink(model.getId());
@@ -282,6 +274,6 @@ public class KerberosFederationProvider implements UserFederationProvider {
             user.addRequiredAction(UserModel.RequiredAction.UPDATE_PROFILE);
         }
 
-        return validateAndProxy(realm, user);
+        return validate(realm, user);
     }
 }
diff --git a/federation/kerberos/src/main/java/org/keycloak/federation/kerberos/KerberosFederationProviderFactory.java b/federation/kerberos/src/main/java/org/keycloak/federation/kerberos/KerberosFederationProviderFactory.java
index 3e713df..e7aa027 100755
--- a/federation/kerberos/src/main/java/org/keycloak/federation/kerberos/KerberosFederationProviderFactory.java
+++ b/federation/kerberos/src/main/java/org/keycloak/federation/kerberos/KerberosFederationProviderFactory.java
@@ -19,18 +19,29 @@ package org.keycloak.federation.kerberos;
 
 import org.jboss.logging.Logger;
 import org.keycloak.Config;
+import org.keycloak.common.constants.KerberosConstants;
+import org.keycloak.component.ComponentModel;
+import org.keycloak.component.ComponentValidationException;
 import org.keycloak.federation.kerberos.impl.KerberosServerSubjectAuthenticator;
 import org.keycloak.federation.kerberos.impl.KerberosUsernamePasswordAuthenticator;
 import org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.LDAPConstants;
+import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserFederationProvider;
 import org.keycloak.models.UserFederationProviderFactory;
 import org.keycloak.models.UserFederationProviderModel;
 import org.keycloak.models.UserFederationSyncResult;
+import org.keycloak.provider.ProviderConfigProperty;
+import org.keycloak.provider.ProviderConfigurationBuilder;
+import org.keycloak.storage.UserStorageProvider;
+import org.keycloak.storage.UserStorageProviderFactory;
+import org.keycloak.storage.UserStorageProviderModel;
 
 import java.util.Collections;
 import java.util.Date;
+import java.util.List;
 import java.util.Set;
 
 /**
@@ -39,18 +50,14 @@ import java.util.Set;
  *
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
  */
-public class KerberosFederationProviderFactory implements UserFederationProviderFactory {
+public class KerberosFederationProviderFactory implements UserStorageProviderFactory<KerberosFederationProvider> {
 
     private static final Logger logger = Logger.getLogger(KerberosFederationProviderFactory.class);
     public static final String PROVIDER_NAME = "kerberos";
-    @Override
-    public UserFederationProvider getInstance(KeycloakSession session, UserFederationProviderModel model) {
-        return new KerberosFederationProvider(session, model, this);
-    }
 
     @Override
-    public Set<String> getConfigurationOptions() {
-        return Collections.emptySet();
+    public KerberosFederationProvider create(KeycloakSession session, ComponentModel model) {
+        return new KerberosFederationProvider(session, new UserStorageProviderModel(model), this);
     }
 
     @Override
@@ -58,23 +65,62 @@ public class KerberosFederationProviderFactory implements UserFederationProvider
         return PROVIDER_NAME;
     }
 
-    @Override
-    public UserFederationSyncResult syncAllUsers(KeycloakSessionFactory sessionFactory, String realmId, UserFederationProviderModel model) {
-        logger.warn("Sync users not supported for this provider");
-        return UserFederationSyncResult.empty();
+    protected static final List<ProviderConfigProperty> configProperties;
+
+    static {
+        configProperties = getConfigProps();
     }
 
-    @Override
-    public UserFederationSyncResult syncChangedUsers(KeycloakSessionFactory sessionFactory, String realmId, UserFederationProviderModel model, Date lastSync) {
-        logger.warn("Sync users not supported for this provider");
-        return UserFederationSyncResult.empty();
+    private static List<ProviderConfigProperty> getConfigProps() {
+        return ProviderConfigurationBuilder.create()
+                .property().name(KerberosConstants.KERBEROS_REALM)
+                .label("kerberos-realm")
+                .helpText("kerberos-realm.tooltip")
+                .type(ProviderConfigProperty.STRING_TYPE)
+                .add()
+                .property().name(KerberosConstants.SERVER_PRINCIPAL)
+                .label("server-principal")
+                .helpText("server-principal.tooltip")
+                .type(ProviderConfigProperty.STRING_TYPE)
+                .add()
+                .property().name(KerberosConstants.KEYTAB)
+                .label("keytab")
+                .helpText("keytab.tooltip")
+                .type(ProviderConfigProperty.STRING_TYPE)
+                .add()
+                .property().name(KerberosConstants.DEBUG)
+                .label("debug")
+                .helpText("debug.tooltip")
+                .type(ProviderConfigProperty.BOOLEAN_TYPE)
+                .defaultValue("false")
+                .add()
+                .property().name(KerberosConstants.ALLOW_PASSWORD_AUTHENTICATION)
+                .label("allow-password-authentication")
+                .helpText("allow-password-authentication.tooltip")
+                .type(ProviderConfigProperty.BOOLEAN_TYPE)
+                .defaultValue("false")
+                .add()
+                .property().name(LDAPConstants.EDIT_MODE)
+                .label("edit-mode")
+                .helpText("edit-mode.tooltip")
+                .type(ProviderConfigProperty.LIST_TYPE)
+                .options(UserStorageProvider.EditMode.READ_ONLY.toString(), UserStorageProvider.EditMode.UNSYNCED.toString())
+                .add()
+                .property().name(KerberosConstants.UPDATE_PROFILE_FIRST_LOGIN)
+                .label("update-profile-first-login")
+                .helpText("update-profile-first-login.tooltip")
+                .type(ProviderConfigProperty.BOOLEAN_TYPE)
+                .defaultValue("false")
+                .add()
+                .build();
     }
 
-    @Override
-    public UserFederationProvider create(KeycloakSession session) {
-        throw new IllegalAccessError("Illegal to call this method");
+     @Override
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return configProperties;
     }
 
+
     @Override
     public void init(Config.Scope config) {
 
diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPConfig.java b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPConfig.java
index e5d497b..ec2e32c 100644
--- a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPConfig.java
+++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPConfig.java
@@ -19,6 +19,7 @@ package org.keycloak.storage.ldap;
 
 import org.keycloak.common.util.MultivaluedHashMap;
 import org.keycloak.models.LDAPConstants;
+import org.keycloak.storage.UserStorageProvider;
 
 import javax.naming.directory.SearchControls;
 import java.util.Collection;
@@ -171,12 +172,12 @@ public class LDAPConfig {
         return null;
     }
 
-    public LDAPStorageProviderFactory.EditMode getEditMode() {
+    public UserStorageProvider.EditMode getEditMode() {
         String editModeString = config.getFirst(LDAPConstants.EDIT_MODE);
         if (editModeString == null) {
-            return LDAPStorageProviderFactory.EditMode.READ_ONLY;
+            return UserStorageProvider.EditMode.READ_ONLY;
         } else {
-            return LDAPStorageProviderFactory.EditMode.valueOf(editModeString);
+            return UserStorageProvider.EditMode.valueOf(editModeString);
         }
     }
 }
diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProvider.java b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProvider.java
index 73923bb..4d91efb 100755
--- a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProvider.java
+++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProvider.java
@@ -85,7 +85,7 @@ public class LDAPStorageProvider implements UserStorageProvider,
     protected KeycloakSession session;
     protected ComponentModel model;
     protected LDAPIdentityStore ldapIdentityStore;
-    protected LDAPStorageProviderFactory.EditMode editMode;
+    protected EditMode editMode;
     protected LDAPProviderKerberosConfig kerberosConfig;
     protected PasswordUpdated updater;
 
@@ -117,7 +117,7 @@ public class LDAPStorageProvider implements UserStorageProvider,
         return this.ldapIdentityStore;
     }
 
-    public LDAPStorageProviderFactory.EditMode getEditMode() {
+    public EditMode getEditMode() {
         return editMode;
     }
 
@@ -174,12 +174,12 @@ public class LDAPStorageProvider implements UserStorageProvider,
     }
 
     public boolean synchronizeRegistrations() {
-        return "true".equalsIgnoreCase(model.getConfig().getFirst(LDAPConstants.SYNC_REGISTRATIONS)) && editMode == LDAPStorageProviderFactory.EditMode.WRITABLE;
+        return "true".equalsIgnoreCase(model.getConfig().getFirst(LDAPConstants.SYNC_REGISTRATIONS)) && editMode == UserStorageProvider.EditMode.WRITABLE;
     }
 
     @Override
     public UserModel addUser(RealmModel realm, String username) {
-        if (editMode == LDAPStorageProviderFactory.EditMode.READ_ONLY || editMode == LDAPStorageProviderFactory.EditMode.UNSYNCED) throw new IllegalStateException("Registration is not supported by this ldap server");
+        if (editMode == UserStorageProvider.EditMode.READ_ONLY || editMode == UserStorageProvider.EditMode.UNSYNCED) throw new IllegalStateException("Registration is not supported by this ldap server");
         if (!synchronizeRegistrations()) throw new IllegalStateException("Registration is not supported by this ldap server");
         UserModel user = session.userLocalStorage().addUser(realm, username);
         user.setFederationLink(model.getId());
@@ -193,7 +193,7 @@ public class LDAPStorageProvider implements UserStorageProvider,
 
     @Override
     public boolean removeUser(RealmModel realm, UserModel user) {
-        if (editMode == LDAPStorageProviderFactory.EditMode.READ_ONLY || editMode == LDAPStorageProviderFactory.EditMode.UNSYNCED) {
+        if (editMode == UserStorageProvider.EditMode.READ_ONLY || editMode == UserStorageProvider.EditMode.UNSYNCED) {
             logger.warnf("User '%s' can't be deleted in LDAP as editMode is '%s'. Deleting user just from Keycloak DB, but he will be re-imported from LDAP again once searched in Keycloak", user.getUsername(), editMode.toString());
             return true;
         }
@@ -479,10 +479,10 @@ public class LDAPStorageProvider implements UserStorageProvider,
     @Override
     public boolean updateCredential(RealmModel realm, UserModel user, CredentialInput input) {
         if (!CredentialModel.PASSWORD.equals(input.getType()) || ! (input instanceof UserCredentialModel)) return false;
-        if (editMode == LDAPStorageProviderFactory.EditMode.READ_ONLY) {
+        if (editMode == UserStorageProvider.EditMode.READ_ONLY) {
             throw new ModelReadOnlyException("Federated storage is not writable");
 
-        } else if (editMode == LDAPStorageProviderFactory.EditMode.WRITABLE) {
+        } else if (editMode == UserStorageProvider.EditMode.WRITABLE) {
             LDAPIdentityStore ldapIdentityStore = getLdapIdentityStore();
             UserCredentialModel cred = (UserCredentialModel)input;
             String password = cred.getValue();
diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProviderFactory.java b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProviderFactory.java
index 2401b49..86db2d9 100755
--- a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProviderFactory.java
+++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProviderFactory.java
@@ -63,27 +63,6 @@ import java.util.List;
  */
 public class LDAPStorageProviderFactory implements UserStorageProviderFactory<LDAPStorageProvider>, ImportSynchronization {
 
-    /**
-     * Optional type that can be by implementations to describe edit mode of federation storage
-     *
-     */
-    public enum EditMode {
-        /**
-         * federation storage is read-only
-         */
-        READ_ONLY,
-        /**
-         * federation storage is writable
-         *
-         */
-        WRITABLE,
-        /**
-         * updates to user are stored locally and not synced with federation storage.
-         *
-         */
-        UNSYNCED
-    }
-
 
     private static final Logger logger = Logger.getLogger(LDAPStorageProviderFactory.class);
     public static final String PROVIDER_NAME = LDAPConstants.LDAP_PROVIDER;
@@ -100,7 +79,7 @@ public class LDAPStorageProviderFactory implements UserStorageProviderFactory<LD
         boolean readOnly = false;
         if (parent != null) {
             LDAPConfig config = new LDAPConfig(parent.getConfig());
-            readOnly = config.getEditMode() != LDAPStorageProviderFactory.EditMode.WRITABLE;
+            readOnly = config.getEditMode() != UserStorageProvider.EditMode.WRITABLE;
         }
 
 
@@ -229,11 +208,11 @@ public class LDAPStorageProviderFactory implements UserStorageProviderFactory<LD
         LDAPConfig ldapConfig = new LDAPConfig(model.getConfig());
 
         boolean activeDirectory = ldapConfig.isActiveDirectory();
-        EditMode editMode = ldapConfig.getEditMode();
-        String readOnly = String.valueOf(editMode == EditMode.READ_ONLY || editMode == EditMode.UNSYNCED);
+        UserStorageProvider.EditMode editMode = ldapConfig.getEditMode();
+        String readOnly = String.valueOf(editMode == UserStorageProvider.EditMode.READ_ONLY || editMode == UserStorageProvider.EditMode.UNSYNCED);
         String usernameLdapAttribute = ldapConfig.getUsernameLdapAttribute();
 
-        String alwaysReadValueFromLDAP = String.valueOf(editMode==EditMode.READ_ONLY || editMode== EditMode.WRITABLE);
+        String alwaysReadValueFromLDAP = String.valueOf(editMode== UserStorageProvider.EditMode.READ_ONLY || editMode== UserStorageProvider.EditMode.WRITABLE);
 
         ComponentModel mapperModel;
         mapperModel = KeycloakModelUtils.createComponentModel("username", model.getId(), UserAttributeLDAPStorageMapperFactory.PROVIDER_ID, LDAPStorageMapper.class.getName(),
@@ -259,7 +238,7 @@ public class LDAPStorageProviderFactory implements UserStorageProviderFactory<LD
                 realm.addComponentModel(mapperModel);
 
             } else {
-                if (editMode == EditMode.WRITABLE) {
+                if (editMode == UserStorageProvider.EditMode.WRITABLE) {
 
                     // For AD deployments with "sAMAccountName" as username and writable, we need to map "cn" as username as well (this is needed so we can register new users from KC into LDAP) and we will map "givenName" to first name.
                     mapperModel = KeycloakModelUtils.createComponentModel("first name", model.getId(), UserAttributeLDAPStorageMapperFactory.PROVIDER_ID,LDAPStorageMapper.class.getName(),
diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/FullNameLDAPStorageMapper.java b/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/FullNameLDAPStorageMapper.java
index 1806ecd..ba43bc6 100644
--- a/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/FullNameLDAPStorageMapper.java
+++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/FullNameLDAPStorageMapper.java
@@ -21,8 +21,8 @@ import org.keycloak.component.ComponentModel;
 import org.keycloak.models.LDAPConstants;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserModel;
+import org.keycloak.storage.UserStorageProvider;
 import org.keycloak.storage.ldap.LDAPStorageProvider;
-import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
 import org.keycloak.storage.ldap.idm.model.LDAPObject;
 import org.keycloak.storage.ldap.idm.query.Condition;
 import org.keycloak.storage.ldap.idm.query.internal.EqualCondition;
@@ -84,7 +84,7 @@ public class FullNameLDAPStorageMapper extends AbstractLDAPStorageMapper {
 
     @Override
     public UserModel proxy(LDAPObject ldapUser, UserModel delegate) {
-        if (ldapProvider.getEditMode() == LDAPStorageProviderFactory.EditMode.WRITABLE && !isReadOnly()) {
+        if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE && !isReadOnly()) {
 
 
             TxAwareLDAPUserModelDelegate txDelegate = new TxAwareLDAPUserModelDelegate(delegate, ldapProvider, ldapUser) {
diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/FullNameLDAPStorageMapperFactory.java b/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/FullNameLDAPStorageMapperFactory.java
index 3cfa6c5..aed520d 100755
--- a/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/FullNameLDAPStorageMapperFactory.java
+++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/FullNameLDAPStorageMapperFactory.java
@@ -22,17 +22,13 @@ import org.keycloak.component.ComponentValidationException;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.LDAPConstants;
 import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserFederationProvider;
-import org.keycloak.models.UserFederationProviderModel;
 import org.keycloak.provider.ProviderConfigProperty;
 import org.keycloak.provider.ProviderConfigurationBuilder;
+import org.keycloak.storage.UserStorageProvider;
 import org.keycloak.storage.ldap.LDAPConfig;
 import org.keycloak.storage.ldap.LDAPStorageProvider;
-import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
 
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@@ -51,7 +47,7 @@ public class FullNameLDAPStorageMapperFactory extends AbstractLDAPStorageMapperF
         boolean readOnly = false;
         if (parent != null) {
             LDAPConfig config = new LDAPConfig(parent.getConfig());
-            readOnly = config.getEditMode() != LDAPStorageProviderFactory.EditMode.WRITABLE;
+            readOnly = config.getEditMode() != UserStorageProvider.EditMode.WRITABLE;
         }
 
 
@@ -107,9 +103,9 @@ public class FullNameLDAPStorageMapperFactory extends AbstractLDAPStorageMapperF
 
         }
         LDAPConfig cfg = new LDAPConfig(parent.getConfig());
-        LDAPStorageProviderFactory.EditMode editMode = cfg.getEditMode();
+        UserStorageProvider.EditMode editMode = cfg.getEditMode();
 
-        if (writeOnly && cfg.getEditMode() != LDAPStorageProviderFactory.EditMode.WRITABLE) {
+        if (writeOnly && cfg.getEditMode() != UserStorageProvider.EditMode.WRITABLE) {
             throw new ComponentValidationException("ldapErrorCantWriteOnlyForReadOnlyLdap");
         }
         if (writeOnly && readOnly) {
diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/membership/group/GroupLDAPStorageMapperFactory.java b/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/membership/group/GroupLDAPStorageMapperFactory.java
index b3baf50..6c01c30 100644
--- a/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/membership/group/GroupLDAPStorageMapperFactory.java
+++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/membership/group/GroupLDAPStorageMapperFactory.java
@@ -22,14 +22,11 @@ import org.keycloak.component.ComponentValidationException;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.LDAPConstants;
 import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserFederationProvider;
-import org.keycloak.models.UserFederationProviderModel;
 import org.keycloak.provider.ProviderConfigProperty;
 import org.keycloak.provider.ProviderConfigurationBuilder;
-import org.keycloak.representations.idm.UserFederationMapperSyncConfigRepresentation;
+import org.keycloak.storage.UserStorageProvider;
 import org.keycloak.storage.ldap.LDAPConfig;
 import org.keycloak.storage.ldap.LDAPStorageProvider;
-import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
 import org.keycloak.storage.ldap.LDAPUtils;
 import org.keycloak.storage.ldap.mappers.AbstractLDAPStorageMapper;
 import org.keycloak.storage.ldap.mappers.AbstractLDAPStorageMapperFactory;
@@ -80,7 +77,7 @@ public class GroupLDAPStorageMapperFactory extends AbstractLDAPStorageMapperFact
         if (parent != null) {
             LDAPConfig config = new LDAPConfig(parent.getConfig());
             roleObjectClasses = config.isActiveDirectory() ? LDAPConstants.GROUP : LDAPConstants.GROUP_OF_NAMES;
-            mode = config.getEditMode() == LDAPStorageProviderFactory.EditMode.WRITABLE ? LDAPGroupMapperMode.LDAP_ONLY.toString() : LDAPGroupMapperMode.READ_ONLY.toString();
+            mode = config.getEditMode() == UserStorageProvider.EditMode.WRITABLE ? LDAPGroupMapperMode.LDAP_ONLY.toString() : LDAPGroupMapperMode.READ_ONLY.toString();
         }
         return ProviderConfigurationBuilder.create()
                     .property().name(GroupMapperConfig.GROUPS_DN)
diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/membership/role/RoleLDAPStorageMapperFactory.java b/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/membership/role/RoleLDAPStorageMapperFactory.java
index e2da595..fe4ee3f 100644
--- a/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/membership/role/RoleLDAPStorageMapperFactory.java
+++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/membership/role/RoleLDAPStorageMapperFactory.java
@@ -22,14 +22,11 @@ import org.keycloak.component.ComponentValidationException;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.LDAPConstants;
 import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserFederationProvider;
-import org.keycloak.models.UserFederationProviderModel;
 import org.keycloak.provider.ProviderConfigProperty;
 import org.keycloak.provider.ProviderConfigurationBuilder;
-import org.keycloak.representations.idm.UserFederationMapperSyncConfigRepresentation;
+import org.keycloak.storage.UserStorageProvider;
 import org.keycloak.storage.ldap.LDAPConfig;
 import org.keycloak.storage.ldap.LDAPStorageProvider;
-import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
 import org.keycloak.storage.ldap.LDAPUtils;
 import org.keycloak.storage.ldap.mappers.AbstractLDAPStorageMapper;
 import org.keycloak.storage.ldap.mappers.AbstractLDAPStorageMapperFactory;
@@ -80,7 +77,7 @@ public class RoleLDAPStorageMapperFactory extends AbstractLDAPStorageMapperFacto
         if (parent != null) {
             LDAPConfig config = new LDAPConfig(parent.getConfig());
             roleObjectClasses = config.isActiveDirectory() ? LDAPConstants.GROUP : LDAPConstants.GROUP_OF_NAMES;
-            mode = config.getEditMode() == LDAPStorageProviderFactory.EditMode.WRITABLE ? LDAPGroupMapperMode.LDAP_ONLY.toString() : LDAPGroupMapperMode.READ_ONLY.toString();
+            mode = config.getEditMode() == UserStorageProvider.EditMode.WRITABLE ? LDAPGroupMapperMode.LDAP_ONLY.toString() : LDAPGroupMapperMode.READ_ONLY.toString();
         }
         return ProviderConfigurationBuilder.create()
                     .property().name(RoleMapperConfig.ROLES_DN)
diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/msad/MSADUserAccountControlStorageMapper.java b/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/msad/MSADUserAccountControlStorageMapper.java
index 7ad5228..2a82c04 100644
--- a/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/msad/MSADUserAccountControlStorageMapper.java
+++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/msad/MSADUserAccountControlStorageMapper.java
@@ -25,8 +25,8 @@ import org.keycloak.models.ModelException;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.utils.UserModelDelegate;
+import org.keycloak.storage.UserStorageProvider;
 import org.keycloak.storage.ldap.LDAPStorageProvider;
-import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
 import org.keycloak.storage.ldap.idm.model.LDAPObject;
 import org.keycloak.storage.ldap.idm.query.internal.LDAPQuery;
 import org.keycloak.storage.ldap.mappers.AbstractLDAPStorageMapper;
@@ -64,7 +64,7 @@ public class MSADUserAccountControlStorageMapper extends AbstractLDAPStorageMapp
         // This needs to be read-only and can be set to writable just on demand
         query.addReturningReadOnlyLdapAttribute(LDAPConstants.PWD_LAST_SET);
 
-        if (ldapProvider.getEditMode() != LDAPStorageProviderFactory.EditMode.WRITABLE) {
+        if (ldapProvider.getEditMode() != UserStorageProvider.EditMode.WRITABLE) {
             query.addReturningReadOnlyLdapAttribute(LDAPConstants.USER_ACCOUNT_CONTROL);
         }
     }
@@ -119,7 +119,7 @@ public class MSADUserAccountControlStorageMapper extends AbstractLDAPStorageMapp
     protected boolean processAuthErrorCode(String errorCode, UserModel user) {
         logger.debugf("MSAD Error code is '%s' after failed LDAP login of user '%s'", errorCode, user.getUsername());
 
-        if (ldapProvider.getEditMode() == LDAPStorageProviderFactory.EditMode.WRITABLE) {
+        if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE) {
             if (errorCode.equals("532") || errorCode.equals("773")) {
                 // User needs to change his MSAD password. Allow him to login, but add UPDATE_PASSWORD required action
                 user.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
@@ -200,7 +200,7 @@ public class MSADUserAccountControlStorageMapper extends AbstractLDAPStorageMapp
             // Always update DB
             super.setEnabled(enabled);
 
-            if (ldapProvider.getEditMode() == LDAPStorageProviderFactory.EditMode.WRITABLE && getPwdLastSet() > 0) {
+            if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE && getPwdLastSet() > 0) {
                 logger.debugf("Going to propagate enabled=%s for ldapUser '%s' to MSAD", enabled, ldapUser.getDn().toString());
 
                 UserAccountControl control = getUserAccountControl(ldapUser);
@@ -225,7 +225,7 @@ public class MSADUserAccountControlStorageMapper extends AbstractLDAPStorageMapp
             // Always update DB
             super.addRequiredAction(action);
 
-            if (ldapProvider.getEditMode() == LDAPStorageProviderFactory.EditMode.WRITABLE && RequiredAction.UPDATE_PASSWORD.toString().equals(action)) {
+            if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE && RequiredAction.UPDATE_PASSWORD.toString().equals(action)) {
                 logger.debugf("Going to propagate required action UPDATE_PASSWORD to MSAD for ldap user '%s' ", ldapUser.getDn().toString());
 
                 // Normally it's read-only
@@ -247,7 +247,7 @@ public class MSADUserAccountControlStorageMapper extends AbstractLDAPStorageMapp
             // Always update DB
             super.removeRequiredAction(action);
 
-            if (ldapProvider.getEditMode() == LDAPStorageProviderFactory.EditMode.WRITABLE && RequiredAction.UPDATE_PASSWORD.toString().equals(action)) {
+            if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE && RequiredAction.UPDATE_PASSWORD.toString().equals(action)) {
 
                 // Don't set pwdLastSet in MSAD when it is new user
                 UserAccountControl accountControl = getUserAccountControl(ldapUser);
@@ -267,7 +267,7 @@ public class MSADUserAccountControlStorageMapper extends AbstractLDAPStorageMapp
         public Set<String> getRequiredActions() {
             Set<String> requiredActions = super.getRequiredActions();
 
-            if (ldapProvider.getEditMode() == LDAPStorageProviderFactory.EditMode.WRITABLE) {
+            if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE) {
                 if (getPwdLastSet() == 0 || getUserAccountControl(ldapUser).has(UserAccountControl.PASSWORD_EXPIRED)) {
                     requiredActions = new HashSet<>(requiredActions);
                     requiredActions.add(RequiredAction.UPDATE_PASSWORD.toString());
diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/UserAttributeLDAPStorageMapper.java b/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/UserAttributeLDAPStorageMapper.java
index cd41c5a..5767c05 100644
--- a/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/UserAttributeLDAPStorageMapper.java
+++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/UserAttributeLDAPStorageMapper.java
@@ -29,8 +29,8 @@ import org.keycloak.models.utils.UserModelDelegate;
 import org.keycloak.models.utils.reflection.Property;
 import org.keycloak.models.utils.reflection.PropertyCriteria;
 import org.keycloak.models.utils.reflection.PropertyQueries;
+import org.keycloak.storage.UserStorageProvider;
 import org.keycloak.storage.ldap.LDAPStorageProvider;
-import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
 import org.keycloak.storage.ldap.idm.model.LDAPObject;
 import org.keycloak.storage.ldap.idm.query.Condition;
 import org.keycloak.storage.ldap.idm.query.internal.LDAPQuery;
@@ -179,7 +179,7 @@ public class UserAttributeLDAPStorageMapper extends AbstractLDAPStorageMapper {
         final boolean isMandatoryInLdap = parseBooleanParameter(mapperModel, IS_MANDATORY_IN_LDAP);
 
         // For writable mode, we want to propagate writing of attribute to LDAP as well
-        if (ldapProvider.getEditMode() == LDAPStorageProviderFactory.EditMode.WRITABLE && !isReadOnly()) {
+        if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE && !isReadOnly()) {
 
             delegate = new TxAwareLDAPUserModelDelegate(delegate, ldapProvider, ldapUser) {
 
diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/UserAttributeLDAPStorageMapperFactory.java b/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/UserAttributeLDAPStorageMapperFactory.java
index 99d9ea1..42ad869 100755
--- a/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/UserAttributeLDAPStorageMapperFactory.java
+++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/UserAttributeLDAPStorageMapperFactory.java
@@ -21,17 +21,13 @@ import org.keycloak.component.ComponentModel;
 import org.keycloak.component.ComponentValidationException;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserFederationProvider;
-import org.keycloak.models.UserFederationProviderModel;
 import org.keycloak.provider.ProviderConfigProperty;
 import org.keycloak.provider.ProviderConfigurationBuilder;
+import org.keycloak.storage.UserStorageProvider;
 import org.keycloak.storage.ldap.LDAPConfig;
 import org.keycloak.storage.ldap.LDAPStorageProvider;
-import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
 
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@@ -50,7 +46,7 @@ public class UserAttributeLDAPStorageMapperFactory extends AbstractLDAPStorageMa
         String readOnly = "false";
         if (parent != null) {
             LDAPConfig ldapConfig = new LDAPConfig(parent.getConfig());
-            readOnly = ldapConfig.getEditMode() == LDAPStorageProviderFactory.EditMode.WRITABLE ? "false" : "true";
+            readOnly = ldapConfig.getEditMode() == UserStorageProvider.EditMode.WRITABLE ? "false" : "true";
         }
         return ProviderConfigurationBuilder.create()
                     .property().name(UserAttributeLDAPStorageMapper.USER_MODEL_ATTRIBUTE)
diff --git a/federation/ldap/src/main/resources/META-INF/services/org.keycloak.storage.ldap.mappers.LDAPStorageMapperFactory b/federation/ldap/src/main/resources/META-INF/services/org.keycloak.storage.ldap.mappers.LDAPStorageMapperFactory
index ff1f0f6..6f3f5ae 100644
--- a/federation/ldap/src/main/resources/META-INF/services/org.keycloak.storage.ldap.mappers.LDAPStorageMapperFactory
+++ b/federation/ldap/src/main/resources/META-INF/services/org.keycloak.storage.ldap.mappers.LDAPStorageMapperFactory
@@ -1,3 +1,20 @@
+#
+# 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.
+#
+
 org.keycloak.storage.ldap.mappers.FullNameLDAPStorageMapperFactory
 org.keycloak.storage.ldap.mappers.HardcodedLDAPRoleStorageMapperFactory
 org.keycloak.storage.ldap.mappers.membership.group.GroupLDAPStorageMapperFactory
diff --git a/federation/ldap/src/main/resources/META-INF/services/org.keycloak.storage.UserStorageProviderFactory b/federation/ldap/src/main/resources/META-INF/services/org.keycloak.storage.UserStorageProviderFactory
index 0d8483f..a1da01f 100644
--- a/federation/ldap/src/main/resources/META-INF/services/org.keycloak.storage.UserStorageProviderFactory
+++ b/federation/ldap/src/main/resources/META-INF/services/org.keycloak.storage.UserStorageProviderFactory
@@ -1 +1,18 @@
+#
+# 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.
+#
+
 org.keycloak.storage.ldap.LDAPStorageProviderFactory
\ No newline at end of file
diff --git a/federation/sssd/pom.xml b/federation/sssd/pom.xml
index f8a1a48..789bbe2 100644
--- a/federation/sssd/pom.xml
+++ b/federation/sssd/pom.xml
@@ -13,6 +13,12 @@
     <name>Keycloak SSSD Federation</name>
     <description/>
 
+    <properties>
+        <maven.compiler.target>1.8</maven.compiler.target>
+        <maven.compiler.source>1.8</maven.compiler.source>
+    </properties>
+
+
     <build>
         <plugins>
             <plugin>
diff --git a/federation/sssd/src/main/java/org/keycloak/federation/sssd/SSSDFederationProvider.java b/federation/sssd/src/main/java/org/keycloak/federation/sssd/SSSDFederationProvider.java
index 44662de..fcfc97f 100755
--- a/federation/sssd/src/main/java/org/keycloak/federation/sssd/SSSDFederationProvider.java
+++ b/federation/sssd/src/main/java/org/keycloak/federation/sssd/SSSDFederationProvider.java
@@ -20,6 +20,7 @@ package org.keycloak.federation.sssd;
 import org.freedesktop.dbus.Variant;
 import org.jboss.logging.Logger;
 import org.keycloak.credential.CredentialInput;
+import org.keycloak.credential.CredentialInputValidator;
 import org.keycloak.credential.CredentialModel;
 import org.keycloak.federation.sssd.api.Sssd;
 import org.keycloak.federation.sssd.impl.PAMAuthenticator;
@@ -35,6 +36,9 @@ import org.keycloak.models.UserFederationProviderModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.models.UserManager;
+import org.keycloak.storage.UserStorageProvider;
+import org.keycloak.storage.UserStorageProviderModel;
+import org.keycloak.storage.user.UserLookupProvider;
 
 import java.util.Collections;
 import java.util.HashSet;
@@ -49,16 +53,16 @@ import java.util.Set;
  * @author <a href="mailto:bruno@abstractj.org">Bruno Oliveira</a>
  * @version $Revision: 1 $
  */
-public class SSSDFederationProvider implements UserFederationProvider {
+public class SSSDFederationProvider implements UserStorageProvider, UserLookupProvider, CredentialInputValidator {
 
     private static final Logger logger = Logger.getLogger(SSSDFederationProvider.class);
 
     protected static final Set<String> supportedCredentialTypes = new HashSet<>();
     private final SSSDFederationProviderFactory factory;
     protected KeycloakSession session;
-    protected UserFederationProviderModel model;
+    protected UserStorageProviderModel model;
 
-    public SSSDFederationProvider(KeycloakSession session, UserFederationProviderModel model, SSSDFederationProviderFactory sssdFederationProviderFactory) {
+    public SSSDFederationProvider(KeycloakSession session, UserStorageProviderModel model, SSSDFederationProviderFactory sssdFederationProviderFactory) {
         this.session = session;
         this.model = model;
         this.factory = sssdFederationProviderFactory;
@@ -70,7 +74,7 @@ public class SSSDFederationProvider implements UserFederationProvider {
 
 
     @Override
-    public UserModel getUserByUsername(RealmModel realm, String username) {
+    public UserModel getUserByUsername(String username, RealmModel realm) {
         return findOrCreateAuthenticatedUser(realm, username);
     }
 
@@ -82,22 +86,22 @@ public class SSSDFederationProvider implements UserFederationProvider {
      * @return user if found or successfully created. Null if user with same username already exists, but is not linked to this provider
      */
     protected UserModel findOrCreateAuthenticatedUser(RealmModel realm, String username) {
-        UserModel user = session.userStorage().getUserByUsername(username, realm);
+        UserModel user = session.userLocalStorage().getUserByUsername(username, realm);
         if (user != null) {
             logger.debug("SSSD authenticated user " + username + " found in Keycloak storage");
 
             if (!model.getId().equals(user.getFederationLink())) {
-                logger.warn("User with username " + username + " already exists, but is not linked to provider [" + model.getDisplayName() + "]");
+                logger.warn("User with username " + username + " already exists, but is not linked to provider [" + model.getName() + "]");
                 return null;
             } else {
                 UserModel proxied = validateAndProxy(realm, user);
                 if (proxied != null) {
                     return proxied;
                 } else {
-                    logger.warn("User with username " + username + " already exists and is linked to provider [" + model.getDisplayName() +
+                    logger.warn("User with username " + username + " already exists and is linked to provider [" + model.getName() +
                             "] but principal is not correct.");
                     logger.warn("Will re-create user");
-                    new UserManager(session).removeUser(realm, user, session.userStorage());
+                    new UserManager(session).removeUser(realm, user, session.userLocalStorage());
                 }
             }
         }
@@ -110,7 +114,7 @@ public class SSSDFederationProvider implements UserFederationProvider {
         Sssd sssd = new Sssd(username);
         Map<String, Variant> sssdUser = sssd.getUserAttributes();
         logger.debugf("Creating SSSD user: %s to local Keycloak storage", username);
-        UserModel user = session.userStorage().addUser(realm, username);
+        UserModel user = session.userLocalStorage().addUser(realm, username);
         user.setEnabled(true);
         user.setEmail(Sssd.getRawAttribute(sssdUser.get("mail")));
         user.setFirstName(Sssd.getRawAttribute(sssdUser.get("givenname")));
@@ -127,18 +131,13 @@ public class SSSDFederationProvider implements UserFederationProvider {
     }
 
     @Override
-    public UserModel getUserByEmail(RealmModel realm, String email) {
+    public UserModel getUserById(String id, RealmModel realm) {
         return null;
     }
 
     @Override
-    public List<UserModel> searchByAttributes(Map<String, String> attributes, RealmModel realm, int maxResults) {
-        return Collections.emptyList();
-    }
-
-    @Override
-    public List<UserModel> getGroupMembers(RealmModel realm, GroupModel group, int firstResult, int maxResults) {
-        return Collections.emptyList();
+    public UserModel getUserByEmail(String email, RealmModel realm) {
+        return null;
     }
 
     @Override
@@ -158,34 +157,12 @@ public class SSSDFederationProvider implements UserFederationProvider {
 
     }
 
-    @Override
     public boolean isValid(RealmModel realm, UserModel local) {
         Map<String, Variant> attributes = new Sssd(local.getUsername()).getUserAttributes();
         return Sssd.getRawAttribute(attributes.get("mail")).equalsIgnoreCase(local.getEmail());
     }
 
     @Override
-    public Set<String> getSupportedCredentialTypes() {
-        return supportedCredentialTypes;
-    }
-
-    @Override
-    public boolean updateCredential(RealmModel realm, UserModel user, CredentialInput input) {
-        if (!(input instanceof UserCredentialModel) || !CredentialModel.PASSWORD.equals(input.getType())) return false;
-        throw new ModelReadOnlyException("Federated storage is not writable");
-    }
-
-    @Override
-    public void disableCredentialType(RealmModel realm, UserModel user, String credentialType) {
-
-    }
-
-    @Override
-    public Set<String> getDisableableCredentialTypes(RealmModel realm, UserModel user) {
-        return Collections.EMPTY_SET;
-    }
-
-    @Override
     public boolean supportsCredentialType(String credentialType) {
         return CredentialModel.PASSWORD.equals(credentialType);
     }
@@ -204,12 +181,6 @@ public class SSSDFederationProvider implements UserFederationProvider {
         return (pam.authenticate() != null);
     }
 
-    @Override
-    public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel credential) {
-        return CredentialValidationOutput.failed();
-    }
-
-    @Override
     public UserModel validateAndProxy(RealmModel realm, UserModel local) {
         if (isValid(realm, local)) {
             return new ReadonlySSSDUserModelDelegate(local, this);
@@ -219,21 +190,6 @@ public class SSSDFederationProvider implements UserFederationProvider {
     }
 
     @Override
-    public boolean synchronizeRegistrations() {
-        return false;
-    }
-
-    @Override
-    public UserModel register(RealmModel realm, UserModel user) {
-        throw new IllegalStateException("Registration not supported");
-    }
-
-    @Override
-    public boolean removeUser(RealmModel realm, UserModel user) {
-        return true;
-    }
-
-    @Override
     public void close() {
         Sssd.disconnect();
     }
diff --git a/federation/sssd/src/main/java/org/keycloak/federation/sssd/SSSDFederationProviderFactory.java b/federation/sssd/src/main/java/org/keycloak/federation/sssd/SSSDFederationProviderFactory.java
index 3140e9e..6a0fc05 100755
--- a/federation/sssd/src/main/java/org/keycloak/federation/sssd/SSSDFederationProviderFactory.java
+++ b/federation/sssd/src/main/java/org/keycloak/federation/sssd/SSSDFederationProviderFactory.java
@@ -19,6 +19,7 @@ package org.keycloak.federation.sssd;
 
 import org.jboss.logging.Logger;
 import org.keycloak.Config;
+import org.keycloak.component.ComponentModel;
 import org.keycloak.federation.sssd.api.Sssd;
 import org.keycloak.federation.sssd.impl.PAMAuthenticator;
 import org.keycloak.models.KeycloakSession;
@@ -28,6 +29,8 @@ import org.keycloak.models.UserFederationProviderFactory;
 import org.keycloak.models.UserFederationProviderModel;
 import org.keycloak.models.UserFederationSyncResult;
 import org.keycloak.provider.EnvironmentDependentProviderFactory;
+import org.keycloak.storage.UserStorageProviderFactory;
+import org.keycloak.storage.UserStorageProviderModel;
 
 import java.util.Date;
 import java.util.HashSet;
@@ -37,12 +40,11 @@ import java.util.Set;
  * @author <a href="mailto:bruno@abstractj.org">Bruno Oliveira</a>
  * @version $Revision: 1 $
  */
-public class SSSDFederationProviderFactory implements UserFederationProviderFactory, EnvironmentDependentProviderFactory {
+public class SSSDFederationProviderFactory implements UserStorageProviderFactory<SSSDFederationProvider>, EnvironmentDependentProviderFactory {
 
     private static final String PROVIDER_NAME = "sssd";
     private static final Logger logger = Logger.getLogger(SSSDFederationProvider.class);
 
-    static final Set<String> configOptions = new HashSet<String>();
 
     @Override
     public String getId() {
@@ -50,24 +52,8 @@ public class SSSDFederationProviderFactory implements UserFederationProviderFact
     }
 
     @Override
-    public UserFederationProvider getInstance(KeycloakSession session, UserFederationProviderModel model) {
-        return new SSSDFederationProvider(session, model, this);
-    }
-
-    /**
-     * List the configuration options to render and display in the admin console's generic management page for this
-     * plugin
-     *
-     * @return
-     */
-    @Override
-    public Set<String> getConfigurationOptions() {
-        return configOptions;
-    }
-
-    @Override
-    public UserFederationProvider create(KeycloakSession session) {
-        return null;
+    public SSSDFederationProvider create(KeycloakSession session, ComponentModel model) {
+        return new SSSDFederationProvider(session, new UserStorageProviderModel(model), this);
     }
 
     @Override
@@ -85,18 +71,6 @@ public class SSSDFederationProviderFactory implements UserFederationProviderFact
 
     }
 
-    @Override
-    public UserFederationSyncResult syncAllUsers(KeycloakSessionFactory sessionFactory, final String realmId, final UserFederationProviderModel model) {
-        logger.info("Sync users not supported for this provider");
-        return UserFederationSyncResult.empty();
-    }
-
-    @Override
-    public UserFederationSyncResult syncChangedUsers(KeycloakSessionFactory sessionFactory, final String realmId, final UserFederationProviderModel model, Date lastSync) {
-        logger.info("Sync users not supported for this provider");
-        return UserFederationSyncResult.empty();
-    }
-
     protected PAMAuthenticator createPAMAuthenticator(String username, String... factors) {
         return new PAMAuthenticator(username, factors);
     }
diff --git a/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/custom/MigrateUserFedToComponent.java b/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/custom/MigrateUserFedToComponent.java
new file mode 100644
index 0000000..bb29830
--- /dev/null
+++ b/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/custom/MigrateUserFedToComponent.java
@@ -0,0 +1,45 @@
+/*
+ * 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.connections.jpa.updater.liquibase.custom;
+
+import liquibase.exception.CustomChangeException;
+import liquibase.statement.core.InsertStatement;
+import liquibase.structure.core.Table;
+import org.keycloak.keys.KeyProvider;
+import org.keycloak.models.LDAPConstants;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.storage.UserStorageProvider;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+
+/**
+ * @author <a href="mailto:bburke@redhat.com">Bill Burke</a>
+ */
+public class MigrateUserFedToComponent extends AbstractUserFedToComponent {
+
+    @Override
+    protected void generateStatementsImpl() throws CustomChangeException {
+        convertFedProviderToComponent("kerberos", null);
+    }
+
+    @Override
+    protected String getTaskId() {
+        return "Update 2.4.1.Final";
+    }
+}
diff --git a/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/custom/PortLdapUserFedToComponentModel.java b/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/custom/PortLdapUserFedToComponentModel.java
index cf224b2..dc9e607 100644
--- a/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/custom/PortLdapUserFedToComponentModel.java
+++ b/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/custom/PortLdapUserFedToComponentModel.java
@@ -18,18 +18,10 @@
 package org.keycloak.connections.jpa.updater.liquibase.custom;
 
 import liquibase.exception.CustomChangeException;
-import liquibase.statement.core.InsertStatement;
-import liquibase.structure.core.Table;
-import org.keycloak.keys.KeyProvider;
 import org.keycloak.models.LDAPConstants;
-import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.storage.UserStorageProvider;
-
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
 
 /**
- * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ * @author <a href="mailto:bburke@redhat.com">Bill Burke</a>
  */
 public class PortLdapUserFedToComponentModel extends AbstractUserFedToComponent {
 
diff --git a/model/jpa/src/main/resources/META-INF/jpa-changelog-2.4.1.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-2.4.1.xml
new file mode 100755
index 0000000..216ce65
--- /dev/null
+++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-2.4.1.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+  ~ 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.
+  -->
+
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
+
+     <changeSet author="bburke@redhat.com" id="2.4.1">
+         <customChange class="org.keycloak.connections.jpa.updater.liquibase.custom.MigrateUserFedToComponent"/>
+     </changeSet>
+
+</databaseChangeLog>
\ No newline at end of file
diff --git a/model/jpa/src/main/resources/META-INF/jpa-changelog-master.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-master.xml
index ebe8cf3..4fe18b6 100755
--- a/model/jpa/src/main/resources/META-INF/jpa-changelog-master.xml
+++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-master.xml
@@ -44,4 +44,5 @@
     <include file="META-INF/jpa-changelog-2.2.0.xml"/>
     <include file="META-INF/jpa-changelog-2.3.0.xml"/>
     <include file="META-INF/jpa-changelog-2.4.0.xml"/>
+    <include file="META-INF/jpa-changelog-2.4.1.xml"/>
 </databaseChangeLog>
diff --git a/model/mongo/src/main/java/org/keycloak/connections/mongo/updater/impl/DefaultMongoUpdaterProvider.java b/model/mongo/src/main/java/org/keycloak/connections/mongo/updater/impl/DefaultMongoUpdaterProvider.java
index c7f5be8..78adfb7 100755
--- a/model/mongo/src/main/java/org/keycloak/connections/mongo/updater/impl/DefaultMongoUpdaterProvider.java
+++ b/model/mongo/src/main/java/org/keycloak/connections/mongo/updater/impl/DefaultMongoUpdaterProvider.java
@@ -35,6 +35,7 @@ import org.keycloak.connections.mongo.updater.impl.updates.Update1_8_0;
 import org.keycloak.connections.mongo.updater.impl.updates.Update1_9_2;
 import org.keycloak.connections.mongo.updater.impl.updates.Update2_3_0;
 import org.keycloak.connections.mongo.updater.impl.updates.Update2_4_0;
+import org.keycloak.connections.mongo.updater.impl.updates.Update2_4_1;
 import org.keycloak.models.KeycloakSession;
 
 import java.util.Date;
@@ -61,7 +62,8 @@ public class DefaultMongoUpdaterProvider implements MongoUpdaterProvider {
             Update1_8_0.class,
             Update1_9_2.class,
             Update2_3_0.class,
-            Update2_4_0.class
+            Update2_4_0.class,
+            Update2_4_1.class
     };
 
     @Override
diff --git a/model/mongo/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/AbstractMigrateUserFedToComponent.java b/model/mongo/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/AbstractMigrateUserFedToComponent.java
new file mode 100644
index 0000000..d4db6d3
--- /dev/null
+++ b/model/mongo/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/AbstractMigrateUserFedToComponent.java
@@ -0,0 +1,167 @@
+/*
+ * 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.connections.mongo.updater.impl.updates;
+
+import com.mongodb.BasicDBList;
+import com.mongodb.BasicDBObject;
+import com.mongodb.DBCollection;
+import com.mongodb.DBCursor;
+import org.jboss.logging.Logger;
+import org.keycloak.storage.UserStorageProvider;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractMigrateUserFedToComponent extends Update {
+    private final Logger logger = Logger.getLogger(getClass());
+
+    public void portUserFedToComponent(String providerId) {
+        DBCollection realms = db.getCollection("realms");
+        DBCursor cursor = realms.find();
+        while (cursor.hasNext()) {
+            BasicDBObject realm = (BasicDBObject) cursor.next();
+
+            String realmId = realm.getString("_id");
+            Set<String> removedProviders = new HashSet<>();
+
+            BasicDBList componentEntities = (BasicDBList) realm.get("componentEntities");
+            BasicDBList federationProviders = (BasicDBList) realm.get("userFederationProviders");
+            for (Object obj : federationProviders) {
+                BasicDBObject fedProvider = (BasicDBObject)obj;
+                if (fedProvider.getString("providerName").equals(providerId)) {
+                    String id = fedProvider.getString("id");
+                    removedProviders.add(id);
+                    int priority = fedProvider.getInt("priority");
+                    String displayName = fedProvider.getString("displayName");
+                    int fullSyncPeriod = fedProvider.getInt("fullSyncPeriod");
+                    int changedSyncPeriod = fedProvider.getInt("changedSyncPeriod");
+                    int lastSync = fedProvider.getInt("lastSync");
+                    BasicDBObject component = new BasicDBObject();
+                    component.put("id", id);
+                    component.put("name", displayName);
+                    component.put("providerType", UserStorageProvider.class.getName());
+                    component.put("providerId", providerId);
+                    component.put("parentId", realmId);
+
+                    BasicDBObject config = new BasicDBObject();
+                    config.put("priority", Collections.singletonList(Integer.toString(priority)));
+                    config.put("fullSyncPeriod", Collections.singletonList(Integer.toString(fullSyncPeriod)));
+                    config.put("changedSyncPeriod", Collections.singletonList(Integer.toString(changedSyncPeriod)));
+                    config.put("lastSync", Collections.singletonList(Integer.toString(lastSync)));
+
+                    BasicDBObject fedConfig = (BasicDBObject)fedProvider.get("config");
+                    if (fedConfig != null) {
+                        for (Map.Entry<String, Object> attr : new HashSet<>(fedConfig.entrySet())) {
+                            String attrName = attr.getKey();
+                            String attrValue = attr.getValue().toString();
+                            config.put(attrName, Collections.singletonList(attrValue));
+
+                        }
+                    }
+
+
+                    component.put("config", config);
+
+                    componentEntities.add(component);
+
+                }
+            }
+            Iterator<Object> it = federationProviders.iterator();
+            while (it.hasNext()) {
+                BasicDBObject fedProvider = (BasicDBObject)it.next();
+                String id = fedProvider.getString("id");
+                if (removedProviders.contains(id)) {
+                    it.remove();
+                }
+
+            }
+            realms.update(new BasicDBObject().append("_id", realmId), realm);
+        }
+    }
+
+    public void portUserFedMappersToComponent(String providerId, String mapperType) {
+        //logger.info("*** port mappers");
+        DBCollection realms = db.getCollection("realms");
+        DBCursor cursor = realms.find();
+        while (cursor.hasNext()) {
+            BasicDBObject realm = (BasicDBObject) cursor.next();
+
+            String realmId = realm.getString("_id");
+            Set<String> removedProviders = new HashSet<>();
+
+            BasicDBList componentEntities = (BasicDBList) realm.get("componentEntities");
+            BasicDBList federationProviders = (BasicDBList) realm.get("userFederationProviders");
+            BasicDBList fedMappers = (BasicDBList) realm.get("userFederationMappers");
+            for (Object obj : federationProviders) {
+                BasicDBObject fedProvider = (BasicDBObject)obj;
+                String providerName = fedProvider.getString("providerName");
+                //logger.info("looking for mappers of fed provider: " + providerName);
+                if (providerName.equals(providerId)) {
+                    String id = fedProvider.getString("id");
+                    //logger.info("found fed provider: " + id + ", looking at mappers");
+                    for (Object obj2 : fedMappers) {
+                        BasicDBObject fedMapper = (BasicDBObject)obj2;
+                        String federationProviderId = fedMapper.getString("federationProviderId");
+                        //logger.info("looking at mapper with federationProviderId: " + federationProviderId);
+                        if (federationProviderId.equals(id)) {
+                            String name = fedMapper.getString("name");
+                            String mapperId = fedMapper.getString("id");
+                            removedProviders.add(mapperId);
+                            String mapperProviderId = fedMapper.getString("federationMapperType");
+                            BasicDBObject component = new BasicDBObject();
+                            component.put("id", mapperId);
+                            component.put("name", name);
+                            component.put("providerType", mapperType);
+                            component.put("providerId", mapperProviderId);
+                            component.put("parentId", id);
+
+                            BasicDBObject fedConfig = (BasicDBObject)fedMapper.get("config");
+                            BasicDBObject config = new BasicDBObject();
+                            if (fedConfig != null) {
+                                for (Map.Entry<String, Object> attr : new HashSet<>(fedConfig.entrySet())) {
+                                    String attrName = attr.getKey();
+                                    String attrValue = attr.getValue().toString();
+                                    config.put(attrName, Collections.singletonList(attrValue));
+
+                                }
+                            }
+                            component.put("config", config);
+                            componentEntities.add(component);
+                        }
+                    }
+                }
+            }
+            Iterator<Object> it = fedMappers.iterator();
+            while (it.hasNext()) {
+                BasicDBObject fedMapper = (BasicDBObject)it.next();
+                String id = fedMapper.getString("id");
+                if (removedProviders.contains(id)) {
+                    it.remove();
+                }
+
+            }
+            realms.update(new BasicDBObject().append("_id", realmId), realm);
+        }
+    }
+}
diff --git a/model/mongo/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update2_4_0.java b/model/mongo/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update2_4_0.java
index d0f9405..883a051 100644
--- a/model/mongo/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update2_4_0.java
+++ b/model/mongo/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update2_4_0.java
@@ -37,8 +37,7 @@ import java.util.Set;
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
  */
-public class Update2_4_0 extends Update {
-    private final Logger logger = Logger.getLogger(getClass());
+public class Update2_4_0 extends AbstractMigrateUserFedToComponent {
 
     @Override
     public String getId() {
@@ -51,131 +50,4 @@ public class Update2_4_0 extends Update {
         portUserFedToComponent(LDAPConstants.LDAP_PROVIDER);
     }
 
-    public void portUserFedToComponent(String providerId) {
-        DBCollection realms = db.getCollection("realms");
-        DBCursor cursor = realms.find();
-        while (cursor.hasNext()) {
-            BasicDBObject realm = (BasicDBObject) cursor.next();
-
-            String realmId = realm.getString("_id");
-            Set<String> removedProviders = new HashSet<>();
-
-            BasicDBList componentEntities = (BasicDBList) realm.get("componentEntities");
-            BasicDBList federationProviders = (BasicDBList) realm.get("userFederationProviders");
-            for (Object obj : federationProviders) {
-                BasicDBObject fedProvider = (BasicDBObject)obj;
-                if (fedProvider.getString("providerName").equals(providerId)) {
-                    String id = fedProvider.getString("id");
-                    removedProviders.add(id);
-                    int priority = fedProvider.getInt("priority");
-                    String displayName = fedProvider.getString("displayName");
-                    int fullSyncPeriod = fedProvider.getInt("fullSyncPeriod");
-                    int changedSyncPeriod = fedProvider.getInt("changedSyncPeriod");
-                    int lastSync = fedProvider.getInt("lastSync");
-                    BasicDBObject component = new BasicDBObject();
-                    component.put("id", id);
-                    component.put("name", displayName);
-                    component.put("providerType", UserStorageProvider.class.getName());
-                    component.put("providerId", providerId);
-                    component.put("parentId", realmId);
-
-                    BasicDBObject config = new BasicDBObject();
-                    config.put("priority", Collections.singletonList(Integer.toString(priority)));
-                    config.put("fullSyncPeriod", Collections.singletonList(Integer.toString(fullSyncPeriod)));
-                    config.put("changedSyncPeriod", Collections.singletonList(Integer.toString(changedSyncPeriod)));
-                    config.put("lastSync", Collections.singletonList(Integer.toString(lastSync)));
-
-                    BasicDBObject fedConfig = (BasicDBObject)fedProvider.get("config");
-                    if (fedConfig != null) {
-                        for (Map.Entry<String, Object> attr : new HashSet<>(fedConfig.entrySet())) {
-                            String attrName = attr.getKey();
-                            String attrValue = attr.getValue().toString();
-                            config.put(attrName, Collections.singletonList(attrValue));
-
-                        }
-                    }
-
-
-                    component.put("config", config);
-
-                    componentEntities.add(component);
-
-                }
-            }
-            Iterator<Object> it = federationProviders.iterator();
-            while (it.hasNext()) {
-                BasicDBObject fedProvider = (BasicDBObject)it.next();
-                String id = fedProvider.getString("id");
-                if (removedProviders.contains(id)) {
-                    it.remove();
-                }
-
-            }
-            realms.update(new BasicDBObject().append("_id", realmId), realm);
-        }
-    }
-    public void portUserFedMappersToComponent(String providerId, String mapperType) {
-        //logger.info("*** port mappers");
-        DBCollection realms = db.getCollection("realms");
-        DBCursor cursor = realms.find();
-        while (cursor.hasNext()) {
-            BasicDBObject realm = (BasicDBObject) cursor.next();
-
-            String realmId = realm.getString("_id");
-            Set<String> removedProviders = new HashSet<>();
-
-            BasicDBList componentEntities = (BasicDBList) realm.get("componentEntities");
-            BasicDBList federationProviders = (BasicDBList) realm.get("userFederationProviders");
-            BasicDBList fedMappers = (BasicDBList) realm.get("userFederationMappers");
-            for (Object obj : federationProviders) {
-                BasicDBObject fedProvider = (BasicDBObject)obj;
-                String providerName = fedProvider.getString("providerName");
-                //logger.info("looking for mappers of fed provider: " + providerName);
-                if (providerName.equals(providerId)) {
-                    String id = fedProvider.getString("id");
-                    //logger.info("found fed provider: " + id + ", looking at mappers");
-                    for (Object obj2 : fedMappers) {
-                        BasicDBObject fedMapper = (BasicDBObject)obj2;
-                        String federationProviderId = fedMapper.getString("federationProviderId");
-                        //logger.info("looking at mapper with federationProviderId: " + federationProviderId);
-                        if (federationProviderId.equals(id)) {
-                            String name = fedMapper.getString("name");
-                            String mapperId = fedMapper.getString("id");
-                            removedProviders.add(mapperId);
-                            String mapperProviderId = fedMapper.getString("federationMapperType");
-                            BasicDBObject component = new BasicDBObject();
-                            component.put("id", mapperId);
-                            component.put("name", name);
-                            component.put("providerType", mapperType);
-                            component.put("providerId", mapperProviderId);
-                            component.put("parentId", id);
-
-                            BasicDBObject fedConfig = (BasicDBObject)fedMapper.get("config");
-                            BasicDBObject config = new BasicDBObject();
-                            if (fedConfig != null) {
-                                for (Map.Entry<String, Object> attr : new HashSet<>(fedConfig.entrySet())) {
-                                    String attrName = attr.getKey();
-                                    String attrValue = attr.getValue().toString();
-                                    config.put(attrName, Collections.singletonList(attrValue));
-
-                                }
-                            }
-                            component.put("config", config);
-                            componentEntities.add(component);
-                        }
-                    }
-                }
-            }
-            Iterator<Object> it = fedMappers.iterator();
-            while (it.hasNext()) {
-                BasicDBObject fedMapper = (BasicDBObject)it.next();
-                String id = fedMapper.getString("id");
-                if (removedProviders.contains(id)) {
-                    it.remove();
-                }
-
-            }
-            realms.update(new BasicDBObject().append("_id", realmId), realm);
-        }
-    }
 }
diff --git a/model/mongo/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update2_4_1.java b/model/mongo/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update2_4_1.java
new file mode 100644
index 0000000..206579f
--- /dev/null
+++ b/model/mongo/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update2_4_1.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.connections.mongo.updater.impl.updates;
+
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.LDAPConstants;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class Update2_4_1 extends AbstractMigrateUserFedToComponent {
+
+    @Override
+    public String getId() {
+        return "2.4.1";
+    }
+
+    @Override
+    public void update(KeycloakSession session) {
+        portUserFedToComponent("kerberos");
+    }
+
+}
diff --git a/server-spi/src/main/java/org/keycloak/storage/UserStorageProvider.java b/server-spi/src/main/java/org/keycloak/storage/UserStorageProvider.java
index dbb4b3c..6cf8ba6 100644
--- a/server-spi/src/main/java/org/keycloak/storage/UserStorageProvider.java
+++ b/server-spi/src/main/java/org/keycloak/storage/UserStorageProvider.java
@@ -26,8 +26,31 @@ import org.keycloak.provider.Provider;
  * @version $Revision: 1 $
  */
 public interface UserStorageProvider extends Provider {
+
+
     void preRemove(RealmModel realm);
     void preRemove(RealmModel realm, GroupModel group);
     void preRemove(RealmModel realm, RoleModel role);
+
+    /**
+     * Optional type that can be by implementations to describe edit mode of federation storage
+     *
+     */
+    enum EditMode {
+        /**
+         * federation storage is read-only
+         */
+        READ_ONLY,
+        /**
+         * federation storage is writable
+         *
+         */
+        WRITABLE,
+        /**
+         * updates to user are stored locally and not synced with federation storage.
+         *
+         */
+        UNSYNCED
+    }
 }
 
diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index 3653fc9..262503f 100755
--- a/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -362,6 +362,7 @@ public class RepresentationToModel {
         // providers to convert to component model
         Set<String> convertSet = new HashSet<>();
         convertSet.add(LDAPConstants.LDAP_PROVIDER);
+        convertSet.add("kerberos");
         Map<String, String> mapperConvertSet = new HashMap<>();
         mapperConvertSet.put(LDAPConstants.LDAP_PROVIDER, "org.keycloak.storage.ldap.mappers.LDAPStorageMapper");
 
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/AbstractKerberosTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/AbstractKerberosTest.java
index 0663e28..10841b5 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/AbstractKerberosTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/AbstractKerberosTest.java
@@ -31,6 +31,7 @@ import org.junit.Test;
 import org.keycloak.adapters.HttpClientBuilder;
 import org.keycloak.authentication.authenticators.browser.SpnegoAuthenticator;
 import org.keycloak.common.constants.KerberosConstants;
+import org.keycloak.component.ComponentModel;
 import org.keycloak.events.Details;
 import org.keycloak.federation.kerberos.CommonKerberosConfig;
 import org.keycloak.models.ClientModel;
@@ -44,6 +45,7 @@ import org.keycloak.models.UserModel;
 import org.keycloak.protocol.oidc.OIDCLoginProtocol;
 import org.keycloak.protocol.oidc.mappers.UserSessionNoteMapper;
 import org.keycloak.services.managers.RealmManager;
+import org.keycloak.storage.UserStorageProvider;
 import org.keycloak.testsuite.AssertEvents;
 import org.keycloak.testsuite.OAuthClient;
 import org.keycloak.testsuite.pages.AccountPasswordPage;
@@ -179,7 +181,7 @@ public abstract class AbstractKerberosTest {
         AssertEvents events = getAssertEvents();
 
         // Change editMode to READ_ONLY
-        updateProviderEditMode(UserFederationProvider.EditMode.READ_ONLY);
+        updateProviderEditMode(UserStorageProvider.EditMode.READ_ONLY);
 
         // Login with username/password from kerberos
         changePasswordPage.open();
@@ -200,7 +202,7 @@ public abstract class AbstractKerberosTest {
         Assert.assertTrue(driver.getPageSource().contains("You can't update your password as your account is read only"));
 
         // Change editMode to UNSYNCED
-        updateProviderEditMode(UserFederationProvider.EditMode.UNSYNCED);
+        updateProviderEditMode(UserStorageProvider.EditMode.UNSYNCED);
 
         // Successfully change password now
         changePasswordPage.changePassword("theduke", "newPass", "newPass");
@@ -382,15 +384,15 @@ public abstract class AbstractKerberosTest {
     }
 
 
-    protected void updateProviderEditMode(UserFederationProvider.EditMode editMode) {
+    protected void updateProviderEditMode(UserStorageProvider.EditMode editMode) {
         KeycloakRule keycloakRule = getKeycloakRule();
 
         KeycloakSession session = keycloakRule.startSession();
         try {
             RealmModel realm = session.realms().getRealm("test");
-            UserFederationProviderModel kerberosProviderModel = realm.getUserFederationProviders().get(0);
-            kerberosProviderModel.getConfig().put(LDAPConstants.EDIT_MODE, editMode.toString());
-            realm.updateUserFederationProvider(kerberosProviderModel);
+            ComponentModel kerberosProviderModel = realm.getComponents(realm.getId(), UserStorageProvider.class.getName()).get(0);
+            kerberosProviderModel.getConfig().putSingle(LDAPConstants.EDIT_MODE, editMode.toString());
+            realm.updateComponent(kerberosProviderModel);
         } finally {
             keycloakRule.stopSession(session, true);
         }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/KerberosStandaloneTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/KerberosStandaloneTest.java
index d3eb5c2..26b11cc 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/KerberosStandaloneTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/KerberosStandaloneTest.java
@@ -19,11 +19,14 @@ package org.keycloak.testsuite.federation;
 
 import org.junit.Assert;
 import org.junit.ClassRule;
+import org.junit.FixMethodOrder;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.RuleChain;
 import org.junit.rules.TestRule;
+import org.junit.runners.MethodSorters;
 import org.keycloak.common.constants.KerberosConstants;
+import org.keycloak.common.util.MultivaluedHashMap;
 import org.keycloak.federation.kerberos.CommonKerberosConfig;
 import org.keycloak.federation.kerberos.KerberosConfig;
 import org.keycloak.federation.kerberos.KerberosFederationProviderFactory;
@@ -32,7 +35,10 @@ import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserFederationProviderModel;
 import org.keycloak.representations.idm.CredentialRepresentation;
 import org.keycloak.services.managers.RealmManager;
+import org.keycloak.storage.UserStorageProviderModel;
+import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
 import org.keycloak.testsuite.AssertEvents;
+import org.keycloak.testsuite.federation.storage.ldap.LDAPTestUtils;
 import org.keycloak.testsuite.rule.KerberosRule;
 import org.keycloak.testsuite.rule.KeycloakRule;
 import org.keycloak.testsuite.rule.WebRule;
@@ -47,11 +53,12 @@ import java.util.Map;
  *
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
  */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
 public class KerberosStandaloneTest extends AbstractKerberosTest {
 
     private static final String PROVIDER_CONFIG_LOCATION = "kerberos/kerberos-standalone-connection.properties";
 
-    private static UserFederationProviderModel kerberosModel;
+    private static UserStorageProviderModel kerberosModel;
 
     private static KerberosRule kerberosRule = new KerberosRule(PROVIDER_CONFIG_LOCATION);
 
@@ -69,7 +76,18 @@ public class KerberosStandaloneTest extends AbstractKerberosTest {
 
 
             Map<String,String> kerberosConfig = kerberosRule.getConfig();
-            kerberosModel = appRealm.addUserFederationProvider(KerberosFederationProviderFactory.PROVIDER_NAME, kerberosConfig, 0, "kerberos-standalone", -1, -1, 0);
+            MultivaluedHashMap<String, String> config = LDAPTestUtils.toComponentConfig(kerberosConfig);
+
+            UserStorageProviderModel model = new UserStorageProviderModel();
+            model.setLastSync(0);
+            model.setChangedSyncPeriod(-1);
+            model.setFullSyncPeriod(-1);
+            model.setName("kerberos-standalone");
+            model.setPriority(0);
+            model.setProviderId(KerberosFederationProviderFactory.PROVIDER_NAME);
+            model.setConfig(config);
+
+            kerberosModel = new UserStorageProviderModel(appRealm.addComponentModel(model));
         }
 
     }) {
@@ -121,6 +139,18 @@ public class KerberosStandaloneTest extends AbstractKerberosTest {
 
     @Test
     @Override
+    public void spnegoCaseInsensitiveTest() throws Exception {
+        super.spnegoCaseInsensitiveTest();
+    }
+
+    @Test
+    @Override
+    public void credentialDelegationTest() throws Exception {
+        super.credentialDelegationTest();
+    }
+
+    @Test
+    @Override
     public void usernamePasswordLoginTest() throws Exception {
         super.usernamePasswordLoginTest();
     }
@@ -131,9 +161,9 @@ public class KerberosStandaloneTest extends AbstractKerberosTest {
         KeycloakSession session = keycloakRule.startSession();
         try {
             RealmModel realm = session.realms().getRealm("test");
-            UserFederationProviderModel kerberosProviderModel = realm.getUserFederationProviders().get(0);
-            kerberosProviderModel.getConfig().put(KerberosConstants.UPDATE_PROFILE_FIRST_LOGIN, "true");
-            realm.updateUserFederationProvider(kerberosProviderModel);
+            UserStorageProviderModel kerberosProviderModel = realm.getUserStorageProviders().get(0);
+            kerberosProviderModel.getConfig().putSingle(KerberosConstants.UPDATE_PROFILE_FIRST_LOGIN, "true");
+            realm.updateComponent(kerberosProviderModel);
         } finally {
             keycloakRule.stopSession(session, true);
         }
@@ -153,9 +183,9 @@ public class KerberosStandaloneTest extends AbstractKerberosTest {
         session = keycloakRule.startSession();
         try {
             RealmModel realm = session.realms().getRealm("test");
-            UserFederationProviderModel kerberosProviderModel = realm.getUserFederationProviders().get(0);
-            kerberosProviderModel.getConfig().put(KerberosConstants.UPDATE_PROFILE_FIRST_LOGIN, "false");
-            realm.updateUserFederationProvider(kerberosProviderModel);
+            UserStorageProviderModel kerberosProviderModel = realm.getUserStorageProviders().get(0);
+            kerberosProviderModel.getConfig().putSingle(KerberosConstants.UPDATE_PROFILE_FIRST_LOGIN, "false");
+            realm.updateComponent(kerberosProviderModel);
         } finally {
             keycloakRule.stopSession(session, true);
         }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/KerberosLdapTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/KerberosLdapTest.java
index 385d123..1e21192 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/KerberosLdapTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/KerberosLdapTest.java
@@ -47,7 +47,6 @@ import org.keycloak.utils.CredentialHelper;
 
 import javax.ws.rs.core.Response;
 import java.net.URL;
-import java.util.Map;
 
 /**
  * Test of LDAPFederationProvider (Kerberos backed by LDAP)
@@ -73,7 +72,7 @@ public class KerberosLdapTest extends AbstractKerberosTest {
                     .servletClass(KerberosCredDelegServlet.class).adapterConfigPath(url.getPath())
                     .role("user").deployApplication();
 
-            MultivaluedHashMap<String, String> ldapConfig = LDAPTestUtils.toLdapConfig(kerberosRule.getConfig());
+            MultivaluedHashMap<String, String> ldapConfig = LDAPTestUtils.toComponentConfig(kerberosRule.getConfig());
             UserStorageProviderModel model = new UserStorageProviderModel();
             model.setLastSync(0);
             model.setChangedSyncPeriod(-1);
@@ -135,42 +134,13 @@ public class KerberosLdapTest extends AbstractKerberosTest {
         super.usernamePasswordLoginTest();
     }
 
-    protected void updateProviderEditMode(LDAPStorageProviderFactory.EditMode editMode) {
-        KeycloakRule keycloakRule = getKeycloakRule();
-
-        KeycloakSession session = keycloakRule.startSession();
-        try {
-            RealmModel realm = session.realms().getRealm("test");
-            ComponentModel kerberosProviderModel = realm.getComponents(realm.getId(), UserStorageProvider.class.getName()).get(0);
-            kerberosProviderModel.getConfig().putSingle(LDAPConstants.EDIT_MODE, editMode.toString());
-            realm.updateComponent(kerberosProviderModel);
-        } finally {
-            keycloakRule.stopSession(session, true);
-        }
-    }
-
-    @Override
-    protected void updateProviderEditMode(UserFederationProvider.EditMode editMode) {
-        switch (editMode) {
-            case WRITABLE:
-                updateProviderEditMode(LDAPStorageProviderFactory.EditMode.WRITABLE);
-                break;
-            case READ_ONLY:
-                updateProviderEditMode(LDAPStorageProviderFactory.EditMode.READ_ONLY);
-                break;
-            case UNSYNCED:
-                updateProviderEditMode(LDAPStorageProviderFactory.EditMode.UNSYNCED);
-                break;
-        }
-    }
-
     @Test
     public void writableEditModeTest() throws Exception {
         KeycloakRule keycloakRule = getKeycloakRule();
         AssertEvents events = getAssertEvents();
 
         // Change editMode to WRITABLE
-        updateProviderEditMode(LDAPStorageProviderFactory.EditMode.WRITABLE);
+        updateProviderEditMode(UserStorageProvider.EditMode.WRITABLE);
 
         // Login with username/password from kerberos
         changePasswordPage.open();
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPGroupMapper2WaySyncTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPGroupMapper2WaySyncTest.java
index 7534a93..47bd2bb 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPGroupMapper2WaySyncTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPGroupMapper2WaySyncTest.java
@@ -25,6 +25,7 @@ import org.junit.Test;
 import org.junit.runners.MethodSorters;
 import org.keycloak.common.util.MultivaluedHashMap;
 import org.keycloak.component.ComponentModel;
+import org.keycloak.storage.UserStorageProvider;
 import org.keycloak.storage.UserStorageProviderModel;
 import org.keycloak.storage.ldap.LDAPStorageProvider;
 import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
@@ -41,8 +42,6 @@ import org.keycloak.storage.user.SynchronizationResult;
 import org.keycloak.testsuite.rule.KeycloakRule;
 import org.keycloak.testsuite.rule.LDAPRule;
 
-import java.util.Map;
-
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
  */
@@ -62,7 +61,7 @@ public class LDAPGroupMapper2WaySyncTest {
         public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
             MultivaluedHashMap<String,String> ldapConfig = LDAPTestUtils.getLdapRuleConfig(ldapRule);
             ldapConfig.putSingle(LDAPConstants.SYNC_REGISTRATIONS, "true");
-            ldapConfig.putSingle(LDAPConstants.EDIT_MODE, LDAPStorageProviderFactory.EditMode.WRITABLE.toString());
+            ldapConfig.putSingle(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.WRITABLE.toString());
             ldapConfig.putSingle(LDAPConstants.BATCH_SIZE_FOR_SYNC, "4"); // Issues with pagination on ApacheDS
             UserStorageProviderModel model = new UserStorageProviderModel();
             model.setLastSync(0);
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPGroupMapperSyncTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPGroupMapperSyncTest.java
index 1fec6d9..91075ae 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPGroupMapperSyncTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPGroupMapperSyncTest.java
@@ -27,6 +27,7 @@ import org.junit.rules.TestRule;
 import org.junit.runners.MethodSorters;
 import org.keycloak.common.util.MultivaluedHashMap;
 import org.keycloak.component.ComponentModel;
+import org.keycloak.storage.UserStorageProvider;
 import org.keycloak.storage.UserStorageProviderModel;
 import org.keycloak.storage.ldap.LDAPStorageProvider;
 import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
@@ -50,7 +51,6 @@ import org.keycloak.testsuite.rule.KeycloakRule;
 import org.keycloak.testsuite.rule.LDAPRule;
 
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 
 /**
@@ -70,7 +70,7 @@ public class LDAPGroupMapperSyncTest {
         public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
             MultivaluedHashMap<String,String> ldapConfig = LDAPTestUtils.getLdapRuleConfig(ldapRule);
             ldapConfig.putSingle(LDAPConstants.SYNC_REGISTRATIONS, "true");
-            ldapConfig.putSingle(LDAPConstants.EDIT_MODE, LDAPStorageProviderFactory.EditMode.WRITABLE.toString());
+            ldapConfig.putSingle(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.WRITABLE.toString());
             UserStorageProviderModel model = new UserStorageProviderModel();
             model.setLastSync(0);
             model.setChangedSyncPeriod(-1);
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPGroupMapperTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPGroupMapperTest.java
index c15a304..693b8ae 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPGroupMapperTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPGroupMapperTest.java
@@ -26,6 +26,7 @@ import org.junit.rules.TestRule;
 import org.junit.runners.MethodSorters;
 import org.keycloak.common.util.MultivaluedHashMap;
 import org.keycloak.component.ComponentModel;
+import org.keycloak.storage.UserStorageProvider;
 import org.keycloak.storage.UserStorageProviderModel;
 import org.keycloak.storage.ldap.LDAPConfig;
 import org.keycloak.storage.ldap.LDAPStorageProvider;
@@ -50,7 +51,6 @@ import org.keycloak.testsuite.rule.KeycloakRule;
 import org.keycloak.testsuite.rule.LDAPRule;
 
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 
 /**
@@ -73,7 +73,7 @@ public class LDAPGroupMapperTest {
 
             MultivaluedHashMap<String,String> ldapConfig = LDAPTestUtils.getLdapRuleConfig(ldapRule);
             ldapConfig.putSingle(LDAPConstants.SYNC_REGISTRATIONS, "true");
-            ldapConfig.putSingle(LDAPConstants.EDIT_MODE, LDAPStorageProviderFactory.EditMode.WRITABLE.toString());
+            ldapConfig.putSingle(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.WRITABLE.toString());
             UserStorageProviderModel model = new UserStorageProviderModel();
             model.setLastSync(0);
             model.setChangedSyncPeriod(-1);
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPMultipleAttributesTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPMultipleAttributesTest.java
index c054e08..7de1ae9 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPMultipleAttributesTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPMultipleAttributesTest.java
@@ -32,13 +32,12 @@ import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.LDAPConstants;
 import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserFederationProvider;
-import org.keycloak.models.UserFederationProviderModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.protocol.oidc.mappers.UserAttributeMapper;
 import org.keycloak.services.managers.RealmManager;
+import org.keycloak.storage.UserStorageProvider;
 import org.keycloak.storage.UserStorageProviderModel;
 import org.keycloak.storage.ldap.LDAPStorageProvider;
 import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
@@ -57,7 +56,6 @@ import java.util.Arrays;
 import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
 
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@@ -77,7 +75,7 @@ public class LDAPMultipleAttributesTest {
         @Override
         public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
             MultivaluedHashMap<String,String> ldapConfig = LDAPTestUtils.getLdapRuleConfig(ldapRule);
-            ldapConfig.putSingle(LDAPConstants.EDIT_MODE, LDAPStorageProviderFactory.EditMode.WRITABLE.toString());
+            ldapConfig.putSingle(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.WRITABLE.toString());
 
             UserStorageProviderModel model = new UserStorageProviderModel();
             model.setLastSync(0);
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPProvidersIntegrationTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPProvidersIntegrationTest.java
index 13735e6..def6639 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPProvidersIntegrationTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPProvidersIntegrationTest.java
@@ -65,7 +65,6 @@ import org.keycloak.testsuite.rule.WebRule;
 import org.openqa.selenium.WebDriver;
 
 import java.util.List;
-import java.util.Map;
 
 import static org.junit.Assert.assertEquals;
 
@@ -88,7 +87,7 @@ public class LDAPProvidersIntegrationTest {
 
             MultivaluedHashMap<String,String> ldapConfig = LDAPTestUtils.getLdapRuleConfig(ldapRule);
             ldapConfig.putSingle(LDAPConstants.SYNC_REGISTRATIONS, "true");
-            ldapConfig.putSingle(LDAPConstants.EDIT_MODE, LDAPStorageProviderFactory.EditMode.WRITABLE.toString());
+            ldapConfig.putSingle(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.WRITABLE.toString());
             UserStorageProviderModel model = new UserStorageProviderModel();
             model.setLastSync(0);
             model.setChangedSyncPeriod(-1);
@@ -670,7 +669,7 @@ public class LDAPProvidersIntegrationTest {
             RealmModel appRealm = session.realms().getRealmByName("test");
 
             UserStorageProviderModel model = new UserStorageProviderModel(ldapModel);
-            model.getConfig().putSingle(LDAPConstants.EDIT_MODE, LDAPStorageProviderFactory.EditMode.READ_ONLY.toString());
+            model.getConfig().putSingle(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.READ_ONLY.toString());
             appRealm.updateComponent(model);
             UserModel user = session.users().getUserByUsername("johnkeycloak", appRealm);
             Assert.assertNotNull(user);
@@ -710,7 +709,7 @@ public class LDAPProvidersIntegrationTest {
         session = keycloakRule.startSession();
         try {
             RealmModel appRealm = session.realms().getRealmByName("test");
-            Assert.assertEquals(LDAPStorageProviderFactory.EditMode.WRITABLE.toString(), appRealm.getComponent(ldapModel.getId()).getConfig().getFirst(LDAPConstants.EDIT_MODE));
+            Assert.assertEquals(UserStorageProvider.EditMode.WRITABLE.toString(), appRealm.getComponent(ldapModel.getId()).getConfig().getFirst(LDAPConstants.EDIT_MODE));
         } finally {
             keycloakRule.stopSession(session, false);
         }
@@ -829,7 +828,7 @@ public class LDAPProvidersIntegrationTest {
             RealmModel appRealm = session.realms().getRealmByName("test");
 
             UserStorageProviderModel model = new UserStorageProviderModel(ldapModel);
-            model.getConfig().putSingle(LDAPConstants.EDIT_MODE, LDAPStorageProviderFactory.EditMode.UNSYNCED.toString());
+            model.getConfig().putSingle(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.UNSYNCED.toString());
             appRealm.updateComponent(model);
             UserModel user = session.users().getUserByUsername("johnkeycloak", appRealm);
             Assert.assertNotNull(user);
@@ -860,7 +859,7 @@ public class LDAPProvidersIntegrationTest {
         session = keycloakRule.startSession();
         try {
             RealmModel appRealm = session.realms().getRealmByName("test");
-            Assert.assertEquals(LDAPStorageProviderFactory.EditMode.WRITABLE.toString(),  appRealm.getComponent(ldapModel.getId()).getConfig().getFirst(LDAPConstants.EDIT_MODE));
+            Assert.assertEquals(UserStorageProvider.EditMode.WRITABLE.toString(),  appRealm.getComponent(ldapModel.getId()).getConfig().getFirst(LDAPConstants.EDIT_MODE));
         } finally {
             keycloakRule.stopSession(session, false);
         }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPRoleMappingsTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPRoleMappingsTest.java
index 19c2b6b..3cb70fb 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPRoleMappingsTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPRoleMappingsTest.java
@@ -27,6 +27,7 @@ import org.junit.rules.TestRule;
 import org.junit.runners.MethodSorters;
 import org.keycloak.common.util.MultivaluedHashMap;
 import org.keycloak.component.ComponentModel;
+import org.keycloak.storage.UserStorageProvider;
 import org.keycloak.storage.UserStorageProviderModel;
 import org.keycloak.storage.ldap.LDAPStorageProvider;
 import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
@@ -52,7 +53,6 @@ import org.keycloak.testsuite.rule.WebResource;
 import org.keycloak.testsuite.rule.WebRule;
 import org.openqa.selenium.WebDriver;
 
-import java.util.Map;
 import java.util.Set;
 
 /**
@@ -73,7 +73,7 @@ public class LDAPRoleMappingsTest {
 
             MultivaluedHashMap<String,String> ldapConfig = LDAPTestUtils.getLdapRuleConfig(ldapRule);
             ldapConfig.putSingle(LDAPConstants.SYNC_REGISTRATIONS, "true");
-            ldapConfig.putSingle(LDAPConstants.EDIT_MODE, LDAPStorageProviderFactory.EditMode.WRITABLE.toString());
+            ldapConfig.putSingle(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.WRITABLE.toString());
             UserStorageProviderModel model = new UserStorageProviderModel();
             model.setLastSync(0);
             model.setChangedSyncPeriod(-1);
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPSyncTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPSyncTest.java
index c1d55c1..169d82f 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPSyncTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPSyncTest.java
@@ -28,6 +28,7 @@ import org.keycloak.common.util.MultivaluedHashMap;
 import org.keycloak.common.util.Time;
 import org.keycloak.component.ComponentModel;
 import org.keycloak.services.managers.UserStorageSyncManager;
+import org.keycloak.storage.UserStorageProvider;
 import org.keycloak.storage.ldap.idm.model.LDAPObject;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
@@ -44,8 +45,6 @@ import org.keycloak.storage.user.SynchronizationResult;
 import org.keycloak.testsuite.rule.KeycloakRule;
 import org.keycloak.testsuite.rule.LDAPRule;
 
-import java.util.Map;
-
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
  */
@@ -65,7 +64,7 @@ public class LDAPSyncTest {
 
             MultivaluedHashMap<String,String> ldapConfig = LDAPTestUtils.getLdapRuleConfig(ldapRule);
             ldapConfig.putSingle(LDAPConstants.SYNC_REGISTRATIONS, "false");
-            ldapConfig.putSingle(LDAPConstants.EDIT_MODE, LDAPStorageProviderFactory.EditMode.WRITABLE.toString());
+            ldapConfig.putSingle(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.WRITABLE.toString());
             UserStorageProviderModel model = new UserStorageProviderModel();
             model.setLastSync(0);
             model.setChangedSyncPeriod(-1);
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPTestConfiguration.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPTestConfiguration.java
index 53a6294..9a9bda1 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPTestConfiguration.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPTestConfiguration.java
@@ -20,7 +20,7 @@ package org.keycloak.testsuite.federation.storage.ldap;
 import org.jboss.logging.Logger;
 import org.keycloak.common.constants.KerberosConstants;
 import org.keycloak.models.LDAPConstants;
-import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
+import org.keycloak.storage.UserStorageProvider;
 
 import java.io.File;
 import java.io.InputStream;
@@ -79,7 +79,7 @@ public class LDAPTestConfiguration {
         DEFAULT_VALUES.put(LDAPConstants.BATCH_SIZE_FOR_SYNC, String.valueOf(LDAPConstants.DEFAULT_BATCH_SIZE_FOR_SYNC));
         DEFAULT_VALUES.put(LDAPConstants.USERNAME_LDAP_ATTRIBUTE, null);
         DEFAULT_VALUES.put(LDAPConstants.USER_OBJECT_CLASSES, null);
-        DEFAULT_VALUES.put(LDAPConstants.EDIT_MODE, LDAPStorageProviderFactory.EditMode.READ_ONLY.toString());
+        DEFAULT_VALUES.put(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.READ_ONLY.toString());
 
         DEFAULT_VALUES.put(KerberosConstants.ALLOW_KERBEROS_AUTHENTICATION, "false");
         DEFAULT_VALUES.put(KerberosConstants.KERBEROS_REALM, "KEYCLOAK.ORG");
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPTestUtils.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPTestUtils.java
index 44a3f24..ae58321 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPTestUtils.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPTestUtils.java
@@ -31,7 +31,6 @@ import org.keycloak.models.utils.UserModelDelegate;
 import org.keycloak.representations.idm.CredentialRepresentation;
 import org.keycloak.storage.UserStorageProvider;
 import org.keycloak.storage.ldap.LDAPStorageProvider;
-import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
 import org.keycloak.storage.ldap.LDAPUtils;
 import org.keycloak.storage.ldap.idm.model.LDAPObject;
 import org.keycloak.storage.ldap.idm.query.internal.LDAPQuery;
@@ -62,11 +61,11 @@ import java.util.Set;
 public class LDAPTestUtils {
     public static MultivaluedHashMap<String, String> getLdapRuleConfig(LDAPRule ldapRule) {
         Map<String,String> ldapConfig = ldapRule.getConfig();
-        return toLdapConfig(ldapConfig);
+        return toComponentConfig(ldapConfig);
 
     }
 
-    public static MultivaluedHashMap<String, String> toLdapConfig(Map<String, String> ldapConfig) {
+    public static MultivaluedHashMap<String, String> toComponentConfig(Map<String, String> ldapConfig) {
         MultivaluedHashMap<String, String> config = new MultivaluedHashMap<>();
         for (Map.Entry<String, String> entry : ldapConfig.entrySet()) {
             config.add(entry.getKey(), entry.getValue());
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/federation/AbstractKerberosAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/federation/AbstractKerberosAdapterTest.java
index 11d2f64..962795e 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/federation/AbstractKerberosAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/federation/AbstractKerberosAdapterTest.java
@@ -45,6 +45,7 @@ import org.keycloak.models.UserModel;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.representations.idm.UserFederationProviderRepresentation;
 import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.storage.UserStorageProviderModel;
 import org.keycloak.testsuite.AssertEvents;
 import org.keycloak.testsuite.adapter.AbstractServletsAdapterTest;
 import org.keycloak.testsuite.adapter.page.KerberosPortal;
@@ -89,7 +90,7 @@ public abstract class AbstractKerberosAdapterTest extends AbstractServletsAdapte
     
     protected abstract String getConnectionPropertiesLocation();
 
-    protected abstract CommonKerberosConfig getKerberosConfig(UserFederationProviderModel model);
+    protected abstract CommonKerberosConfig getKerberosConfig(UserStorageProviderModel model);
     
     @Deployment(name = KerberosPortal.DEPLOYMENT_NAME)
     protected static WebArchive kerberosPortal() {
@@ -116,8 +117,8 @@ public abstract class AbstractKerberosAdapterTest extends AbstractServletsAdapte
             ldapEmbeddedServer.init();
             ldapEmbeddedServer.start();
         }
-        UserFederationProviderModel model = new UserFederationProviderModel();
-        model.setConfig(ldapTestConfiguration.getLDAPConfig());
+        UserStorageProviderModel model = new UserStorageProviderModel();
+        model.setConfig(AbstractKerberosStandaloneAdapterTest.toComponentConfig(ldapTestConfiguration.getLDAPConfig()));
         spnegoSchemeFactory = new KeycloakSPNegoSchemeFactory(getKerberosConfig(model));
         initHttpClient(true);
         removeAllUsers();
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/federation/AbstractKerberosStandaloneAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/federation/AbstractKerberosStandaloneAdapterTest.java
index 08b97e7..77fe410 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/federation/AbstractKerberosStandaloneAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/federation/AbstractKerberosStandaloneAdapterTest.java
@@ -21,12 +21,16 @@ import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.keycloak.common.constants.KerberosConstants;
+import org.keycloak.common.util.MultivaluedHashMap;
 import org.keycloak.federation.kerberos.CommonKerberosConfig;
 import org.keycloak.federation.kerberos.KerberosConfig;
 import org.keycloak.federation.kerberos.KerberosFederationProviderFactory;
 import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.representations.idm.ComponentRepresentation;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.representations.idm.UserFederationProviderRepresentation;
+import org.keycloak.storage.UserStorageProvider;
+import org.keycloak.storage.UserStorageProviderModel;
 
 import javax.ws.rs.core.Response;
 import java.util.Arrays;
@@ -39,28 +43,36 @@ import java.util.Map;
  */
 public abstract class AbstractKerberosStandaloneAdapterTest extends AbstractKerberosAdapterTest {
 
+    public static MultivaluedHashMap<String, String> toComponentConfig(Map<String, String> ldapConfig) {
+        MultivaluedHashMap<String, String> config = new MultivaluedHashMap<>();
+        for (Map.Entry<String, String> entry : ldapConfig.entrySet()) {
+            config.add(entry.getKey(), entry.getValue());
+
+        }
+        return config;
+    }
+
     protected static final String PROVIDER_CONFIG_LOCATION = "kerberos-standalone-connection.properties";
 
     @Before
     public void init() throws Exception{
-        Map<String,String> ldapConfig = getConfig();
-        UserFederationProviderRepresentation userFederationProviderRepresentation = new UserFederationProviderRepresentation();
-        userFederationProviderRepresentation.setProviderName(KerberosFederationProviderFactory.PROVIDER_NAME);
-        userFederationProviderRepresentation.setConfig(ldapConfig);
-        userFederationProviderRepresentation.setPriority(0);
-        userFederationProviderRepresentation.setDisplayName("kerberos-standalone");
-        userFederationProviderRepresentation.setFullSyncPeriod(-1);
-        userFederationProviderRepresentation.setChangedSyncPeriod(-1);
-        userFederationProviderRepresentation.setLastSync(0);
-        
         RealmRepresentation realmRepresentation = testRealmResource().toRepresentation();
-        realmRepresentation.setUserFederationProviders(Arrays.asList(userFederationProviderRepresentation));
-        realmRepresentation.setEventsEnabled(true); 
+        Map<String,String> ldapConfig = getConfig();
+        ComponentRepresentation component = new ComponentRepresentation();
+        component.setName("kerberos-standalone");
+        component.setParentId(realmRepresentation.getId());
+        component.setProviderId(KerberosFederationProviderFactory.PROVIDER_NAME);
+        component.setProviderType(UserStorageProvider.class.getName());
+        component.setConfig(toComponentConfig(ldapConfig));
+        component.getConfig().putSingle("priority", "0");
+
+        testRealmResource().components().add(component);
+        realmRepresentation.setEventsEnabled(true);
         testRealmResource().update(realmRepresentation);        
     }
     
     @Override
-    protected CommonKerberosConfig getKerberosConfig(UserFederationProviderModel model) {
+    protected CommonKerberosConfig getKerberosConfig(UserStorageProviderModel model) {
         return new KerberosConfig(model);
     }
     
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/Assert.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/Assert.java
index 68163dd..1f37ca2 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/Assert.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/Assert.java
@@ -18,6 +18,7 @@
 package org.keycloak.testsuite;
 
 import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.representations.idm.ComponentRepresentation;
 import org.keycloak.representations.idm.ConfigPropertyRepresentation;
 import org.keycloak.representations.idm.GroupRepresentation;
 import org.keycloak.representations.idm.IdentityProviderRepresentation;
@@ -75,6 +76,8 @@ public class Assert extends org.junit.Assert {
             return ((UserFederationProviderFactoryRepresentation) o1).getId();
         } else if (o1 instanceof GroupRepresentation) {
             return ((GroupRepresentation) o1).getName();
+        }else if (o1 instanceof ComponentRepresentation) {
+            return ((ComponentRepresentation) o1).getName();
         }
 
         throw new IllegalArgumentException();
diff --git a/testsuite/integration-arquillian/tests/other/sssd/src/test/java/org/keycloak/testsuite/sssd/SSSDTest.java b/testsuite/integration-arquillian/tests/other/sssd/src/test/java/org/keycloak/testsuite/sssd/SSSDTest.java
index 68488cc..a59adfc 100644
--- a/testsuite/integration-arquillian/tests/other/sssd/src/test/java/org/keycloak/testsuite/sssd/SSSDTest.java
+++ b/testsuite/integration-arquillian/tests/other/sssd/src/test/java/org/keycloak/testsuite/sssd/SSSDTest.java
@@ -5,11 +5,14 @@ import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
+import org.keycloak.common.util.MultivaluedHashMap;
+import org.keycloak.representations.idm.ComponentRepresentation;
 import org.keycloak.representations.idm.GroupRepresentation;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.representations.idm.UserFederationProviderFactoryRepresentation;
 import org.keycloak.representations.idm.UserFederationProviderRepresentation;
 import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.storage.UserStorageProvider;
 import org.keycloak.testsuite.AbstractKeycloakTest;
 import org.keycloak.testsuite.Assert;
 import org.keycloak.testsuite.AssertEvents;
@@ -61,16 +64,17 @@ public class SSSDTest extends AbstractKeycloakTest {
 
     @Before
     public void createUserFederation() {
-        UserFederationProviderRepresentation userFederation = new UserFederationProviderRepresentation();
+        ComponentRepresentation userFederation = new ComponentRepresentation();
 
-        Map<String, String> config = new HashMap<>();
+        MultivaluedHashMap<String, String> config = new MultivaluedHashMap<>();
         userFederation.setConfig(config);
 
-        userFederation.setDisplayName(DISPLAY_NAME);
-        userFederation.setPriority(0);
-        userFederation.setProviderName(PROVIDER_NAME);
+        userFederation.setName(DISPLAY_NAME);
+        userFederation.getConfig().putSingle("priority", "0");
+        userFederation.setProviderType(UserStorageProvider.class.getName());
+        userFederation.setProviderId(PROVIDER_NAME);
 
-        adminClient.realm(REALM_NAME).userFederation().create(userFederation);
+        adminClient.realm(REALM_NAME).components().add(userFederation);
     }
 
     @Ignore