keycloak-uncached

Changes

Details

diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/app.js b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/app.js
index bf1f0fc..937bad7 100755
--- a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/app.js
+++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/app.js
@@ -702,6 +702,53 @@ module.config([ '$routeProvider', function($routeProvider) {
             },
             controller : 'RealmSessionStatsCtrl'
         })
+        .when('/realms/:realm/user-federation', {
+            templateUrl : 'partials/user-federation.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                }
+            },
+            controller : 'UserFederationCtrl'
+        })
+        .when('/realms/:realm/user-federation/providers/ldap/:provider', {
+            templateUrl : 'partials/federated-ldap.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                provider : function(UserFederationInstanceLoader) {
+                    return UserFederationInstanceLoader();
+                }
+            },
+            controller : 'LDAPCtrl'
+        })
+        .when('/create/user-federation/:realm/providers/ldap', {
+            templateUrl : 'partials/federated-ldap.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                provider : function() {
+                    return {};
+                }
+            },
+            controller : 'LDAPCtrl'
+        })
+        .when('/create/user-federation/:realm/providers/:provider', {
+            templateUrl : 'partials/federated-ldap.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                provider : function() {
+                    return {
+                        providerName: "@provider"
+                    };
+                }
+            },
+            controller : 'GenericUserFederationCtrl'
+        })
         .when('/logout', {
             templateUrl : 'partials/home.html',
             controller : 'LogoutCtrl'
diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/controllers/users.js b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/controllers/users.js
index 571bbfc..73b476f 100755
--- a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/controllers/users.js
+++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/controllers/users.js
@@ -331,3 +331,150 @@ module.controller('UserCredentialsCtrl', function($scope, realm, user, User, Use
         $scope.userChange = false;
     };
 });
+
+module.controller('UserFederationCtrl', function($scope, $location, realm, UserFederationProviders, UserFederationInstances, Notifications, Dialog) {
+    console.log('UserFederationCtrl ++++****');
+    $scope.realm = realm;
+    $scope.providers = UserFederationProviders.query({realm: realm.realm});
+
+    $scope.addProvider = function(provider) {
+        console.log('Add provider: ' + provider.name);
+        $location.url("/create/user-federation/" + realm.realm + "/providers/" + provider.name);
+    };
+
+    $scope.instances = UserFederationInstances.query({realm: realm.realm});
+
+});
+
+module.controller('GenericUserFederationCtrl', function($scope, realm, provider, UserFederationProviders, UserFederationInstances, Notifications, Dialog) {
+    console.log('GenericUserFederationCtrl');
+
+    console.log("provider: " + provider.providerName);
+
+});
+
+
+module.controller('LDAPCtrl', function($scope, $location, Notifications, Dialog, realm, provider, UserFederationInstances, RealmLDAPConnectionTester) {
+    console.log('LDAPCtrl');
+
+    $scope.provider = angular.copy(provider);
+    $scope.create = !provider.providerName;
+
+    if ($scope.create) {
+        $scope.provider.providerName = "ldap";
+        $scope.provider.config = {};
+    }
+
+    $scope.ldapVendors = [
+        { "id": "ad", "name": "Active Directory" },
+        { "id": "rhds", "name": "Red Hat Directory Server" },
+        { "id": "other", "name": "Other" }
+    ];
+
+    $scope.usernameLDAPAttributes = [
+        "uid", "cn", "sAMAccountName"
+    ];
+
+    $scope.realm = realm;
+
+
+    $scope.changed = false;
+
+    $scope.lastVendor = $scope.provider.config.vendor;
+
+    $scope.$watch('realm', function() {
+        if (!angular.equals($scope.provider, provider)) {
+            $scope.changed = true;
+        }
+
+        if (!angular.equals($scope.provider.config.vendor, $scope.lastVendor)) {
+            console.log("LDAP vendor changed");
+            $scope.lastVendor = $scope.provider.config.vendor;
+
+            if ($scope.lastVendor === "ad") {
+                $scope.provider.config.usernameLDAPAttribute = "cn";
+                $scope.provider.config.userObjectClasses = "person, organizationalPerson";
+            } else {
+                $scope.provider.config.usernameLDAPAttribute = "uid";
+                $scope.provider.config.userObjectClasses = "inetOrgPerson, organizationalPerson";
+            }
+        }
+    }, true);
+
+    $scope.save = function() {
+        $scope.changed = false;
+        if ($scope.create) {
+            UserFederationInstances.save({realm: realm.realm}, $scope.provider,  function () {
+                $scope.changed = false;
+                $location.url("/realms/" + realm.realm + "/user-federation");
+                Notifications.success("The provider has been created.");
+            });
+        } else {
+            UserFederationInstances.update({realm: realm.realm,
+                                          provider: provider.id
+                },
+                $scope.provider,  function () {
+                $scope.changed = false;
+                $location.url("/realms/" + realm.realm + "/user-federation");
+                Notifications.success("The provider has been updated.");
+            });
+
+        }
+    };
+
+    $scope.reset = function() {
+        $scope.provider = angular.copy(provider);
+        if ($scope.create) {
+            $scope.provider.providerName = "ldap";
+            $scope.provider.config = {};
+        }
+        $scope.changed = false;
+        $scope.lastVendor = $scope.provider.config.vendor;
+    };
+
+    $scope.cancel = function() {
+        $location.url("/realms/" + realm.realm + "/user-federation");
+    };
+
+    $scope.remove = function() {
+        Dialog.confirmDelete($scope.provider.id, 'provider', function() {
+            $scope.provider.$remove({
+                realm : realm.realm,
+                provider : $scope.provider.id
+            }, function() {
+                $location.url("/realms/" + realm.realm + "/user-federation");
+                Notifications.success("The provider has been deleted.");
+            });
+        });
+    };
+
+
+    var initConnectionTest = function(testAction, ldapConfig) {
+        return {
+            action: testAction,
+            realm: $scope.realm.realm,
+            connectionUrl: ldapConfig.connectionUrl,
+            bindDn: ldapConfig.bindDn,
+            bindCredential: ldapConfig.bindCredential
+        };
+    };
+
+    $scope.testConnection = function() {
+        console.log('LDAPCtrl: testConnection');
+        RealmLDAPConnectionTester.get(initConnectionTest("testConnection", $scope.provider.config), function() {
+            Notifications.success("LDAP connection successful.");
+        }, function() {
+            Notifications.error("Error when trying to connect to LDAP. See server.log for details.");
+        });
+    }
+
+    $scope.testAuthentication = function() {
+        console.log('LDAPCtrl: testAuthentication');
+        RealmLDAPConnectionTester.get(initConnectionTest("testAuthentication", $scope.realm.ldapServer), function() {
+            Notifications.success("LDAP authentication successful.");
+        }, function() {
+            Notifications.error("LDAP authentication failed. See server.log for details");
+        });
+    }
+});
+
diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/loaders.js b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/loaders.js
index 139d507..f18f1c2 100755
--- a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/loaders.js
+++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/loaders.js
@@ -88,6 +88,16 @@ module.factory('UserLoader', function(Loader, User, $route, $q) {
     });
 });
 
