keycloak-memoizeit

port kerberos

11/21/2016 2:33:44 PM

Changes

Details

diff --git a/federation/kerberos/pom.xml b/federation/kerberos/pom.xml
index da453d6..79300c1 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/model/jpa/src/main/resources/META-INF/jpa-changelog-2.4.0.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-2.4.0.xml
index 0aebd9a..e8af8da 100755
--- a/model/jpa/src/main/resources/META-INF/jpa-changelog-2.4.0.xml
+++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-2.4.0.xml
@@ -19,7 +19,7 @@
 <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.0">
-         <customChange class="org.keycloak.connections.jpa.updater.liquibase.custom.PortLdapUserFedToComponentModel"/>
+         <customChange class="org.keycloak.connections.jpa.updater.liquibase.custom.MigrateUserFedToComponent"/>
      </changeSet>
 
 </databaseChangeLog>
\ No newline at end of file
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..8900b3a 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
@@ -49,6 +49,7 @@ public class Update2_4_0 extends Update {
     public void update(KeycloakSession session) {
         portUserFedMappersToComponent(LDAPConstants.LDAP_PROVIDER, "org.keycloak.storage.ldap.mappers.LDAPStorageMapper");
         portUserFedToComponent(LDAPConstants.LDAP_PROVIDER);
+        portUserFedToComponent("kerberos");
     }
 
     public void portUserFedToComponent(String providerId) {
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 ee4b561..c62e2c6 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 6632124..f5cbccb 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);
     }