+module.factory('UserFederationInstanceLoader', function(Loader, UserFederationInstances, $route, $q) {
+    return Loader.get(UserFederationInstances, function() {
+        return {
+            realm : $route.current.params.realm,
+            provider: $route.current.params.provider
+        }
+    });
+});
+
+
 module.factory('UserSessionStatsLoader', function(Loader, UserSessionStats, $route, $q) {
     return Loader.get(UserSessionStats, function() {
         return {
@@ -115,6 +125,9 @@ module.factory('UserSocialLinksLoader', function(Loader, UserSocialLinks, $route
     });
 });
 
+
+
+
 module.factory('RoleLoader', function(Loader, Role, $route, $q) {
     return Loader.get(Role, function() {
         return {
diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/services.js b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/services.js
index f0a4114..6ea04fd 100755
--- a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/services.js
+++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/services.js
@@ -199,6 +199,24 @@ module.factory('User', function($resource) {
     });
 });
 
+module.factory('UserFederationInstances', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/user-federation/instances/:provider', {
+        realm : '@realm',
+        provider : '@provider'
+    },  {
+        update : {
+            method : 'PUT'
+        }
+    });
+});
+
+module.factory('UserFederationProviders', function($resource) {
+    return $resource(authUrl + '/admin/realms/:realm/user-federation/providers', {
+        realm : '@realm'
+    });
+});
+
+
 module.factory('UserSessionStats', function($resource) {
     return $resource(authUrl + '/admin/realms/:realm/users/:user/session-stats', {
         realm : '@realm',
diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/federated-generic.html b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/federated-generic.html
new file mode 100755
index 0000000..775f8f8
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/federated-generic.html
@@ -0,0 +1,16 @@
+<div class="bs-sidebar col-sm-3 " data-ng-include data-src="'partials/realm-menu.html'"></div>
+<div id="content-area" class="col-sm-9" role="main">
+    <ul class="nav nav-tabs nav-tabs-pf">
+        <li><a href="#/realms/{{realm.realm}}/users">User List</a></li>
+        <li><a href="#/realms/{{realm.realm}}/user-federation">Federation</a></li>
+    </ul>
+    <div id="content">
+        <ol class="breadcrumb">
+            <li><a href="#/realms/{{realm.realm}}/user-federation">Federation</a></li>
+            <li class="active">User Federation Provider Configuration</li>
+        </ol>
+        <h2 class="pull-left"><span>{{realm.realm}}</span> Provider Settings</h2>
+        <p class="subtitle"><span class="required">*</span> Required fields</p>
+
+    </div>
+</div>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/federated-ldap.html b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/federated-ldap.html
new file mode 100755
index 0000000..c4f1d7b
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/federated-ldap.html
@@ -0,0 +1,96 @@
+<div class="bs-sidebar col-sm-3 " data-ng-include data-src="'partials/realm-menu.html'"></div>
+<div id="content-area" class="col-sm-9" role="main">
+    <ul class="nav nav-tabs nav-tabs-pf">
+        <li><a href="#/realms/{{realm.realm}}/users">User List</a></li>
+        <li><a href="#/realms/{{realm.realm}}/user-federation">Federation</a></li>
+    </ul>
+    <div id="content">
+        <ol class="breadcrumb">
+            <li><a href="#/realms/{{realm.realm}}/user-federation">Federation</a></li>
+            <li class="active">Ldap Configuration</li>
+        </ol>
+        <h2 class="pull-left"><span>{{realm.realm}}</span> Ldap Server Settings</h2>
+        <p class="subtitle"><span class="required">*</span> Required fields</p>
+        <form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
+            
+            <fieldset>
+                <legend><span class="text">Required Settings</span></legend>
+                <div class="form-group clearfix">
+                    <label class="col-sm-2 control-label" for="vendor">Vendor</label>
+                    <div class="col-sm-4">
+                        <div class="select-kc">
+                            <select id="vendor"
+                                    ng-model="provider.config.vendor"
+                                    ng-options="vendor.id as vendor.name for vendor in ldapVendors">
+                            </select>
+                        </div>
+                    </div>
+                </div>
+                <div class="form-group clearfix">
+                    <label class="col-sm-2 control-label" for="usernameLDAPAttribute">Username LDAP attribute </label>
+                    <div class="col-sm-4">
+                        <div class="select-kc">
+                            <select id="usernameLDAPAttribute"
+                                    ng-model="provider.config.usernameLDAPAttribute"
+                                    ng-options="usernameLDAPAttribute for usernameLDAPAttribute in usernameLDAPAttributes">
+                            </select>
+                        </div>
+                    </div>
+                </div>
+                <div class="form-group clearfix">
+                    <label class="col-sm-2 control-label" for="userObjectClasses">User Object Classes </label>
+                    <div class="col-sm-4">
+                        <input class="form-control" id="userObjectClasses" type="text" ng-model="provider.config.userObjectClasses" placeholder="LDAP User Object Classes (div. by comma)">
+                    </div>
+                </div>
+                <div class="form-group clearfix">
+                    <label class="col-sm-2 control-label" for="ldapConnectionUrl">Connection URL <span class="required">*</span></label>
+                    <div class="col-sm-4">
+                        <input class="form-control" id="ldapConnectionUrl" type="text" ng-model="provider.config.connectionUrl" placeholder="LDAP connection URL" required>
+                    </div>
+                    <div class="col-sm-4" data-ng-show="access.manageRealm">
+                        <a class="btn btn-primary" data-ng-click="testConnection()">Test connection</a>
+                    </div>
+                </div>
+                <div class="form-group clearfix">
+                    <label class="col-sm-2 control-label" for="ldapBaseDn">Base DN <span class="required">*</span></label>
+                    <div class="col-sm-4">
+                        <input class="form-control" id="ldapBaseDn" type="text" ng-model="provider.config.baseDn" placeholder="LDAP Base DN" required>
+                    </div>
+                </div>
+                <div class="form-group clearfix">
+                    <label class="col-sm-2 control-label" for="ldapUserDnSuffix">User DN Suffix <span class="required">*</span></label>
+                    <div class="col-sm-4">
+                        <input class="form-control" id="ldapUserDnSuffix" type="text" ng-model="provider.config.userDnSuffix" placeholder="LDAP User DN Suffix" required>
+                    </div>
+                </div>
+                <div class="form-group clearfix">
+                    <label class="col-sm-2 control-label" for="ldapBindDn">Bind DN <span class="required">*</span></label>
+                    <div class="col-sm-4">
+                        <input class="form-control" id="ldapBindDn" type="text" ng-model="provider.config.bindDn" placeholder="LDAP Bind DN" required>
+                    </div>
+                </div>
+                <div class="form-group clearfix">
+                    <label class="col-sm-2 control-label" for="ldapBindCredential">Bind Credential <span class="required">*</span></label>
+                    <div class="col-sm-4">
+                        <input class="form-control" id="ldapBindCredential" type="text" ng-model="provider.config.bindCredential" placeholder="LDAP Bind Credentials" required>
+                    </div>
+                    <div class="col-sm-4" data-ng-show="access.manageRealm">
+                        <a class="btn btn-primary" data-ng-click="testAuthentication()">Test authentication</a>
+                    </div>
+                </div>
+            </fieldset>
+
+            <div class="pull-right form-actions" data-ng-show="create && access.manageUsers">
+                <button kc-cancel data-ng-click="cancel()">Cancel</button>
+                <button kc-save data-ng-show="changed">Save</button>
+            </div>
+
+            <div class="pull-right form-actions" data-ng-show="!create && access.manageUsers">
+                <button kc-reset data-ng-show="changed">Clear changes</button>
+                <button kc-save  data-ng-show="changed">Save</button>
+                <button kc-delete data-ng-click="remove()" data-ng-hide="changed">Delete</button>
+            </div>
+        </form>
+    </div>
+</div>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/user-federation.html b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/user-federation.html
new file mode 100755
index 0000000..d56ec17
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/user-federation.html
@@ -0,0 +1,47 @@
+<div class="bs-sidebar col-sm-3 " data-ng-include data-src="'partials/realm-menu.html'"></div>
+<div id="content-area" class="col-sm-9" role="main">
+    <ul class="nav nav-tabs nav-tabs-pf">
+        <li><a href="#/realms/{{realm.realm}}/users">User List</a></li>
+        <li class="active"><a href="">Federation</a></li>
+    </ul>
+    <div id="content">
+        <ol class="breadcrumb">
+            <li><a href="#/realms/{{realm.realm}}">{{realm.realm}}</a></li>
+            <li class="active">Federation</li>
+        </ol>
+        <h2><span>{{realm.realm}}</span> User Federation Providers</h2>
+
+        <table class="table table-striped table-bordered">
+            <thead>
+            <tr ng-show="providers.length > 0 && access.manageUsers">
+                <th colspan="3" class="kc-table-actions">
+                    <div class="pull-right">
+                        <div class="select-kc">
+                            <select ng-model="selectedProvider"
+                                    ng-options="p.name for p in providers"
+                                    data-ng-change="addProvider(selectedProvider); selectedProvider = null">
+                                <option value="" disabled selected>Add provider...</option>
+                            </select>
+                        </div>
+                    </div>
+                </th>
+            </tr>
+            <tr data-ng-show="instances && instances.length > 0">
+                <th>ID</th>
+                <th>Provider Name</th>
+                <th>Priority</th>
+            </tr>
+            </thead>
+            <tbody>
+            <tr ng-repeat="instance in instances">
+                <td><a href="#/realms/{{realm.realm}}/user-federation/providers/{{instance.providerName}}/{{instance.id}}">{{instance.id}}</a></td>
+                <td>{{instance.providerName|capitalize}}</td>
+                <td>{{instance.priority}}</td>
+             </tr>
+            <tr data-ng-show="!instances || instances.length == 0">
+                <td>No user federation providers configured</td>
+            </tr>
+            </tbody>
+        </table>
+    </div>
+</div>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/user-list.html b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/user-list.html
index d6dcd49..8f1a5d0 100755
--- a/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/user-list.html
+++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/user-list.html
@@ -2,6 +2,7 @@
 <div id="content-area" class="col-md-9" role="main">
     <ul class="nav nav-tabs nav-tabs-pf">
         <li class="active"><a href="">User List</a></li>
+        <li><a href="#/realms/{{realm.realm}}/user-federation">Federation</a></li>
     </ul>
     <div id="content">
         <ol class="breadcrumb">
diff --git a/model/api/src/main/java/org/keycloak/models/KeycloakSessionFactory.java b/model/api/src/main/java/org/keycloak/models/KeycloakSessionFactory.java
index af31c09..2e94eed 100755
--- a/model/api/src/main/java/org/keycloak/models/KeycloakSessionFactory.java
+++ b/model/api/src/main/java/org/keycloak/models/KeycloakSessionFactory.java
@@ -3,6 +3,8 @@ package org.keycloak.models;
 import org.keycloak.provider.Provider;
 import org.keycloak.provider.ProviderFactory;
 
+import java.util.List;
+
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
@@ -14,5 +16,7 @@ public interface KeycloakSessionFactory {
 
     <T extends Provider> ProviderFactory<T> getProviderFactory(Class<T> clazz, String id);
 
+    List<ProviderFactory> getProviderFactories(Class<? extends Provider> clazz);
+
     void close();
 }
diff --git a/model/api/src/main/java/org/keycloak/models/RealmModel.java b/model/api/src/main/java/org/keycloak/models/RealmModel.java
index cc3a9b6..aee3119 100755
--- a/model/api/src/main/java/org/keycloak/models/RealmModel.java
+++ b/model/api/src/main/java/org/keycloak/models/RealmModel.java
@@ -168,6 +168,7 @@ public interface RealmModel extends RoleContainerModel {
     List<UserFederationProviderModel> getUserFederationProviders();
 
     UserFederationProviderModel addUserFederationProvider(String providerName, Map<String, String> config, int priority);
+    void updateUserFederationProvider(UserFederationProviderModel provider);
     void removeUserFederationProvider(UserFederationProviderModel provider);
     void setUserFederationProviders(List<UserFederationProviderModel> providers);
 
diff --git a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
index b28f71c..714ee8d 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
@@ -269,4 +269,13 @@ public class ModelToRepresentation {
         rep.setNotBefore(model.getNotBefore());
         return rep;
     }
+
+    public static UserFederationProviderRepresentation toRepresentation(UserFederationProviderModel model) {
+        UserFederationProviderRepresentation rep = new UserFederationProviderRepresentation();
+        rep.setId(model.getId());
+        rep.setConfig(model.getConfig());
+        rep.setProviderName(model.getProviderName());
+        rep.setPriority(model.getPriority());
+        return rep;
+    }
 }
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java
index 6353b50..b0281dc 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java
@@ -631,6 +631,13 @@ public class RealmAdapter implements RealmModel {
     }
 
     @Override
+    public void updateUserFederationProvider(UserFederationProviderModel provider) {
+        getDelegateForUpdate();
+        updated.updateUserFederationProvider(provider);
+
+    }
+
+    @Override
     public String getLoginTheme() {
         if (updated != null) return updated.getLoginTheme();
         return cached.getLoginTheme();
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
index 2103f3f..ee94cf1 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
@@ -769,9 +769,9 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public void removeUserFederationProvider(UserFederationProviderModel provider) {
-        UserFederationProviderEntity entity = null;
         Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
         while (it.hasNext()) {
+            UserFederationProviderEntity entity = it.next();
             if (entity.getId().equals(provider.getId())) {
                 it.remove();
                 em.remove(entity);
@@ -779,6 +779,20 @@ public class RealmAdapter implements RealmModel {
             }
         }
     }
+    @Override
+    public void updateUserFederationProvider(UserFederationProviderModel model) {
+        Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
+        while (it.hasNext()) {
+            UserFederationProviderEntity entity = it.next();
+            if (entity.getId().equals(model.getId())) {
+                entity.setConfig(model.getConfig());
+                entity.setPriority(model.getPriority());
+                entity.setProviderName(model.getProviderName());
+                entity.setPriority(model.getPriority());
+                break;
+            }
+        }
+    }
 
     @Override
     public void setUserFederationProviders(List<UserFederationProviderModel> providers) {
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
index 2ce26cb..351ea6b 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
@@ -820,6 +820,20 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
     }
 
     @Override
+    public void updateUserFederationProvider(UserFederationProviderModel model) {
+        Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
+        while (it.hasNext()) {
+            UserFederationProviderEntity entity = it.next();
+            if (entity.getId().equals(model.getId())) {
+                entity.setProviderName(model.getProviderName());
+                entity.setConfig(model.getConfig());
+                entity.setPriority(model.getPriority());
+            }
+        }
+        updateRealm();
+    }
+
+    @Override
     public List<UserFederationProviderModel> getUserFederationProviders() {
         List<UserFederationProviderEntity> entities = realm.getUserFederationProviders();
         List<UserFederationProviderEntity> copy = new LinkedList<UserFederationProviderEntity>();
diff --git a/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java b/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java
index 94b3ea7..5df7859 100755
--- a/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java
+++ b/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java
@@ -10,6 +10,8 @@ import org.keycloak.provider.Spi;
 
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 import java.util.ServiceLoader;
 import java.util.Set;
@@ -84,6 +86,16 @@ public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory {
          return factoriesMap.get(clazz).get(id);
     }
 
+    @Override
+    public List<ProviderFactory> getProviderFactories(Class<? extends Provider> clazz) {
+        List<ProviderFactory> list = new LinkedList<ProviderFactory>();
+        if (factoriesMap == null) return list;
+        Map<String, ProviderFactory> providerFactoryMap = factoriesMap.get(clazz);
+        if (providerFactoryMap == null) return list;
+        list.addAll(providerFactoryMap.values());
+        return list;
+    }
+
     <T extends Provider> Set<String> getAllProviderIds(Class<T> clazz) {
         Set<String> ids = new HashSet<String>();
         for (ProviderFactory f : factoriesMap.get(clazz).values()) {
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
index 1a50ffa..2173d7e 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
@@ -192,6 +192,14 @@ public class RealmAdminResource {
         return users;
     }
 
+    @Path("user-federation")
+    public UserFederationResource userFederation() {
+        UserFederationResource fed = new UserFederationResource(realm, auth);
+        ResteasyProviderFactory.getInstance().injectProperties(fed);
+        //resourceContext.initResource(fed);
+        return fed;
+    }
+
     /**
      * Path for managing all realm-level or application-level roles defined in this realm by it's id.
      *
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UserFederationResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UserFederationResource.java
new file mode 100755
index 0000000..4ceef1c
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UserFederationResource.java
@@ -0,0 +1,199 @@
+package org.keycloak.services.resources.admin;
+
+import org.jboss.logging.Logger;
+import org.jboss.resteasy.annotations.cache.NoCache;
+import org.jboss.resteasy.spi.BadRequestException;
+import org.jboss.resteasy.spi.NotFoundException;
+import org.keycloak.email.EmailException;
+import org.keycloak.email.EmailProvider;
+import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.Constants;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ModelDuplicateException;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.SocialLinkModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserFederationProvider;
+import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.models.utils.ModelToRepresentation;
+import org.keycloak.models.utils.RepresentationToModel;
+import org.keycloak.provider.ProviderFactory;
+import org.keycloak.representations.adapters.action.UserStats;
+import org.keycloak.representations.idm.ApplicationMappingsRepresentation;
+import org.keycloak.representations.idm.CredentialRepresentation;
+import org.keycloak.representations.idm.MappingsRepresentation;
+import org.keycloak.representations.idm.RoleRepresentation;
+import org.keycloak.representations.idm.SocialLinkRepresentation;
+import org.keycloak.representations.idm.UserFederationProviderRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.representations.idm.UserSessionRepresentation;
+import org.keycloak.services.managers.AccessCode;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.services.managers.ResourceAdminManager;
+import org.keycloak.services.managers.TokenManager;
+import org.keycloak.services.managers.UserManager;
+import org.keycloak.services.resources.flows.Flows;
+import org.keycloak.services.resources.flows.Urls;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Base resource for managing users
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UserFederationResource {
+    protected static final Logger logger = Logger.getLogger(UserFederationResource.class);
+
+    protected RealmModel realm;
+
+    protected  RealmAuth auth;
+
+    @Context
+    protected UriInfo uriInfo;
+
+    @Context
+    protected KeycloakSession session;
+
+    public UserFederationResource(RealmModel realm, RealmAuth auth) {
+        this.auth = auth;
+        this.realm = realm;
+
+        auth.init(RealmAuth.Resource.USER);
+    }
+
+    /**
+     * Get List of available provider factories
+     *
+     * @return
+     */
+    @GET
+    @Path("providers")
+    @Produces("application/json")
+    public List<Map<String, String>> getProviders() {
+        logger.info("get provider list");
+        auth.requireView();
+        List<Map<String, String>> providers = new LinkedList<Map<String, String>>();
+        for (ProviderFactory factory : session.getKeycloakSessionFactory().getProviderFactories(UserFederationProvider.class)) {
+            Map<String, String> provider = new HashMap<String, String>();
+            provider.put("name", factory.getId());
+            providers.add(provider);
+        }
+        logger.info("provider list.size() " + providers.size());
+        return providers;
+    }
+
+    /**
+     * Create a provider
+     *
+     * @param rep
+     * @return
+     */
+    @POST
+    @Path("instances")
+    @Consumes("application/json")
+    public Response createProvider(UserFederationProviderRepresentation rep) {
+        logger.info("createProvider");
+        auth.requireManage();
+        UserFederationProviderModel model = realm.addUserFederationProvider(rep.getProviderName(), rep.getConfig(), rep.getPriority());
+        return Response.created(uriInfo.getAbsolutePathBuilder().path(model.getId()).build()).build();
+    }
+
+    /**
+     * Update a provider
+     *
+     * @param id
+     * @param rep
+     */
+    @PUT
+    @Path("instances/{id}")
+    @Consumes("application/json")
+    public void updateProvider(@PathParam("id") String id, UserFederationProviderRepresentation rep) {
+        logger.info("updateProvider");
+        auth.requireManage();
+        UserFederationProviderModel model = new UserFederationProviderModel(id, rep.getProviderName(), rep.getConfig(), rep.getPriority());
+        realm.updateUserFederationProvider(model);
+    }
+
+    /**
+     * get a provider
+     *
+     * @param id
+     */
+    @GET
+    @Path("instances/{id}")
+    @Consumes("application/json")
+    public UserFederationProviderRepresentation getProvider(@PathParam("id") String id) {
+        logger.info("getProvider");
+        auth.requireView();
+        for (UserFederationProviderModel model : realm.getUserFederationProviders()) {
+            if (model.getId().equals(id)) {
+                return ModelToRepresentation.toRepresentation(model);
+            }
+        }
+        throw new NotFoundException("could not find provider");
+    }
+
+    /**
+     * Delete a provider
+     *
+     * @param id
+     */
+    @DELETE
+    @Path("instances/{id}")
+    public void deleteProvider(@PathParam("id") String id) {
+        logger.info("deleteProvider");
+        auth.requireManage();
+        UserFederationProviderModel model = new UserFederationProviderModel(id, null, null, -1);
+        realm.removeUserFederationProvider(model);
+
+    }
+
+
+    /**
+     * list configured providers
+     *
+     * @return
+     */
+    @GET
+    @Path("instances")
+    @Produces("application/json")
+    public List<UserFederationProviderRepresentation> getUserFederationProviders() {
+        logger.info("getUserFederationProviders");
+        auth.requireManage();
+        List<UserFederationProviderRepresentation> reps = new LinkedList<UserFederationProviderRepresentation>();
+        for (UserFederationProviderModel model : realm.getUserFederationProviders()) {
+            UserFederationProviderRepresentation rep = ModelToRepresentation.toRepresentation(model);
+            reps.add(rep);
+        }
+        return reps;
+    }
+
+
+}
diff --git a/testsuite/integration/pom.xml b/testsuite/integration/pom.xml
index 3aab521..5ca079e 100755
--- a/testsuite/integration/pom.xml
+++ b/testsuite/integration/pom.xml
@@ -1,418 +1,416 @@
-<?xml version="1.0"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <artifactId>keycloak-testsuite-pom</artifactId>
-        <groupId>org.keycloak</groupId>
-        <version>1.0-beta-4-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>keycloak-testsuite-integration</artifactId>
-    <name>Keycloak Integration TestSuite</name>
-    <description />
-
-    <dependencyManagement>
-        <dependencies>
-            <dependency>
-                <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-as7-adapter</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-        </dependencies>
-    </dependencyManagement>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-dependencies-server-all</artifactId>
-            <version>${project.version}</version>
-            <type>pom</type>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-admin-client</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>log4j</groupId>
-            <artifactId>log4j</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-log4j12</artifactId>
-            <version>${slf4j.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.spec.javax.servlet</groupId>
-            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>jaxrs-api</artifactId>
-            <version>${resteasy.version.latest}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jaxrs</artifactId>
-            <version>${resteasy.version.latest}</version>
-            <exclusions>
-                <exclusion>
-                    <groupId>log4j</groupId>
-                    <artifactId>log4j</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-simple</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-client</artifactId>
-            <version>${resteasy.version.latest}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-crypto</artifactId>
-            <version>${resteasy.version.latest}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-multipart-provider</artifactId>
-            <version>${resteasy.version.latest}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jackson-provider</artifactId>
-            <version>${resteasy.version.latest}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-undertow</artifactId>
-            <version>${resteasy.version.latest}</version>
-        </dependency>
-        <dependency>
-            <groupId>com.google.zxing</groupId>
-            <artifactId>javase</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcprov-jdk16</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-            <version>${keycloak.apache.httpcomponents.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-ldap-federation</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-undertow-adapter</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>log4j</groupId>
-            <artifactId>log4j</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>io.undertow</groupId>
-            <artifactId>undertow-servlet</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>io.undertow</groupId>
-            <artifactId>undertow-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-core-asl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-mapper-asl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-xc</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.hamcrest</groupId>
-            <artifactId>hamcrest-all</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.hibernate.javax.persistence</groupId>
-            <artifactId>hibernate-jpa-2.0-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.h2database</groupId>
-            <artifactId>h2</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.hibernate</groupId>
-            <artifactId>hibernate-entitymanager</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.icegreen</groupId>
-            <artifactId>greenmail</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.seleniumhq.selenium</groupId>
-            <artifactId>selenium-java</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>xml-apis</groupId>
-            <artifactId>xml-apis</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.seleniumhq.selenium</groupId>
-            <artifactId>selenium-chrome-driver</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.picketbox</groupId>
-            <artifactId>picketbox-ldap</artifactId>
-            <scope>compile</scope>
-            <type>test-jar</type>
-        </dependency>
-        <dependency>
-            <groupId>org.picketbox</groupId>
-            <artifactId>picketbox-ldap</artifactId>
-            <scope>compile</scope>
-        </dependency>
-    </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-deploy-plugin</artifactId>
-                <configuration>
-                    <skip>true</skip>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>${maven.compiler.source}</source>
-                    <target>${maven.compiler.target}</target>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>exec-maven-plugin</artifactId>
-                <configuration>
-                    <workingDirectory>${project.basedir}</workingDirectory>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-    <profiles>
-        <profile>
-            <id>keycloak-server</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <configuration>
-                            <mainClass>org.keycloak.testutils.KeycloakServer</mainClass>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>mail-server</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <configuration>
-                            <mainClass>org.keycloak.testutils.MailServer</mainClass>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-        <profile>
-            <id>totp</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>exec-maven-plugin</artifactId>
-                        <configuration>
-                            <mainClass>org.keycloak.testutils.TotpGenerator</mainClass>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <profile>
-            <id>jpa</id>
-
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <configuration>
-                            <systemPropertyVariables>
-                                <keycloak.realm.provider>jpa</keycloak.realm.provider>
-                                <keycloak.user.provider>jpa</keycloak.user.provider>
-                                <keycloak.audit.provider>jpa</keycloak.audit.provider>
-                                <keycloak.userSessions.provider>jpa</keycloak.userSessions.provider>
-                            </systemPropertyVariables>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-
-        <profile>
-            <id>mongo</id>
-
-            <properties>
-                <keycloak.connectionsMongo.host>localhost</keycloak.connectionsMongo.host>
-                <keycloak.connectionsMongo.port>27018</keycloak.connectionsMongo.port>
-                <keycloak.connectionsMongo.db>keycloak</keycloak.connectionsMongo.db>
-                <keycloak.connectionsMongo.clearOnStartup>true</keycloak.connectionsMongo.clearOnStartup>
-                <keycloak.connectionsMongo.bindIp>127.0.0.1</keycloak.connectionsMongo.bindIp>
-            </properties>
-
-            <build>
-                <plugins>
-
-                    <!-- Postpone tests to "integration-test" phase, so that we can bootstrap embedded mongo on 27018 before running tests -->
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-surefire-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>test</id>
-                                <phase>integration-test</phase>
-                                <goals>
-                                    <goal>test</goal>
-                                </goals>
-                                <configuration>
-                                    <systemPropertyVariables>
-                                        <keycloak.realm.provider>mongo</keycloak.realm.provider>
-                                        <keycloak.user.provider>mongo</keycloak.user.provider>
-                                        <keycloak.audit.provider>mongo</keycloak.audit.provider>
-                                        <keycloak.userSessions.provider>mongo</keycloak.userSessions.provider>
-                                        <keycloak.connectionsMongo.host>${keycloak.connectionsMongo.host}</keycloak.connectionsMongo.host>
-                                        <keycloak.connectionsMongo.port>${keycloak.connectionsMongo.port}</keycloak.connectionsMongo.port>
-                                        <keycloak.connectionsMongo.db>${keycloak.connectionsMongo.db}</keycloak.connectionsMongo.db>
-                                        <keycloak.connectionsMongo.clearOnStartup>${keycloak.connectionsMongo.clearOnStartup}</keycloak.connectionsMongo.clearOnStartup>
-                                        <keycloak.connectionsMongo.bindIp>${keycloak.connectionsMongo.bindIp}</keycloak.connectionsMongo.bindIp>
-                                    </systemPropertyVariables>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>default-test</id>
-                                <configuration>
-                                    <skip>true</skip>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-
-                    <!-- Embedded mongo -->
-                    <plugin>
-                        <groupId>com.github.joelittlejohn.embedmongo</groupId>
-                        <artifactId>embedmongo-maven-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>start-mongodb</id>
-                                <phase>pre-integration-test</phase>
-                                <goals>
-                                    <goal>start</goal>
-                                </goals>
-                                <configuration>
-                                    <port>${keycloak.connectionsMongo.port}</port>
-                                    <logging>file</logging>
-                                    <logFile>${project.build.directory}/mongodb.log</logFile>
-                                    <bindIp>${keycloak.connectionsMongo.bindIp}</bindIp>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>stop-mongodb</id>
-                                <phase>post-integration-test</phase>
-                                <goals>
-                                    <goal>stop</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-
-        </profile>
-
-        <!-- MySQL -->
-        <profile>
-            <activation>
-                <property>
-                    <name>keycloak.connectionsJpa.driver</name>
-                    <value>com.mysql.jdbc.Driver</value>
-                </property>
-            </activation>
-            <id>mysql</id>
-            <dependencies>
-                <dependency>
-                    <groupId>mysql</groupId>
-                    <artifactId>mysql-connector-java</artifactId>
-                    <version>${mysql.version}</version>
-                </dependency>
-            </dependencies>
-        </profile>
-
-        <!-- PostgreSQL -->
-        <profile>
-            <activation>
-                <property>
-                    <name>keycloak.connectionsJpa.driver</name>
-                    <value>org.postgresql.Driver</value>
-                </property>
-            </activation>
-            <id>postgresql</id>
-            <dependencies>
-                <dependency>
-                    <groupId>org.postgresql</groupId>
-                    <artifactId>postgresql</artifactId>
-                    <version>${postgresql.version}</version>
-                </dependency>
-            </dependencies>
-        </profile>
-
-    </profiles>
-</project>
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-testsuite-pom</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.0-beta-4-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>keycloak-testsuite-integration</artifactId>
+    <name>Keycloak Integration TestSuite</name>
+    <description />
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-as7-adapter</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-dependencies-server-all</artifactId>
+            <version>${project.version}</version>
+            <type>pom</type>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-admin-client</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+            <version>${slf4j.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>jaxrs-api</artifactId>
+            <version>${resteasy.version.latest}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <version>${resteasy.version.latest}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>log4j</groupId>
+                    <artifactId>log4j</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-simple</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-client</artifactId>
+            <version>${resteasy.version.latest}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-crypto</artifactId>
+            <version>${resteasy.version.latest}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-multipart-provider</artifactId>
+            <version>${resteasy.version.latest}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jackson-provider</artifactId>
+            <version>${resteasy.version.latest}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-undertow</artifactId>
+            <version>${resteasy.version.latest}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>javase</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk16</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>${keycloak.apache.httpcomponents.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-ldap-federation</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-undertow-adapter</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-servlet</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-core-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-xc</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest-all</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate.javax.persistence</groupId>
+            <artifactId>hibernate-jpa-2.0-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.h2database</groupId>
+            <artifactId>h2</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-entitymanager</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.icegreen</groupId>
+            <artifactId>greenmail</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.seleniumhq.selenium</groupId>
+            <artifactId>selenium-java</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>xml-apis</groupId>
+            <artifactId>xml-apis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.seleniumhq.selenium</groupId>
+            <artifactId>selenium-chrome-driver</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.picketbox</groupId>
+            <artifactId>picketbox-ldap</artifactId>
+            <type>test-jar</type>
+        </dependency>
+        <dependency>
+            <groupId>org.picketbox</groupId>
+            <artifactId>picketbox-ldap</artifactId>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>exec-maven-plugin</artifactId>
+                <configuration>
+                    <workingDirectory>${project.basedir}</workingDirectory>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>keycloak-server</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <configuration>
+                            <mainClass>org.keycloak.testutils.KeycloakServer</mainClass>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>mail-server</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <configuration>
+                            <mainClass>org.keycloak.testutils.MailServer</mainClass>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>totp</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <configuration>
+                            <mainClass>org.keycloak.testutils.TotpGenerator</mainClass>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <profile>
+            <id>jpa</id>
+
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <configuration>
+                            <systemPropertyVariables>
+                                <keycloak.realm.provider>jpa</keycloak.realm.provider>
+                                <keycloak.user.provider>jpa</keycloak.user.provider>
+                                <keycloak.audit.provider>jpa</keycloak.audit.provider>
+                                <keycloak.userSessions.provider>jpa</keycloak.userSessions.provider>
+                            </systemPropertyVariables>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <profile>
+            <id>mongo</id>
+
+            <properties>
+                <keycloak.connectionsMongo.host>localhost</keycloak.connectionsMongo.host>
+                <keycloak.connectionsMongo.port>27018</keycloak.connectionsMongo.port>
+                <keycloak.connectionsMongo.db>keycloak</keycloak.connectionsMongo.db>
+                <keycloak.connectionsMongo.clearOnStartup>true</keycloak.connectionsMongo.clearOnStartup>
+                <keycloak.connectionsMongo.bindIp>127.0.0.1</keycloak.connectionsMongo.bindIp>
+            </properties>
+
+            <build>
+                <plugins>
+
+                    <!-- Postpone tests to "integration-test" phase, so that we can bootstrap embedded mongo on 27018 before running tests -->
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>test</id>
+                                <phase>integration-test</phase>
+                                <goals>
+                                    <goal>test</goal>
+                                </goals>
+                                <configuration>
+                                    <systemPropertyVariables>
+                                        <keycloak.realm.provider>mongo</keycloak.realm.provider>
+                                        <keycloak.user.provider>mongo</keycloak.user.provider>
+                                        <keycloak.audit.provider>mongo</keycloak.audit.provider>
+                                        <keycloak.userSessions.provider>mongo</keycloak.userSessions.provider>
+                                        <keycloak.connectionsMongo.host>${keycloak.connectionsMongo.host}</keycloak.connectionsMongo.host>
+                                        <keycloak.connectionsMongo.port>${keycloak.connectionsMongo.port}</keycloak.connectionsMongo.port>
+                                        <keycloak.connectionsMongo.db>${keycloak.connectionsMongo.db}</keycloak.connectionsMongo.db>
+                                        <keycloak.connectionsMongo.clearOnStartup>${keycloak.connectionsMongo.clearOnStartup}</keycloak.connectionsMongo.clearOnStartup>
+                                        <keycloak.connectionsMongo.bindIp>${keycloak.connectionsMongo.bindIp}</keycloak.connectionsMongo.bindIp>
+                                    </systemPropertyVariables>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>default-test</id>
+                                <configuration>
+                                    <skip>true</skip>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+
+                    <!-- Embedded mongo -->
+                    <plugin>
+                        <groupId>com.github.joelittlejohn.embedmongo</groupId>
+                        <artifactId>embedmongo-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>start-mongodb</id>
+                                <phase>pre-integration-test</phase>
+                                <goals>
+                                    <goal>start</goal>
+                                </goals>
+                                <configuration>
+                                    <port>${keycloak.connectionsMongo.port}</port>
+                                    <logging>file</logging>
+                                    <logFile>${project.build.directory}/mongodb.log</logFile>
+                                    <bindIp>${keycloak.connectionsMongo.bindIp}</bindIp>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>stop-mongodb</id>
+                                <phase>post-integration-test</phase>
+                                <goals>
+                                    <goal>stop</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+
+        </profile>
+
+        <!-- MySQL -->
+        <profile>
+            <activation>
+                <property>
+                    <name>keycloak.connectionsJpa.driver</name>
+                    <value>com.mysql.jdbc.Driver</value>
+                </property>
+            </activation>
+            <id>mysql</id>
+            <dependencies>
+                <dependency>
+                    <groupId>mysql</groupId>
+                    <artifactId>mysql-connector-java</artifactId>
+                    <version>${mysql.version}</version>
+                </dependency>
+            </dependencies>
+        </profile>
+
+        <!-- PostgreSQL -->
+        <profile>
+            <activation>
+                <property>
+                    <name>keycloak.connectionsJpa.driver</name>
+                    <value>org.postgresql.Driver</value>
+                </property>
+            </activation>
+            <id>postgresql</id>
+            <dependencies>
+                <dependency>
+                    <groupId>org.postgresql</groupId>
+                    <artifactId>postgresql</artifactId>
+                    <version>${postgresql.version}</version>
+                </dependency>
+            </dependencies>
+        </profile>
+
+    </profiles>
+</project>
diff --git a/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java b/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java
index 4e22fc5..1e1836f 100755
--- a/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java
+++ b/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java
@@ -104,8 +104,27 @@ public class KeycloakServer {
     }
 
     public static void main(String[] args) throws Throwable {
+        //bootstrapLdap();  Can't seem to get this to work.
         bootstrapKeycloakServer(args);
     }
+    private static LDAPEmbeddedServer embeddedServer;
+    public static void bootstrapLdap() throws Exception {
+        embeddedServer = new LDAPEmbeddedServer();
+        embeddedServer.setup();
+        embeddedServer.importLDIF("ldap/users.ldif");
+        Runtime.getRuntime().addShutdownHook(new Thread() {
+            @Override
+            public void run() {
+                try {
+                    embeddedServer.tearDown();
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        });
+
+
+    }
 
     public static KeycloakServer bootstrapKeycloakServer(String[] args) throws Throwable {
         KeycloakServerConfig config = new KeycloakServerConfig();
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/FederationProvidersIntegrationTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/FederationProvidersIntegrationTest.java
index d638db4..ba16262 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/FederationProvidersIntegrationTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/FederationProvidersIntegrationTest.java
@@ -3,6 +3,7 @@ package org.keycloak.testsuite.forms;
 import org.junit.Assert;
 import org.junit.ClassRule;
 import org.junit.FixMethodOrder;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.RuleChain;
@@ -10,8 +11,7 @@ import org.junit.rules.TestRule;
 import org.junit.runners.MethodSorters;
 import org.keycloak.OAuth2Constants;
 import org.keycloak.federation.ldap.LDAPFederationProviderFactory;
-import org.keycloak.models.UserFederationProviderModel;
-import org.keycloak.testsuite.LDAPEmbeddedServer;
+import org.keycloak.testutils.LDAPEmbeddedServer;
 import org.keycloak.testsuite.LDAPTestUtils;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.LDAPConstants;
@@ -32,7 +32,6 @@ import org.keycloak.testsuite.rule.WebResource;
 import org.keycloak.testsuite.rule.WebRule;
 import org.openqa.selenium.WebDriver;
 
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -44,6 +43,8 @@ public class FederationProvidersIntegrationTest {
 
     private static LDAPRule ldapRule = new LDAPRule();
 
+    private static Map<String,String> ldapConfig = null;
+
     private static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakRule.KeycloakSetup() {
 
         @Override
@@ -52,13 +53,15 @@ public class FederationProvidersIntegrationTest {
             addUser(manager.getSession(), adminstrationRealm, "mary-admin", "mary@admin.com", "password-admin");
 
             LDAPEmbeddedServer ldapServer = ldapRule.getEmbeddedServer();
-            Map<String,String> ldapConfig = new HashMap<String,String>();
+            ldapConfig = new HashMap<String,String>();
             ldapConfig.put(LDAPConstants.CONNECTION_URL, ldapServer.getConnectionUrl());
             ldapConfig.put(LDAPConstants.BASE_DN, ldapServer.getBaseDn());
             ldapConfig.put(LDAPConstants.BIND_DN, ldapServer.getBindDn());
             ldapConfig.put(LDAPConstants.BIND_CREDENTIAL, ldapServer.getBindCredential());
             ldapConfig.put(LDAPConstants.USER_DN_SUFFIX, ldapServer.getUserDnSuffix());
-            ldapConfig.put(LDAPConstants.VENDOR, ldapServer.getVendor());
+            String vendor = ldapServer.getVendor();
+            ldapConfig.put(LDAPConstants.VENDOR, vendor);
+
 
 
             appRealm.addUserFederationProvider(LDAPFederationProviderFactory.PROVIDER_NAME, ldapConfig, 0);
@@ -112,6 +115,16 @@ public class FederationProvidersIntegrationTest {
     }
 
     @Test
+    @Ignore
+    public void runit() throws Exception {
+        System.out.println("*** ldap config ***");
+        for (Map.Entry<String, String> entry : ldapConfig.entrySet()) {
+            System.out.println("key: " + entry.getKey() + " value: " + entry.getValue());
+        }
+        Thread.sleep(10000000);
+    }
+
+    @Test
     public void loginClassic() {
         loginPage.open();
         loginPage.login("mary", "password-app");
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AuthProvidersLDAPTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AuthProvidersLDAPTest.java
index 56bbb91..4894f9b 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AuthProvidersLDAPTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AuthProvidersLDAPTest.java
@@ -10,7 +10,7 @@ import org.junit.runners.MethodSorters;
 import org.keycloak.authentication.AuthProviderConstants;
 import org.keycloak.authentication.AuthenticationProviderException;
 import org.keycloak.authentication.AuthenticationProviderManager;
-import org.keycloak.testsuite.LDAPEmbeddedServer;
+import org.keycloak.testutils.LDAPEmbeddedServer;
 import org.keycloak.testsuite.LDAPTestUtils;
 import org.keycloak.models.AuthenticationLinkModel;
 import org.keycloak.models.AuthenticationProviderModel;
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/LDAPRule.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/LDAPRule.java
old mode 100644
new mode 100755
index b2b4aae..8cd9793
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/LDAPRule.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/LDAPRule.java
@@ -1,7 +1,7 @@
 package org.keycloak.testsuite.rule;
 
 import org.junit.rules.ExternalResource;
-import org.keycloak.testsuite.LDAPEmbeddedServer;
+import org.keycloak.testutils.LDAPEmbeddedServer;
 
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>