keycloak-memoizeit

Changes

testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/CreateUsers.java 77(+0 -77)

Details

diff --git a/authentication/authentication-api/src/main/java/org/keycloak/authentication/AuthenticationProviderManager.java b/authentication/authentication-api/src/main/java/org/keycloak/authentication/AuthenticationProviderManager.java
index 20d08bb..9c81665 100755
--- a/authentication/authentication-api/src/main/java/org/keycloak/authentication/AuthenticationProviderManager.java
+++ b/authentication/authentication-api/src/main/java/org/keycloak/authentication/AuthenticationProviderManager.java
@@ -70,7 +70,7 @@ public class AuthenticationProviderManager {
         AuthenticationLinkModel authLink = user.getAuthenticationLink();
         if (authLink == null) {
             // User not yet linked with any authenticationProvider. Find provider with biggest priority where he is and link
-            AuthUser authUser = getUser(user.getLoginName());
+            AuthUser authUser = getUser(user.getUsername());
             authLink = new AuthenticationLinkModel(authUser.getProviderName(), authUser.getId());
             user.setAuthenticationLink(authLink);
             logger.infof("User '%s' linked with provider '%s'", authUser.getUsername(), authUser.getProviderName());
@@ -85,10 +85,10 @@ public class AuthenticationProviderManager {
         }
 
         try {
-            checkCorrectAuthLink(delegate, providerModel, authLink, user.getLoginName());
+            checkCorrectAuthLink(delegate, providerModel, authLink, user.getUsername());
 
-            AuthProviderStatus currentResult = delegate.validatePassword(realm, providerModel.getConfig(), user.getLoginName(), password);
-            logger.debugf("Authentication provider '%s' finished with '%s' for authentication of '%s'", delegate.getName(), currentResult.toString(), user.getLoginName());
+            AuthProviderStatus currentResult = delegate.validatePassword(realm, providerModel.getConfig(), user.getUsername(), password);
+            logger.debugf("Authentication provider '%s' finished with '%s' for authentication of '%s'", delegate.getName(), currentResult.toString(), user.getUsername());
             return currentResult;
         } catch (AuthenticationProviderException ape) {
             logger.warn(ape.getMessage(), ape);
@@ -105,7 +105,7 @@ public class AuthenticationProviderManager {
                 if (providerModel.isPasswordUpdateSupported()) {
                     AuthenticationProvider delegate = getProvider(providerModel.getProviderName());
                     if (delegate != null) {
-                        AuthUser authUser = delegate.getUser(realm, providerModel.getConfig(), user.getLoginName());
+                        AuthUser authUser = delegate.getUser(realm, providerModel.getConfig(), user.getUsername());
                         if (authUser != null) {
                             // Linking existing user supported just for "model" provider. In other cases throw exception
                             if (providerModel.getProviderName().equals(AuthenticationProviderModel.DEFAULT_PROVIDER.getProviderName())) {
@@ -120,7 +120,7 @@ public class AuthenticationProviderManager {
                             String userIdInProvider = delegate.registerUser(realm, providerModel.getConfig(), user);
                             authLink = new AuthenticationLinkModel(providerModel.getProviderName(), userIdInProvider);
                             user.setAuthenticationLink(authLink);
-                            logger.infof("User '%s' registered in provider '%s' and linked", user.getLoginName(), providerModel.getProviderName());
+                            logger.infof("User '%s' registered in provider '%s' and linked", user.getUsername(), providerModel.getProviderName());
                         }
                         break;
                     }
@@ -128,7 +128,7 @@ public class AuthenticationProviderManager {
             }
 
             if (authLink == null) {
-                logger.warnf("No providers found where password update is supported for user '%s'", user.getLoginName());
+                logger.warnf("No providers found where password update is supported for user '%s'", user.getUsername());
                 return false;
             }
         }
@@ -140,7 +140,7 @@ public class AuthenticationProviderManager {
             return false;
         }
 
-        String username = user.getLoginName();
+        String username = user.getUsername();
 
         // Update just if password update is supported
         if (providerModel.isPasswordUpdateSupported()) {
@@ -152,7 +152,7 @@ public class AuthenticationProviderManager {
 
                 checkCorrectAuthLink(delegate, providerModel, authLink, username);
 
-                if (delegate.updateCredential(realm,providerModel.getConfig(), user.getLoginName(), password)) {
+                if (delegate.updateCredential(realm,providerModel.getConfig(), user.getUsername(), password)) {
                     logger.debugf("Updated password in authentication provider '%s' for user '%s'", providerName, username);
                     return true;
                 } else {
diff --git a/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/AbstractModelAuthenticationProvider.java b/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/AbstractModelAuthenticationProvider.java
index ea20abc..d3433a9 100755
--- a/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/AbstractModelAuthenticationProvider.java
+++ b/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/AbstractModelAuthenticationProvider.java
@@ -32,7 +32,7 @@ public abstract class AbstractModelAuthenticationProvider implements Authenticat
     @Override
     public String registerUser(RealmModel currentRealm, Map<String, String> config, UserModel user) throws AuthenticationProviderException {
         RealmModel realm = getRealm(currentRealm, config);
-        UserModel newUser = realm.addUser(user.getLoginName());
+        UserModel newUser = realm.addUser(user.getUsername());
         newUser.setFirstName(user.getFirstName());
         newUser.setLastName(user.getLastName());
         newUser.setEmail(user.getEmail());
@@ -80,7 +80,7 @@ public abstract class AbstractModelAuthenticationProvider implements Authenticat
     protected abstract RealmModel getRealm(RealmModel currentRealm, Map<String, String> config) throws AuthenticationProviderException;
 
     protected AuthUser createAuthenticatedUserInstance(UserModel user) {
-        return new AuthUser(user.getId(), user.getLoginName(), getName())
+        return new AuthUser(user.getId(), user.getUsername(), getName())
                 .setName(user.getFirstName(), user.getLastName())
                 .setEmail(user.getEmail());
     }
diff --git a/authentication/authentication-picketlink/src/main/java/org/keycloak/authentication/picketlink/PicketlinkAuthenticationProvider.java b/authentication/authentication-picketlink/src/main/java/org/keycloak/authentication/picketlink/PicketlinkAuthenticationProvider.java
index 772f6da..6cbcaad 100755
--- a/authentication/authentication-picketlink/src/main/java/org/keycloak/authentication/picketlink/PicketlinkAuthenticationProvider.java
+++ b/authentication/authentication-picketlink/src/main/java/org/keycloak/authentication/picketlink/PicketlinkAuthenticationProvider.java
@@ -72,7 +72,7 @@ public class PicketlinkAuthenticationProvider implements AuthenticationProvider 
         IdentityManager identityManager = getIdentityManager(realm);
 
         try {
-            User picketlinkUser = new User(user.getLoginName());
+            User picketlinkUser = new User(user.getUsername());
             picketlinkUser.setFirstName(user.getFirstName());
             picketlinkUser.setLastName(user.getLastName());
             picketlinkUser.setEmail(user.getEmail());
diff --git a/examples/providers/authentication-properties/src/main/java/org/keycloak/examples/providers/authentication/PropertiesAuthenticationProvider.java b/examples/providers/authentication-properties/src/main/java/org/keycloak/examples/providers/authentication/PropertiesAuthenticationProvider.java
index 9b83ec0..8c5ff1a 100644
--- a/examples/providers/authentication-properties/src/main/java/org/keycloak/examples/providers/authentication/PropertiesAuthenticationProvider.java
+++ b/examples/providers/authentication-properties/src/main/java/org/keycloak/examples/providers/authentication/PropertiesAuthenticationProvider.java
@@ -48,7 +48,7 @@ public class PropertiesAuthenticationProvider implements AuthenticationProvider 
     @Override
     public String registerUser(RealmModel realm, Map<String, String> configuration, UserModel user) throws AuthenticationProviderException {
         // Registration ignored
-        return user.getLoginName();
+        return user.getUsername();
     }
 
     @Override
diff --git a/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ModelExporter.java b/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ModelExporter.java
index eb6b363..951ea73 100755
--- a/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ModelExporter.java
+++ b/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ModelExporter.java
@@ -211,7 +211,7 @@ public class ModelExporter {
 
                 this.propertiesManager.setBasicPropertiesFromModel(userModel, userEntity);
 
-                userEntity.setLoginName(userModel.getLoginName());
+                userEntity.setUsername(userModel.getUsername());
                 userEntity.setRealmId(realm.getId());
 
                 // authentication links
diff --git a/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ModelImporter.java b/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ModelImporter.java
index 6ff1fa9..c187bb8 100755
--- a/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ModelImporter.java
+++ b/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ModelImporter.java
@@ -243,7 +243,7 @@ public class ModelImporter {
         List<UserEntity> users = this.importReader.readEntities(fileName, UserEntity.class);
         for (UserEntity userEntity : users) {
             RealmModel realm = session.getRealm(userEntity.getRealmId());
-            UserModel user = realm.addUser(userEntity.getId(), userEntity.getLoginName());
+            UserModel user = realm.addUser(userEntity.getId(), userEntity.getUsername());
 
             // We need to remove defaultRoles here as realm.addUser is automatically adding them. We may add them later during roles mapping processing
             for (RoleModel role : user.getRoleMappings()) {
diff --git a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/AccountBean.java b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/AccountBean.java
index b07d38b..06ef6c2 100644
--- a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/AccountBean.java
+++ b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/AccountBean.java
@@ -22,7 +22,7 @@ public class AccountBean {
     }
 
     public String getUsername() {
-        return user.getLoginName();
+        return user.getUsername();
     }
 
     public String getEmail() {
diff --git a/model/api/src/main/java/org/keycloak/models/entities/UserEntity.java b/model/api/src/main/java/org/keycloak/models/entities/UserEntity.java
index f1248b0..2297eed 100644
--- a/model/api/src/main/java/org/keycloak/models/entities/UserEntity.java
+++ b/model/api/src/main/java/org/keycloak/models/entities/UserEntity.java
@@ -11,14 +11,13 @@ import org.keycloak.models.UserModel;
  */
 public class UserEntity extends AbstractIdentifiableEntity {
 
-    private String loginName;
+    private String username;
     private String firstName;
     private String lastName;
     private String email;
     private boolean emailVerified;
     private boolean totp;
     private boolean enabled;
-    private int notBefore;
 
     private String realmId;
 
@@ -30,12 +29,12 @@ public class UserEntity extends AbstractIdentifiableEntity {
     private List<SocialLinkEntity> socialLinks;
     private AuthenticationLinkEntity authenticationLink;
 
-    public String getLoginName() {
-        return loginName;
+    public String getUsername() {
+        return username;
     }
 
-    public void setLoginName(String loginName) {
-        this.loginName = loginName;
+    public void setUsername(String username) {
+        this.username = username;
     }
 
     public String getFirstName() {
@@ -86,14 +85,6 @@ public class UserEntity extends AbstractIdentifiableEntity {
         this.enabled = enabled;
     }
 
-    public int getNotBefore() {
-        return notBefore;
-    }
-
-    public void setNotBefore(int notBefore) {
-        this.notBefore = notBefore;
-    }
-
     public String getRealmId() {
         return realmId;
     }
diff --git a/model/api/src/main/java/org/keycloak/models/UserModel.java b/model/api/src/main/java/org/keycloak/models/UserModel.java
index 3a7bd0b..621148e 100755
--- a/model/api/src/main/java/org/keycloak/models/UserModel.java
+++ b/model/api/src/main/java/org/keycloak/models/UserModel.java
@@ -16,9 +16,9 @@ public interface UserModel {
 
     String getId();
 
-    String getLoginName();
+    String getUsername();
 
-    void setLoginName(String loginName);
+    void setUsername(String username);
 
     boolean isEnabled();
 
@@ -58,9 +58,6 @@ public interface UserModel {
 
     void setTotp(boolean totp);
 
-    int getNotBefore();
-    void setNotBefore(int notBefore);
-
     void updateCredential(UserCredentialModel cred);
 
     List<UserCredentialValueModel> getCredentialsDirectly();
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedUser.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedUser.java
index 465f08f..ee0318f 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedUser.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedUser.java
@@ -19,14 +19,13 @@ import java.util.Set;
  */
 public class CachedUser {
     private String id;
-    private String loginName;
+    private String username;
     private String usernameKey;
     private String firstName;
     private String lastName;
     private String email;
     private String emailKey;
     private boolean emailVerified;
-    private int notBefore;
     private List<UserCredentialValueModel> credentials = new LinkedList<UserCredentialValueModel>();
     private boolean enabled;
     private boolean totp;
@@ -38,8 +37,8 @@ public class CachedUser {
 
     public CachedUser(RealmModel realm, UserModel user) {
         this.id = user.getId();
-        this.loginName = user.getLoginName();
-        this.usernameKey = realm.getId() + "." + this.loginName;
+        this.username = user.getUsername();
+        this.usernameKey = realm.getId() + "." + this.username;
         this.firstName = user.getFirstName();
         this.lastName = user.getLastName();
         this.attributes.putAll(user.getAttributes());
@@ -48,7 +47,6 @@ public class CachedUser {
             this.emailKey = realm.getId() + "." + this.email;
         }
         this.emailVerified = user.isEmailVerified();
-        this.notBefore = user.getNotBefore();
         this.credentials.addAll(user.getCredentialsDirectly());
         this.enabled = user.isEnabled();
         this.totp = user.isTotp();
@@ -63,8 +61,8 @@ public class CachedUser {
         return id;
     }
 
-    public String getLoginName() {
-        return loginName;
+    public String getUsername() {
+        return username;
     }
 
     public String getUsernameKey() {
@@ -91,10 +89,6 @@ public class CachedUser {
         return emailVerified;
     }
 
-    public int getNotBefore() {
-        return notBefore;
-    }
-
     public List<UserCredentialValueModel> getCredentials() {
         return credentials;
     }
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserAdapter.java
index 727244c..b48e1c5 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserAdapter.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserAdapter.java
@@ -47,15 +47,15 @@ public class UserAdapter implements UserModel {
     }
 
     @Override
-    public String getLoginName() {
-        if (updated != null) return updated.getLoginName();
-        return cached.getLoginName();
+    public String getUsername() {
+        if (updated != null) return updated.getUsername();
+        return cached.getUsername();
     }
 
     @Override
-    public void setLoginName(String loginName) {
+    public void setUsername(String username) {
         getDelegateForUpdate();
-        updated.setLoginName(loginName);
+        updated.setUsername(username);
     }
 
     @Override
@@ -173,18 +173,6 @@ public class UserAdapter implements UserModel {
     }
 
     @Override
-    public int getNotBefore() {
-        if (updated != null) return updated.getNotBefore();
-        return cached.getNotBefore();
-    }
-
-    @Override
-    public void setNotBefore(int notBefore) {
-        getDelegateForUpdate();
-        updated.setNotBefore(notBefore);
-    }
-
-    @Override
     public void updateCredential(UserCredentialModel cred) {
         getDelegateForUpdate();
         updated.updateCredential(cred);
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java
index 3b765b4..75389c9 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java
@@ -35,28 +35,27 @@ import java.util.Set;
  */
 @NamedQueries({
         @NamedQuery(name="getRealmUserById", query="select u from UserEntity u where u.id = :id and u.realm = :realm"),
-        @NamedQuery(name="getRealmUserByLoginName", query="select u from UserEntity u where u.loginName = :loginName and u.realm = :realm"),
+        @NamedQuery(name="getRealmUserByUsername", query="select u from UserEntity u where u.username = :username and u.realm = :realm"),
         @NamedQuery(name="getRealmUserByEmail", query="select u from UserEntity u where u.email = :email and u.realm = :realm"),
         @NamedQuery(name="getRealmUserByLastName", query="select u from UserEntity u where u.lastName = :lastName and u.realm = :realm"),
         @NamedQuery(name="getRealmUserByFirstLastName", query="select u from UserEntity u where u.firstName = :first and u.lastName = :last and u.realm = :realm")
 })
 @Entity
 @Table(uniqueConstraints = {
-        @UniqueConstraint(columnNames = { "realm", "loginName" }),
+        @UniqueConstraint(columnNames = { "realm", "username" }),
         @UniqueConstraint(columnNames = { "realm", "emailConstraint" })
 })
 public class UserEntity {
     @Id
     protected String id;
 
-    protected String loginName;
+    protected String username;
     protected String firstName;
     protected String lastName;
     protected String email;
     protected boolean enabled;
     protected boolean totp;
     protected boolean emailVerified;
-    protected int notBefore;
 
     // Hack just to workaround the fact that on MS-SQL you can't have unique constraint with multiple NULL values TODO: Find better solution (like unique index with 'where' but that's proprietary)
     protected String emailConstraint = KeycloakModelUtils.generateId();
@@ -89,12 +88,12 @@ public class UserEntity {
         this.id = id;
     }
 
-    public String getLoginName() {
-        return loginName;
+    public String getUsername() {
+        return username;
     }
 
-    public void setLoginName(String loginName) {
-        this.loginName = loginName;
+    public void setUsername(String username) {
+        this.username = username;
     }
 
     public String getFirstName() {
@@ -194,11 +193,4 @@ public class UserEntity {
         this.authenticationLink = authenticationLink;
     }
 
-    public int getNotBefore() {
-        return notBefore;
-    }
-
-    public void setNotBefore(int notBefore) {
-        this.notBefore = notBefore;
-    }
 }
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaModelProvider.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaModelProvider.java
index b750373..940e067 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaModelProvider.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaModelProvider.java
@@ -93,8 +93,8 @@ public class JpaModelProvider implements ModelProvider {
 
     @Override
     public UserModel getUserByUsername(String username, RealmModel realmModel) {
-        TypedQuery<UserEntity> query = em.createNamedQuery("getRealmUserByLoginName", UserEntity.class);
-        query.setParameter("loginName", username);
+        TypedQuery<UserEntity> query = em.createNamedQuery("getRealmUserByUsername", UserEntity.class);
+        query.setParameter("username", username);
         RealmEntity realm = em.getReference(RealmEntity.class, realmModel.getId());
         query.setParameter("realm", realm);
         List<UserEntity> results = query.getResultList();
@@ -130,7 +130,7 @@ public class JpaModelProvider implements ModelProvider {
         }
 
         for (UserEntity u : em.createQuery("from UserEntity u where u.realm = :realm", UserEntity.class).setParameter("realm", realm).getResultList()) {
-            adapter.removeUser(u.getLoginName());
+            adapter.removeUser(u.getUsername());
         }
 
         em.remove(realm);
@@ -185,7 +185,7 @@ public class JpaModelProvider implements ModelProvider {
 
     @Override
     public List<UserModel> searchForUser(String search, RealmModel realm) {
-        TypedQuery<UserEntity> query = em.createQuery("select u from UserEntity u where u.realm = :realm and ( lower(u.loginName) like :search or lower(concat(u.firstName, ' ', u.lastName)) like :search or u.email like :search )", UserEntity.class);
+        TypedQuery<UserEntity> query = em.createQuery("select u from UserEntity u where u.realm = :realm and ( lower(u.username) like :search or lower(concat(u.firstName, ' ', u.lastName)) like :search or u.email like :search )", UserEntity.class);
         RealmEntity realmEntity = em.getReference(RealmEntity.class, realm.getId());
         query.setParameter("realm", realmEntity);
         query.setParameter("search", "%" + search.toLowerCase() + "%");
@@ -202,7 +202,7 @@ public class JpaModelProvider implements ModelProvider {
         for (Map.Entry<String, String> entry : attributes.entrySet()) {
             String attribute = null;
             if (entry.getKey().equals(UserModel.LOGIN_NAME)) {
-                attribute = "lower(loginName)";
+                attribute = "lower(username)";
             } else if (entry.getKey().equalsIgnoreCase(UserModel.FIRST_NAME)) {
                 attribute = "lower(firstName)";
             } else if (entry.getKey().equalsIgnoreCase(UserModel.LAST_NAME)) {
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 0c2f66a..390dea4 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
@@ -463,7 +463,7 @@ public class RealmAdapter implements RealmModel {
     public UserModel addUser(String id, String username) {
         UserEntity entity = new UserEntity();
         entity.setId(id);
-        entity.setLoginName(username);
+        entity.setUsername(username);
         entity.setRealm(realm);
         em.persist(entity);
         em.flush();
@@ -484,8 +484,8 @@ public class RealmAdapter implements RealmModel {
 
     @Override
     public boolean removeUser(String name) {
-        TypedQuery<UserEntity> query = em.createNamedQuery("getRealmUserByLoginName", UserEntity.class);
-        query.setParameter("loginName", name);
+        TypedQuery<UserEntity> query = em.createNamedQuery("getRealmUserByUsername", UserEntity.class);
+        query.setParameter("username", name);
         query.setParameter("realm", realm);
         List<UserEntity> results = query.getResultList();
         if (results.size() == 0) return false;
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java
index 25e6fa3..18219f6 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java
@@ -54,13 +54,13 @@ public class UserAdapter implements UserModel {
     }
 
     @Override
-    public String getLoginName() {
-        return user.getLoginName();
+    public String getUsername() {
+        return user.getUsername();
     }
 
     @Override
-    public void setLoginName(String loginName) {
-        user.setLoginName(loginName);
+    public void setUsername(String username) {
+        user.setUsername(username);
     }
 
     @Override
@@ -175,16 +175,6 @@ public class UserAdapter implements UserModel {
     }
 
     @Override
-    public int getNotBefore() {
-        return user.getNotBefore();
-    }
-
-    @Override
-    public void setNotBefore(int notBefore) {
-        user.setNotBefore(notBefore);
-    }
-
-    @Override
     public void updateCredential(UserCredentialModel cred) {
         CredentialEntity credentialEntity = getCredentialEntity(user, cred.getType());
 
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoModelProvider.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoModelProvider.java
index 739bbc0..efc8277 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoModelProvider.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoModelProvider.java
@@ -132,7 +132,7 @@ public class MongoModelProvider implements ModelProvider {
     @Override
     public UserModel getUserByUsername(String username, RealmModel realm) {
         DBObject query = new QueryBuilder()
-                .and("loginName").is(username)
+                .and("username").is(username)
                 .and("realmId").is(realm.getId())
                 .get();
         MongoUserEntity user = getMongoStore().loadSingleEntity(MongoUserEntity.class, query, invocationContext);
@@ -226,7 +226,7 @@ public class MongoModelProvider implements ModelProvider {
         QueryBuilder builder = new QueryBuilder().and(
                 new QueryBuilder().and("realmId").is(realm.getId()).get(),
                 new QueryBuilder().or(
-                        new QueryBuilder().put("loginName").regex(caseInsensitivePattern).get(),
+                        new QueryBuilder().put("username").regex(caseInsensitivePattern).get(),
                         new QueryBuilder().put("email").regex(caseInsensitivePattern).get(),
                         nameBuilder.get()
 
@@ -243,7 +243,7 @@ public class MongoModelProvider implements ModelProvider {
 
         for (Map.Entry<String, String> entry : attributes.entrySet()) {
             if (entry.getKey().equals(UserModel.LOGIN_NAME)) {
-                queryBuilder.and("loginName").regex(Pattern.compile("(?i:" + entry.getValue() + "$)"));
+                queryBuilder.and("username").regex(Pattern.compile("(?i:" + entry.getValue() + "$)"));
             } else if (entry.getKey().equalsIgnoreCase(UserModel.FIRST_NAME)) {
                 queryBuilder.and(UserModel.FIRST_NAME).regex(Pattern.compile("(?i:" + entry.getValue() + "$)"));
 
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 0109804..0b75af0 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
@@ -504,7 +504,7 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
     protected UserAdapter addUserEntity(String id, String username) {
         MongoUserEntity userEntity = new MongoUserEntity();
         userEntity.setId(id);
-        userEntity.setLoginName(username);
+        userEntity.setUsername(username);
         // Compatibility with JPA model, which has user disabled by default
         // userEntity.setEnabled(true);
         userEntity.setRealmId(getId());
@@ -516,7 +516,7 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
     @Override
     public boolean removeUser(String name) {
         DBObject query = new QueryBuilder()
-                .and("loginName").is(name)
+                .and("username").is(name)
                 .and("realmId").is(getId())
                 .get();
         return getMongoStore().removeEntities(MongoUserEntity.class, query, invocationContext);
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java
index 3a1d14d..8e21f7e 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java
@@ -50,13 +50,13 @@ public class UserAdapter extends AbstractMongoAdapter<MongoUserEntity> implement
     }
 
     @Override
-    public String getLoginName() {
-        return user.getLoginName();
+    public String getUsername() {
+        return user.getUsername();
     }
 
     @Override
-    public void setLoginName(String loginName) {
-        user.setLoginName(loginName);
+    public void setUsername(String username) {
+        user.setUsername(username);
         updateUser();
     }
 
@@ -72,16 +72,6 @@ public class UserAdapter extends AbstractMongoAdapter<MongoUserEntity> implement
     }
 
     @Override
-    public int getNotBefore() {
-        return user.getNotBefore();
-    }
-
-    @Override
-    public void setNotBefore(int notBefore) {
-        user.setNotBefore(notBefore);
-    }
-
-    @Override
     public String getFirstName() {
         return user.getFirstName();
     }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRoleEntity.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRoleEntity.java
index f931a91..afc649f 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRoleEntity.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoRoleEntity.java
@@ -50,7 +50,7 @@ public class MongoRoleEntity extends RoleEntity implements MongoIdentifiableEnti
 
         List<MongoUserEntity> users = mongoStore.loadEntities(MongoUserEntity.class, query, invContext);
         for (MongoUserEntity user : users) {
-            logger.info("Removing role " + getName() + " from user " + user.getLoginName());
+            logger.info("Removing role " + getName() + " from user " + user.getUsername());
             mongoStore.pullItemFromList(user, "roleIds", getId(), invContext);
         }
 
@@ -61,7 +61,7 @@ public class MongoRoleEntity extends RoleEntity implements MongoIdentifiableEnti
 
         users = mongoStore.loadEntities(MongoUserEntity.class, query, invContext);
         for (MongoUserEntity user : users) {
-            logger.info("Removing scope " + getName() + " from user " + user.getLoginName());
+            logger.info("Removing scope " + getName() + " from user " + user.getUsername());
             mongoStore.pullItemFromList(user, "scopeIds", getId(), invContext);
         }
 
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoUserEntity.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoUserEntity.java
index 084a153..9399ae2 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoUserEntity.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/MongoUserEntity.java
@@ -14,7 +14,7 @@ import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
  */
 @MongoCollection(collectionName = "users")
 @MongoIndexes({
-        @MongoIndex(fields = { "realmId", "loginName" }, unique = true),
+        @MongoIndex(fields = { "realmId", "username" }, unique = true),
         @MongoIndex(fields = { "emailIndex" }, unique = true, sparse = true),
 })
 public class MongoUserEntity extends UserEntity implements MongoIdentifiableEntity {
diff --git a/model/tests/src/test/java/org/keycloak/model/test/AdapterTest.java b/model/tests/src/test/java/org/keycloak/model/test/AdapterTest.java
index e5b8766..fa0460d 100755
--- a/model/tests/src/test/java/org/keycloak/model/test/AdapterTest.java
+++ b/model/tests/src/test/java/org/keycloak/model/test/AdapterTest.java
@@ -169,7 +169,7 @@ public class AdapterTest extends AbstractModelTest {
         RoleModel appRole = app.addRole("test");
         user.grantRole(appRole);
 
-        SocialLinkModel socialLink = new SocialLinkModel("google", "google1", user.getLoginName());
+        SocialLinkModel socialLink = new SocialLinkModel("google", "google1", user.getUsername());
         realmModel.addSocialLink(user, socialLink);
 
         UserCredentialModel cred = new UserCredentialModel();
@@ -321,7 +321,7 @@ public class AdapterTest extends AbstractModelTest {
         {
             ArrayList<String> users = new ArrayList<String>();
             for (UserModel u : adapter.searchUsers("ole alver", realmModel)) {
-                users.add(u.getLoginName());
+                users.add(u.getUsername());
             }
             String[] usernames = users.toArray(new String[users.size()]);
             Arrays.sort(usernames);
@@ -634,7 +634,7 @@ public class AdapterTest extends AbstractModelTest {
         realmManager.getRealmByName("JUGGLER1").addUser("user2");
         commit();
         try {
-            realmManager.getRealmByName("JUGGLER1").getUser("user2").setLoginName("user1");
+            realmManager.getRealmByName("JUGGLER1").getUser("user2").setUsername("user1");
             commit();
             Assert.fail("Expected exception");
         } catch (ModelDuplicateException e) {
diff --git a/model/tests/src/test/java/org/keycloak/model/test/AuthProvidersExternalModelTest.java b/model/tests/src/test/java/org/keycloak/model/test/AuthProvidersExternalModelTest.java
index 5b04316..f2b3a77 100755
--- a/model/tests/src/test/java/org/keycloak/model/test/AuthProvidersExternalModelTest.java
+++ b/model/tests/src/test/java/org/keycloak/model/test/AuthProvidersExternalModelTest.java
@@ -91,7 +91,7 @@ public class AuthProvidersExternalModelTest extends AbstractModelTest {
             Assert.assertEquals(AuthenticationManager.AuthenticationStatus.SUCCESS, am.authenticateForm(null, realm2, formData));
             UserModel john2 = realm2.getUser("john");
             Assert.assertNotNull(john2);
-            Assert.assertEquals("john", john2.getLoginName());
+            Assert.assertEquals("john", john2.getUsername());
             Assert.assertEquals("John", john2.getFirstName());
             Assert.assertEquals("Doe", john2.getLastName());
             Assert.assertEquals("john@email.org", john2.getEmail());
diff --git a/model/tests/src/test/java/org/keycloak/model/test/AuthProvidersLDAPTest.java b/model/tests/src/test/java/org/keycloak/model/test/AuthProvidersLDAPTest.java
index a39c033..10383de 100755
--- a/model/tests/src/test/java/org/keycloak/model/test/AuthProvidersLDAPTest.java
+++ b/model/tests/src/test/java/org/keycloak/model/test/AuthProvidersLDAPTest.java
@@ -89,7 +89,7 @@ public class AuthProvidersLDAPTest extends AbstractModelTest {
         Assert.assertEquals(AuthenticationManager.AuthenticationStatus.SUCCESS, am.authenticateForm(null, realm, formData));
         UserModel john = realm.getUser("johnkeycloak");
         Assert.assertNotNull(john);
-        Assert.assertEquals("johnkeycloak", john.getLoginName());
+        Assert.assertEquals("johnkeycloak", john.getUsername());
         Assert.assertEquals("John", john.getFirstName());
         Assert.assertEquals("Doe", john.getLastName());
         Assert.assertEquals("john@email.org", john.getEmail());
diff --git a/model/tests/src/test/java/org/keycloak/model/test/ImportTest.java b/model/tests/src/test/java/org/keycloak/model/test/ImportTest.java
index 4264ff7..dd7d12e 100755
--- a/model/tests/src/test/java/org/keycloak/model/test/ImportTest.java
+++ b/model/tests/src/test/java/org/keycloak/model/test/ImportTest.java
@@ -173,7 +173,7 @@ public class ImportTest extends AbstractModelTest {
         Assert.assertTrue(facebookFound && twitterFound && googleFound);
 
         UserModel foundSocialUser = realm.getUserBySocialLink(new SocialLinkModel("facebook", "facebook1", "fbuser1"));
-        Assert.assertEquals(foundSocialUser.getLoginName(), socialUser.getLoginName());
+        Assert.assertEquals(foundSocialUser.getUsername(), socialUser.getUsername());
         Assert.assertNull(realm.getUserBySocialLink(new SocialLinkModel("facebook", "not-existing", "not-existing")));
 
         SocialLinkModel foundSocialLink = realm.getSocialLink(socialUser, "facebook");
diff --git a/model/tests/src/test/java/org/keycloak/model/test/MultipleRealmsTest.java b/model/tests/src/test/java/org/keycloak/model/test/MultipleRealmsTest.java
index 4ea8ab2..a3eda8c 100755
--- a/model/tests/src/test/java/org/keycloak/model/test/MultipleRealmsTest.java
+++ b/model/tests/src/test/java/org/keycloak/model/test/MultipleRealmsTest.java
@@ -33,7 +33,7 @@ public class MultipleRealmsTest extends AbstractModelTest {
     public void testUsers() {
         UserModel r1user1 = realm1.getUser("user1");
         UserModel r2user1 = realm2.getUser("user1");
-        Assert.assertEquals(r1user1.getLoginName(), r2user1.getLoginName());
+        Assert.assertEquals(r1user1.getUsername(), r2user1.getUsername());
         Assert.assertNotEquals(r1user1.getId(), r2user1.getId());
 
         // Test password
diff --git a/model/tests/src/test/java/org/keycloak/model/test/UserModelTest.java b/model/tests/src/test/java/org/keycloak/model/test/UserModelTest.java
index 132e39c..3de0ae2 100755
--- a/model/tests/src/test/java/org/keycloak/model/test/UserModelTest.java
+++ b/model/tests/src/test/java/org/keycloak/model/test/UserModelTest.java
@@ -111,7 +111,7 @@ public class UserModelTest extends AbstractModelTest {
     }
 
     public static void assertEquals(UserModel expected, UserModel actual) {
-        Assert.assertEquals(expected.getLoginName(), actual.getLoginName());
+        Assert.assertEquals(expected.getUsername(), actual.getUsername());
         Assert.assertEquals(expected.getFirstName(), actual.getFirstName());
         Assert.assertEquals(expected.getLastName(), actual.getLastName());
         Assert.assertArrayEquals(expected.getRequiredActions().toArray(), actual.getRequiredActions().toArray());
diff --git a/project-integrations/aerogear-ups/auth-server/src/main/java/org/aerogear/ups/security/UpsSecurityApplication.java b/project-integrations/aerogear-ups/auth-server/src/main/java/org/aerogear/ups/security/UpsSecurityApplication.java
index 9f322e1..ef7a1ef 100755
--- a/project-integrations/aerogear-ups/auth-server/src/main/java/org/aerogear/ups/security/UpsSecurityApplication.java
+++ b/project-integrations/aerogear-ups/auth-server/src/main/java/org/aerogear/ups/security/UpsSecurityApplication.java
@@ -31,7 +31,7 @@ public class UpsSecurityApplication extends KeycloakApplication {
             RealmManager manager = new RealmManager(session);
             RealmModel master = manager.getKeycloakAdminstrationRealm();
             UserModel admin = master.getUser("admin");
-            if (admin != null) master.removeUser(admin.getLoginName());
+            if (admin != null) master.removeUser(admin.getUsername());
             session.getTransaction().commit();
         } finally {
             session.close();
diff --git a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
index 26fe574..96aab65 100755
--- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
@@ -69,7 +69,7 @@ public class AuthenticationManager {
         if (session == null) return;
         UserModel user = session.getUser();
 
-        logger.infov("Logging out: {0} ({1})", user.getLoginName(), session.getId());
+        logger.infov("Logging out: {0} ({1})", user.getUsername(), session.getId());
 
         realm.removeUserSession(session);
         expireIdentityCookie(realm, uriInfo);
@@ -205,11 +205,6 @@ public class AuthenticationManager {
                 return null;
             }
 
-            if (token.getIssuedAt() < user.getNotBefore()) {
-                logger.info("Stale cookie");
-                return null;
-            }
-
             UserSessionModel session = realm.getUserSession(token.getSessionState());
             if (!isSessionValid(realm, session)) {
                 if (session != null) logout(realm, session, uriInfo);
@@ -343,7 +338,7 @@ public class AuthenticationManager {
 
     private boolean checkEnabled(UserModel user) {
         if (!user.isEnabled()) {
-            logger.warn("AccountProvider is disabled, contact admin. " + user.getLoginName());
+            logger.warn("AccountProvider is disabled, contact admin. " + user.getUsername());
             return false;
         } else {
             return true;
diff --git a/services/src/main/java/org/keycloak/services/managers/ModelToRepresentation.java b/services/src/main/java/org/keycloak/services/managers/ModelToRepresentation.java
index 49ca015..4a27c2d 100755
--- a/services/src/main/java/org/keycloak/services/managers/ModelToRepresentation.java
+++ b/services/src/main/java/org/keycloak/services/managers/ModelToRepresentation.java
@@ -38,7 +38,7 @@ public class ModelToRepresentation {
     public static UserRepresentation toRepresentation(UserModel user) {
         UserRepresentation rep = new UserRepresentation();
         rep.setId(user.getId());
-        rep.setUsername(user.getLoginName());
+        rep.setUsername(user.getUsername());
         rep.setLastName(user.getLastName());
         rep.setFirstName(user.getFirstName());
         rep.setEmail(user.getEmail());
@@ -190,7 +190,7 @@ public class ModelToRepresentation {
         rep.setId(session.getId());
         rep.setStart(((long)session.getStarted()) * 1000L);
         rep.setLastAccess(((long)session.getLastSessionRefresh())* 1000L);
-        rep.setUser(session.getUser().getLoginName());
+        rep.setUser(session.getUser().getUsername());
         rep.setIpAddress(session.getIpAddress());
         for (ClientModel client : session.getClientAssociations()) {
             if (client instanceof ApplicationModel) {
diff --git a/services/src/main/java/org/keycloak/services/managers/RealmManager.java b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
index 6fae8e7..aba6233 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -370,7 +370,7 @@ public class RealmManager {
         if (rep.getUsers() != null) {
             for (UserRepresentation userRep : rep.getUsers()) {
                 UserModel user = createUser(newRealm, userRep);
-                userMap.put(user.getLoginName(), user);
+                userMap.put(user.getUsername(), user);
             }
         }
 
diff --git a/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java b/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java
index 2498eda..35a118e 100755
--- a/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java
@@ -79,7 +79,7 @@ public class ResourceAdminManager {
                     for (Map.Entry<String, UserStats> entry : stats.getUsers().entrySet()) {
                         UserModel user = realm.getUserById(entry.getKey());
                         if (user == null) continue;
-                        newUsers.put(user.getLoginName(), entry.getValue());
+                        newUsers.put(user.getUsername(), entry.getValue());
 
                     }
                     stats.setUsers(newUsers);
diff --git a/services/src/main/java/org/keycloak/services/managers/TokenManager.java b/services/src/main/java/org/keycloak/services/managers/TokenManager.java
index c28825a..73270e9 100755
--- a/services/src/main/java/org/keycloak/services/managers/TokenManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/TokenManager.java
@@ -155,7 +155,7 @@ public class TokenManager {
             throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Unmatching clients", "Unmatching clients");
         }
 
-        if (refreshToken.getIssuedAt() < client.getNotBefore() || refreshToken.getIssuedAt() < user.getNotBefore()) {
+        if (refreshToken.getIssuedAt() < client.getNotBefore()) {
             throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale refresh token");
         }
 
@@ -262,7 +262,7 @@ public class TokenManager {
 
     public void initClaims(IDToken token, ClientModel model, UserModel user) {
         if (ClaimMask.hasUsername(model.getAllowedClaimsMask())) {
-            token.setPreferredUsername(user.getLoginName());
+            token.setPreferredUsername(user.getUsername());
         }
         if (ClaimMask.hasEmail(model.getAllowedClaimsMask())) {
             token.setEmail(user.getEmail());
@@ -284,7 +284,7 @@ public class TokenManager {
         token.subject(user.getId());
         token.audience(realm.getName());
         token.issuedNow();
-        token.issuedFor(client.getLoginName());
+        token.issuedFor(client.getUsername());
         token.issuer(realm.getName());
         if (realm.getAccessTokenLifespan() > 0) {
             token.expiration(Time.currentTime() + realm.getAccessTokenLifespan());
diff --git a/services/src/main/java/org/keycloak/services/resources/AccountService.java b/services/src/main/java/org/keycloak/services/resources/AccountService.java
index aa34c27..1641757 100755
--- a/services/src/main/java/org/keycloak/services/resources/AccountService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java
@@ -514,7 +514,7 @@ public class AccountService {
                     if (realm.getSocialLinks(user).size() > 1 || user.getAuthenticationLink() != null) {
                         realm.removeSocialLink(user, providerId);
 
-                        logger.debug("Social provider " + providerId + " removed successfully from user " + user.getLoginName());
+                        logger.debug("Social provider " + providerId + " removed successfully from user " + user.getUsername());
 
                         audit.event(EventType.REMOVE_SOCIAL_LINK).client(auth.getClient()).user(auth.getUser())
                                 .detail(Details.USERNAME, link.getSocialUserId() + "@" + link.getSocialProvider())
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java
index 8976f2b..a7c2f7d 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java
@@ -185,7 +185,7 @@ public class AdminConsole {
                 displayName = displayName != null ? displayName + " " + user.getLastName() : user.getLastName();
             }
         } else {
-            displayName = user.getLoginName();
+            displayName = user.getUsername();
         }
 
         RealmModel masterRealm = getAdminstrationRealm(realmManager);
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java
index deb3513..98a29f4 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java
@@ -182,7 +182,7 @@ public class AdminRoot {
 
         AdminAuth auth = authenticateRealmAdminRequest(headers);
         if (auth != null) {
-            logger.info("authenticated admin access for: " + auth.getUser().getLoginName());
+            logger.info("authenticated admin access for: " + auth.getUser().getUsername());
         }
 
         Cors.add(request).allowedOrigins(auth.getToken()).allowedMethods("GET", "PUT", "POST", "DELETE").auth().build(response);
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
index 788cc56..5b503a5 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
@@ -127,7 +127,7 @@ public class UsersResource {
             UserModel user = realm.addUser(rep.getUsername());
             updateUserFromRep(user, rep);
 
-            return Response.created(uriInfo.getAbsolutePathBuilder().path(user.getLoginName()).build()).build();
+            return Response.created(uriInfo.getAbsolutePathBuilder().path(user.getUsername()).build()).build();
         } catch (ModelDuplicateException e) {
             return Flows.errors().exists("User exists with same username or email");
         }
@@ -277,8 +277,6 @@ public class UsersResource {
             throw new NotFoundException("User not found");
         }
         realm.removeUserSessions(user);
-        // set notBefore so that user will be forced to log in.
-        user.setNotBefore(Time.currentTime());
         new ResourceAdminManager().logoutUser(uriInfo.getRequestUri(), realm, user.getId(), null);
     }
 
diff --git a/services/src/main/java/org/keycloak/services/resources/RequiredActionsService.java b/services/src/main/java/org/keycloak/services/resources/RequiredActionsService.java
index 269fa51..64e680f 100755
--- a/services/src/main/java/org/keycloak/services/resources/RequiredActionsService.java
+++ b/services/src/main/java/org/keycloak/services/resources/RequiredActionsService.java
@@ -381,7 +381,7 @@ public class RequiredActionsService {
     }
 
     private UserModel getUser(AccessCodeEntry accessCode) {
-        return realm.getUser(accessCode.getUser().getLoginName());
+        return realm.getUser(accessCode.getUser().getUsername());
     }
 
     private Response redirectOauth(UserModel user, AccessCodeEntry accessCode) {
diff --git a/services/src/main/java/org/keycloak/services/resources/SocialResource.java b/services/src/main/java/org/keycloak/services/resources/SocialResource.java
index c59c8f6..2da3ec8 100755
--- a/services/src/main/java/org/keycloak/services/resources/SocialResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/SocialResource.java
@@ -212,7 +212,7 @@ public class SocialResource {
             }
 
             realm.addSocialLink(authenticatedUser, socialLink);
-            logger.debug("Social provider " + provider.getId() + " linked with user " + authenticatedUser.getLoginName());
+            logger.debug("Social provider " + provider.getId() + " linked with user " + authenticatedUser.getUsername());
 
             audit.success();
             return Response.status(302).location(UriBuilder.fromUri(redirectUri).build()).build();
diff --git a/services/src/main/java/org/keycloak/services/resources/TokenService.java b/services/src/main/java/org/keycloak/services/resources/TokenService.java
index 93949d1..371d8c4 100755
--- a/services/src/main/java/org/keycloak/services/resources/TokenService.java
+++ b/services/src/main/java/org/keycloak/services/resources/TokenService.java
@@ -830,7 +830,7 @@ public class TokenService {
             UserModel user = authResult.getUser();
             UserSessionModel session = authResult.getSession();
 
-            logger.debug(user.getLoginName() + " already logged in.");
+            logger.debug(user.getUsername() + " already logged in.");
             audit.user(user).session(session).detail(Details.AUTH_METHOD, "sso");
             return oauth.processAccessCode(scopeParam, state, redirect, client, user, session, null, false, "sso", audit);
         }
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 c401f0a..45bb7cc 100755
--- a/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java
+++ b/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java
@@ -201,6 +201,10 @@ public class KeycloakServer {
         return server;
     }
 
+    public KeycloakServerConfig getConfig() {
+        return config;
+    }
+
     public void importRealm(InputStream realm) {
         RealmRepresentation rep = loadJson(realm, RealmRepresentation.class);
         importRealm(rep);
diff --git a/testsuite/performance-web/pom.xml b/testsuite/performance-web/pom.xml
index e2d61db..b9fee7c 100644
--- a/testsuite/performance-web/pom.xml
+++ b/testsuite/performance-web/pom.xml
@@ -216,11 +216,11 @@
                                     <preserveDirectories>false</preserveDirectories>
 
                                     <requestGroups>
-                                        <requestGroup>
+                                        <requestGroup implementation="com.lazerycode.jmeter.analyzer.config.RequestGroup">
                                             <name>aggregatedRequests</name>
                                             <pattern>* request</pattern>
                                         </requestGroup>
-                                        <requestGroup>
+                                        <requestGroup implementation="com.lazerycode.jmeter.analyzer.config.RequestGroup">
                                             <name>codes</name>
                                             <pattern>**/perf-app/perf-servlet?code=*</pattern>
                                         </requestGroup>
diff --git a/testsuite/performance-web/README.md b/testsuite/performance-web/README.md
index 950e90c..7546378 100644
--- a/testsuite/performance-web/README.md
+++ b/testsuite/performance-web/README.md
@@ -53,10 +53,20 @@ http://localhost:8081/keycloak-tools/perf/perf-realm/get-users-count?prefix=user
 
 For adding 10000 new users into your database (will start from last added user, so you don't need to explicitly check how many users to create are needed:
 ```shell 
-http://localhost:8081/keycloak-tools/perf/perf-realm/create-available-users?prefix=user&count=10000&batch=100&roles=user
+http://localhost:8081/keycloak-tools/perf/perf-realm/create-available-users?prefix=user&count=10000&batch=100&async=true&roles=role-0,role-1
 ````
 
-Seeing progress of job for creating users
+For update role mappings of all users:
+```shell 
+http://localhost:8081/keycloak-tools/perf/perf-realm/update-all-users?prefix=user&async=true&roles=role-3,perf-app:approle-3,perf-app:approle-4
+````
+
+For deleting all users:
+```shell 
+http://localhost:8081/keycloak-tools/perf/perf-realm/delete-all-users?prefix=user
+````
+
+Seeing progress of job for creating/updating/deleting users
 ```shell 
 http://localhost:8081/keycloak-tools/perf/jobs
 ````
diff --git a/testsuite/performance-web/src/main/java/org/keycloak/testsuite/performance/web/KeycloakPerfServer.java b/testsuite/performance-web/src/main/java/org/keycloak/testsuite/performance/web/KeycloakPerfServer.java
index 5dde02e..cb9e239 100644
--- a/testsuite/performance-web/src/main/java/org/keycloak/testsuite/performance/web/KeycloakPerfServer.java
+++ b/testsuite/performance-web/src/main/java/org/keycloak/testsuite/performance/web/KeycloakPerfServer.java
@@ -85,6 +85,7 @@ public class KeycloakPerfServer {
 
         ServletInfo servlet = new ServletInfo("PerfAppServlet", PerfAppServlet.class);
         servlet.addMapping("/perf-servlet/*");
+        servlet.addInitParam(PerfAppServlet.BASE_URL_INIT_PARAM, "http://" + keycloakServer.getConfig().getHost() + ":" + keycloakServer.getConfig().getPort());
 
         deploymentInfo.addServlet(servlet);
 
diff --git a/testsuite/performance-web/src/main/java/org/keycloak/testsuite/performance/web/OAuthClient.java b/testsuite/performance-web/src/main/java/org/keycloak/testsuite/performance/web/OAuthClient.java
index bb6e0c1..40409ad 100644
--- a/testsuite/performance-web/src/main/java/org/keycloak/testsuite/performance/web/OAuthClient.java
+++ b/testsuite/performance-web/src/main/java/org/keycloak/testsuite/performance/web/OAuthClient.java
@@ -42,7 +42,7 @@ import org.keycloak.util.BasicAuthHelper;
  */
 public class OAuthClient {
 
-    private String baseUrl = "http://localhost:8081/auth";
+    private String baseUrl;
 
     private String realm = "perf-realm";
 
@@ -52,16 +52,19 @@ public class OAuthClient {
 
     private String clientId = "perf-app";
 
-    private String redirectUri = "http://localhost:8081/perf-app/perf-servlet";
+    private String redirectUri;
 
     private String state = "123";
 
     private PublicKey realmPublicKey;
 
-    public OAuthClient() {
+    public OAuthClient(String baseUrl) {
         try {
             JSONObject realmJson = new JSONObject(IOUtils.toString(getClass().getResourceAsStream("/perfrealm.json")));
             realmPublicKey = PemUtils.decodePublicKey(realmJson.getString("publicKey"));
+
+            this.baseUrl = (baseUrl != null) ? baseUrl + "/auth" : "http://localhost:8081/auth";
+            this.redirectUri = baseUrl + "/perf-app/perf-servlet";
         } catch (Exception e) {
             throw new RuntimeException("Failed to retrieve realm public key", e);
         }
diff --git a/testsuite/performance-web/src/main/java/org/keycloak/testsuite/performance/web/PerfAppServlet.java b/testsuite/performance-web/src/main/java/org/keycloak/testsuite/performance/web/PerfAppServlet.java
index 52cf1fa..dbab2da 100644
--- a/testsuite/performance-web/src/main/java/org/keycloak/testsuite/performance/web/PerfAppServlet.java
+++ b/testsuite/performance-web/src/main/java/org/keycloak/testsuite/performance/web/PerfAppServlet.java
@@ -25,6 +25,8 @@ import org.keycloak.util.Time;
  */
 public class PerfAppServlet extends HttpServlet {
 
+    public static final String BASE_URL_INIT_PARAM = "baseUrl";
+
     private Template indexTemplate;
     private OAuthClient oauthClient;
 
@@ -35,7 +37,8 @@ public class PerfAppServlet extends HttpServlet {
             cfg.setTemplateLoader(new ClassTemplateLoader(getClass(), "/"));
             indexTemplate = cfg.getTemplate("perf-app-resources/index.ftl");
 
-            oauthClient = new OAuthClient();
+            String baseUrl = getInitParameter(BASE_URL_INIT_PARAM);
+            oauthClient = new OAuthClient(baseUrl);
         } catch (IOException ioe) {
             throw new ServletException(ioe);
         }
diff --git a/testsuite/performance-web/src/main/resources/perfrealm.json b/testsuite/performance-web/src/main/resources/perfrealm.json
index 1fab9a5..78d31ea 100644
--- a/testsuite/performance-web/src/main/resources/perfrealm.json
+++ b/testsuite/performance-web/src/main/resources/perfrealm.json
@@ -8,7 +8,6 @@
     "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
     "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
     "requiredCredentials": [ "password" ],
-    "defaultRoles": [ "user" ],
     "smtpServer": {
         "from": "auto@keycloak.org",
         "host": "localhost",
@@ -30,7 +29,7 @@
             "name" : "third-party",
             "enabled": true,
             "redirectUris": [
-                "http://localhost:8081/app/*"
+                "/app/*"
             ],
             "secret": "password"
         }
@@ -48,41 +47,55 @@
         },
         {
             "client": "perf-app",
-            "roles": ["user"]
+            "roles": [ "role-0", "role-1", "role-2", "role-3", "role-4" ]
         }
     ],
     "applications": [
         {
             "name": "perf-app",
             "enabled": true,
-            "baseUrl": "http://localhost:8081/perf-app",
+            "baseUrl": "/perf-app",
             "redirectUris": [
-                "http://localhost:8081/perf-app/*"
+                "/perf-app/*"
             ],
-            "adminUrl": "http://localhost:8081/perf-app/perf-servlet",
+            "adminUrl": "/perf-app/perf-servlet",
             "secret": "password"
          }
     ],
     "roles" : {
         "realm" : [
             {
-                "name": "user",
-                "description": "Have User privileges"
+                "name": "role-0"
+            },
+            {
+                "name": "role-1"
+            },
+            {
+                "name": "role-2"
+            },
+            {
+                "name": "role-3"
             },
             {
-                "name": "admin",
-                "description": "Have Administrator privileges"
+                "name": "role-4"
             }
         ],
         "application" : {
             "perf-app" : [
                 {
-                    "name": "customer-user",
-                    "description": "Have Customer User privileges"
+                    "name": "approle-0"
+                },
+                {
+                    "name": "approle-1"
+                },
+                {
+                    "name": "approle-2"
+                },
+                {
+                    "name": "approle-3"
                 },
                 {
-                    "name": "customer-admin",
-                    "description": "Have Customer Admin privileges"
+                    "name": "approle-4"
                 }
             ]
         }
diff --git a/testsuite/performance-web/src/test/jmeter/keycloak_web_perf_test.jmx b/testsuite/performance-web/src/test/jmeter/keycloak_web_perf_test.jmx
index 07074aa..07f16ef 100644
--- a/testsuite/performance-web/src/test/jmeter/keycloak_web_perf_test.jmx
+++ b/testsuite/performance-web/src/test/jmeter/keycloak_web_perf_test.jmx
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<jmeterTestPlan version="1.2" properties="2.6" jmeter="2.11 r1554548">
+<jmeterTestPlan version="1.2" properties="2.5" jmeter="2.10 r1533061">
   <hashTree>
     <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true">
       <stringProp name="TestPlan.comments"></stringProp>
@@ -166,7 +166,7 @@
           <stringProp name="HTTPSampler.response_timeout"></stringProp>
           <stringProp name="HTTPSampler.protocol"></stringProp>
           <stringProp name="HTTPSampler.contentEncoding"></stringProp>
-          <stringProp name="HTTPSampler.path">/auth/realms/perf-realm/tokens/auth/request/login?response_type=code&amp;redirect_uri=http%3A%2F%2Flocalhost%3A8081%2Fperf-app%2Fperf-servlet&amp;state=123&amp;client_id=perf-app</stringProp>
+          <stringProp name="HTTPSampler.path">/auth/realms/perf-realm/tokens/auth/request/login?response_type=code&amp;redirect_uri=http%3A%2F%2F${host}%3A${port}%2Fperf-app%2Fperf-servlet&amp;state=123&amp;client_id=perf-app</stringProp>
           <stringProp name="HTTPSampler.method">POST</stringProp>
           <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
           <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
@@ -322,6 +322,32 @@
             <bytes>true</bytes>
           </value>
         </objProp>
+        <objProp>
+          <value class="SampleSaveConfiguration">
+            <time>true</time>
+            <latency>true</latency>
+            <timestamp>true</timestamp>
+            <success>true</success>
+            <label>true</label>
+            <code>true</code>
+            <message>true</message>
+            <threadName>true</threadName>
+            <dataType>true</dataType>
+            <encoding>false</encoding>
+            <assertions>true</assertions>
+            <subresults>true</subresults>
+            <responseData>false</responseData>
+            <samplerData>false</samplerData>
+            <xml>false</xml>
+            <fieldNames>false</fieldNames>
+            <responseHeaders>false</responseHeaders>
+            <requestHeaders>false</requestHeaders>
+            <responseDataOnError>false</responseDataOnError>
+            <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
+            <assertionsResultsToSave>0</assertionsResultsToSave>
+            <bytes>true</bytes>
+          </value>
+        </objProp>
         <stringProp name="filename"></stringProp>
       </ResultCollector>
       <hashTree/>
diff --git a/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/CreateUsersJob.java b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/CreateUsersJob.java
new file mode 100644
index 0000000..b00f08f
--- /dev/null
+++ b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/CreateUsersJob.java
@@ -0,0 +1,50 @@
+package org.keycloak.test.tools.jobs;
+
+import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserModel;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class CreateUsersJob extends UsersJob {
+
+    private String[] roles;
+
+    public CreateUsersJob(String[] roles) {
+        this.roles = roles;
+    }
+
+    @Override
+    protected void before(KeycloakSession session) {
+    }
+
+    @Override
+    protected void runIteration(RealmModel realm, Map<String, ApplicationModel> apps, Set<RoleModel> realmRoles, Map<String, Set<RoleModel>> appRoles, int counter) {
+        String username = prefix + "-" + counter;
+        UserModel user = realm.addUser(username);
+        user.setEnabled(true);
+        user.setFirstName("First");
+        user.setLastName("Last");
+        user.setEmail(username + "@localhost");
+
+        UserCredentialModel password = new UserCredentialModel();
+        password.setType(UserCredentialModel.PASSWORD);
+        password.setValue("password");
+
+        user.updateCredential(password);
+
+        for (String r : roles) {
+            grantRole(user, r, realmRoles, appRoles);
+        }
+    }
+
+}
diff --git a/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/DeleteUsersJob.java b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/DeleteUsersJob.java
new file mode 100644
index 0000000..0f98cb4
--- /dev/null
+++ b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/DeleteUsersJob.java
@@ -0,0 +1,38 @@
+package org.keycloak.test.tools.jobs;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.services.managers.RealmManager;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class DeleteUsersJob extends UsersJob {
+
+    private Iterator<UserModel> users;
+
+    @Override
+    protected void before(KeycloakSession session) {
+        RealmModel realm = new RealmManager(session).getRealmByName(realmName);
+
+        // TODO: pagination
+        List<UserModel> users = (prefix==null) ? realm.getUsers() : realm.searchForUser(prefix);
+        users = users.subList(start, start + count);
+
+        this.users = users.iterator();
+    }
+
+    @Override
+    protected void runIteration(RealmModel realm, Map<String, ApplicationModel> apps, Set<RoleModel> realmRoles, Map<String, Set<RoleModel>> appRoles, int counter) {
+        String username = users.next().getUsername();
+        realm.removeUser(username);
+    }
+}
diff --git a/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UpdateUsersJob.java b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UpdateUsersJob.java
new file mode 100644
index 0000000..d0a1af9
--- /dev/null
+++ b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UpdateUsersJob.java
@@ -0,0 +1,54 @@
+package org.keycloak.test.tools.jobs;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.services.managers.RealmManager;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class UpdateUsersJob extends UsersJob {
+
+    private String[] roles;
+    private Iterator<UserModel> users;
+
+    public UpdateUsersJob(String[] roles) {
+        this.roles = roles;
+    }
+
+    @Override
+    protected void before(KeycloakSession session) {
+        RealmModel realm = new RealmManager(session).getRealmByName(realmName);
+
+        // TODO: pagination
+        List<UserModel> users = (prefix==null) ? realm.getUsers() : realm.searchForUser(prefix);
+        users = users.subList(start, start + count);
+
+        this.users = users.iterator();
+    }
+
+    @Override
+    protected void runIteration(RealmModel realm, Map<String, ApplicationModel> apps, Set<RoleModel> realmRoles, Map<String, Set<RoleModel>> appRoles, int counter) {
+        String username = users.next().getUsername();
+
+        // Remove all role mappings first
+        UserModel user = realm.getUser(username);
+        Set<RoleModel> currRoles = user.getRoleMappings();
+        for (RoleModel role : currRoles) {
+            user.deleteRoleMapping(role);
+        }
+
+        // Add new roles now
+        for (String r : roles) {
+            grantRole(user, r, realmRoles, appRoles);
+        }
+    }
+}
diff --git a/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UsersJob.java b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UsersJob.java
new file mode 100644
index 0000000..efc598a
--- /dev/null
+++ b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UsersJob.java
@@ -0,0 +1,126 @@
+package org.keycloak.test.tools.jobs;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+
+import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.test.tools.PerfTools;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public abstract class UsersJob implements Runnable {
+
+    protected PerfTools.JobRepresentation job;
+    protected KeycloakSessionFactory sessionFactory;
+    protected String realmName;
+    protected int start;
+    protected int count;
+    protected String prefix;
+    protected CountDownLatch latch;
+
+    public void init(PerfTools.JobRepresentation job, KeycloakSessionFactory sessionFactory, String realmName, int start, int count, String prefix, CountDownLatch latch) {
+        this.sessionFactory = sessionFactory;
+        this.realmName = realmName;
+        this.start = start;
+        this.count = count;
+        this.prefix = prefix;
+        this.job = job;
+        this.latch = latch;
+
+        KeycloakSession session = sessionFactory.create();
+        try {
+            session.getTransaction().begin();
+
+            before(session);
+
+            session.getTransaction().commit();
+        } catch (Throwable t) {
+            handleThrowable(t, session);
+        } finally {
+            session.close();
+        }
+    }
+
+    @Override
+    public void run() {
+        job.start();
+
+        KeycloakSession session = sessionFactory.create();
+        try {
+            session.getTransaction().begin();
+
+            RealmModel realm = new RealmManager(session).getRealmByName(realmName);
+            Map<String, ApplicationModel> apps = realm.getApplicationNameMap();
+
+            Set<RoleModel> realmRoles = realm.getRoles();
+            Map<String, Set<RoleModel>> appRoles = new HashMap<String, Set<RoleModel>>();
+            for (Map.Entry<String, ApplicationModel> appEntry : apps.entrySet()) {
+                appRoles.put(appEntry.getKey(), appEntry.getValue().getRoles());
+            }
+
+            for (int i = start; i < (start + count); i++) {
+                runIteration(realm, apps, realmRoles, appRoles, i);
+                job.increment();
+            }
+
+            session.getTransaction().commit();
+        } catch (Throwable t) {
+            handleThrowable(t, session);
+        } finally {
+            latch.countDown();
+            session.close();
+        }
+
+    }
+
+    protected abstract void before(KeycloakSession keycloakSession);
+
+    protected abstract void runIteration(RealmModel realm, Map<String, ApplicationModel> apps, Set<RoleModel> realmRoles, Map<String, Set<RoleModel>> appRoles, int counter);
+
+    protected RoleModel findRole(Set<RoleModel> roles, String roleName) {
+        for (RoleModel role : roles) {
+            if (role.getName().equals(roleName)) {
+                return role;
+            }
+        }
+
+        return null;
+    }
+
+    protected void grantRole(UserModel user, String roleName, Set<RoleModel> realmRoles, Map<String, Set<RoleModel>> appRoles) {
+        if (roleName.indexOf(':') == -1) {
+            // We expect "realmRoleName"
+            RoleModel realmRole = findRole(realmRoles, roleName);
+            user.grantRole(realmRole);
+        } else {
+            // We expect "appName:appRoleName"
+            String[] parts = roleName.split(":");
+            Set<RoleModel> currentAppRoles = appRoles.get(parts[0]);
+            if (currentAppRoles == null) {
+                throw new IllegalStateException("Application '" + parts[0] + "' not found");
+            }
+
+            RoleModel appRole = findRole(currentAppRoles, parts[1]);
+            user.grantRole(appRole);
+        }
+    }
+
+    private void handleThrowable(Throwable t, KeycloakSession session) {
+        StringWriter sw = new StringWriter();
+        t.printStackTrace(new PrintWriter(sw));
+        job.setError(sw.toString());
+        session.getTransaction().rollback();
+    }
+
+}
diff --git a/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UsersJobInitializer.java b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UsersJobInitializer.java
new file mode 100644
index 0000000..d999856
--- /dev/null
+++ b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UsersJobInitializer.java
@@ -0,0 +1,9 @@
+package org.keycloak.test.tools.jobs;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public interface UsersJobInitializer {
+
+    UsersJob instantiateJob();
+}
diff --git a/testsuite/tools/src/main/java/org/keycloak/test/tools/PerfTools.java b/testsuite/tools/src/main/java/org/keycloak/test/tools/PerfTools.java
index 32a1fdc..3090654 100644
--- a/testsuite/tools/src/main/java/org/keycloak/test/tools/PerfTools.java
+++ b/testsuite/tools/src/main/java/org/keycloak/test/tools/PerfTools.java
@@ -5,8 +5,11 @@ import org.keycloak.exportimport.ExportImportProvider;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
 import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.test.tools.jobs.CreateUsers;
+import org.keycloak.test.tools.jobs.CreateUsersJob;
+import org.keycloak.test.tools.jobs.DeleteUsersJob;
+import org.keycloak.test.tools.jobs.UpdateUsersJob;
+import org.keycloak.test.tools.jobs.UsersJob;
+import org.keycloak.test.tools.jobs.UsersJobInitializer;
 import org.keycloak.util.ProviderLoader;
 
 import javax.ws.rs.GET;
@@ -18,11 +21,11 @@ import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.Response;
 
-import java.util.HashMap;
+import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -41,7 +44,7 @@ public class PerfTools {
     @Context
     private KeycloakSession session;
 
-    private List<Job> jobs = new LinkedList<Job>();
+    private List<JobRepresentation> jobs = new LinkedList<JobRepresentation>();
 
     public PerfTools(KeycloakSessionFactory sessionFactory) {
         this.sessionFactory = sessionFactory;
@@ -50,16 +53,16 @@ public class PerfTools {
     @GET
     @Path("jobs")
     @Produces("application/json")
-    public List<Job> jobs() {
+    public List<JobRepresentation> jobs() {
         return jobs;
     }
 
     @GET
     @Path("delete-jobs")
     public void deleteJobs() {
-        Iterator<Job> itr = jobs.iterator();
+        Iterator<JobRepresentation> itr = jobs.iterator();
         while(itr.hasNext()) {
-            Job j = itr.next();
+            JobRepresentation j = itr.next();
             if (j.getError() != null || j.getCount() == j.getTotal()) {
                 itr.remove();
             }
@@ -68,38 +71,94 @@ public class PerfTools {
 
     @GET
     @Path("{realm}/create-users")
-    public void createUsers(@PathParam("realm") String realmName, @QueryParam("count") Integer count, @QueryParam("batch") Integer batch, @QueryParam("start") Integer start, @QueryParam("prefix") String prefix, @QueryParam("roles") String roles) throws InterruptedException {
-        if (count == null) {
-            count = 1;
-        }
-        if (batch == null) {
-            batch = 1000;
-        }
-        if (start == null) {
-            start = 0;
+    public void createUsers(@PathParam("realm") String realmName, @QueryParam("count") Integer count,
+                            @QueryParam("batch") Integer batch, @QueryParam("start") Integer start, @QueryParam("prefix") String prefix,
+                            @QueryParam("async") Boolean async, @QueryParam("roles") String roles) throws InterruptedException {
+        final String[] rolesArray = roles != null ? roles.split(",") : new String[0];
+
+        createAndRunJob(realmName, count, batch, start, prefix, async, "Create users", new UsersJobInitializer() {
+
+            @Override
+            public UsersJob instantiateJob() {
+                return new CreateUsersJob(rolesArray);
+            }
+
+        });
+    }
+
+    // Same as createUsers, but dynamically compute "start" (Next available user)
+    @GET
+    @Path("{realm}/create-available-users")
+    public void createAvailableUsers(@PathParam("realm") String realmName, @QueryParam("count") Integer count,
+                                     @QueryParam("batch") Integer batch, @QueryParam("prefix") String prefix,
+                                     @QueryParam("async") Boolean async, @QueryParam("roles") String roles) throws InterruptedException {
+        int start = getUsersCount(realmName, prefix);
+        createUsers(realmName, count, batch, start, prefix, async, roles);
+    }
+
+    @GET
+    @Path("{realm}/delete-users")
+    public void deleteUsers(@PathParam("realm") String realmName, @QueryParam("count") Integer count,
+                            @QueryParam("batch") Integer batch, @QueryParam("start") Integer start, @QueryParam("prefix") String prefix,
+                            @QueryParam("async") Boolean async) throws InterruptedException {
+        createAndRunJob(realmName, count, batch, start, prefix, async, "Delete users", new UsersJobInitializer() {
+
+            @Override
+            public UsersJob instantiateJob() {
+                return new DeleteUsersJob();
+            }
+
+        });
+    }
+
+    @GET
+    @Path("{realm}/delete-all-users")
+    public void deleteUsers(@PathParam("realm") String realmName, @QueryParam("prefix") String prefix, @QueryParam("async") Boolean async) throws InterruptedException {
+        int count = getUsersCount(realmName, prefix);
+        if (count == 0) {
+            return;
         }
-        if (prefix == null) {
-            prefix = String.valueOf(System.currentTimeMillis());
+
+        int batch = count / 10;
+        if (batch == 0) {
+            batch = 1;
         }
 
-        String[] rolesArray = roles != null ? roles.split(",") : new String[0];
+        deleteUsers(realmName, count, batch, 0, prefix, async);
+    }
 
-        Job job = new Job("Create users " + prefix + "-" + start + " to " + prefix + "-" + (start + count), count);
-        jobs.add(job);
+    @GET
+    @Path("{realm}/update-users")
+    public void updateUsers(@PathParam("realm") String realmName, @QueryParam("count") Integer count,
+                            @QueryParam("batch") Integer batch, @QueryParam("start") Integer start, @QueryParam("prefix") String prefix,
+                            @QueryParam("async") Boolean async, @QueryParam("roles") String roles) throws InterruptedException {
+        final String[] rolesArray = roles != null ? roles.split(",") : new String[0];
 
-        for (int s = start; s < (start + count); s += batch) {
-            int c = s + batch <= (start + count) ? batch : (start + count) - s;
-            executor.submit(new CreateUsers(job, sessionFactory, realmName, s, c, prefix, rolesArray));
-        }
+        createAndRunJob(realmName, count, batch, start, prefix, async, "Update users", new UsersJobInitializer() {
+
+            @Override
+            public UsersJob instantiateJob() {
+                return new UpdateUsersJob(rolesArray);
+            }
+
+        });
     }
 
     @GET
-    @Path("{realm}/delete-users")
-    public void deleteUsers(@PathParam("realm") String realmName) {
-        RealmModel realm = session.getRealmByName(realmName);
-        for (UserModel user : realm.getUsers()) {
-            realm.removeUser(user.getLoginName());
+    @Path("{realm}/update-all-users")
+    public void updateAllUsers(@PathParam("realm") String realmName, @QueryParam("prefix") String prefix, @QueryParam("async") Boolean async,
+                               @QueryParam("roles") String roles) throws InterruptedException {
+        int count = getUsersCount(realmName, prefix);
+        if (count == 0) {
+            return;
         }
+
+        int batch = count / 10;
+        if (batch == 0) {
+            batch = 1;
+        }
+
+        updateUsers(realmName, count, batch, 0, prefix, async, roles);
     }
 
 
@@ -110,14 +169,6 @@ public class PerfTools {
         return Response.ok(String.valueOf(usersCount)).build();
     }
 
-    // Same as createUsers, but dynamically compute "start" (Next available user)
-    @GET
-    @Path("{realm}/create-available-users")
-    public void createAvailableUsers(@PathParam("realm") String realmName, @QueryParam("count") Integer count, @QueryParam("batch") Integer batch, @QueryParam("prefix") String prefix, @QueryParam("roles") String roles) throws InterruptedException {
-        int start = getUsersCount(realmName, prefix);
-        createUsers(realmName, count, batch, start, prefix, roles);
-    }
-
     private int getUsersCount(String realmName, String prefix) {
         RealmModel realm = session.getRealmByName(realmName);
 
@@ -129,6 +180,50 @@ public class PerfTools {
         }
     }
 
+    private void createAndRunJob(String realmName, Integer count, Integer batch, Integer start, String prefix, Boolean async, String jobName, UsersJobInitializer initializer) throws InterruptedException {
+        if (count == null) {
+            count = 1;
+        }
+        if (batch == null) {
+            batch = 1000;
+        }
+        if (start == null) {
+            start = 0;
+        }
+        if (prefix == null) {
+            prefix = String.valueOf(System.currentTimeMillis());
+        }
+        if (async == null) {
+            async = true;
+        }
+
+        int executorsCount = count / batch;
+        if (count % batch > 0) {
+            executorsCount++;
+        }
+        CountDownLatch latch = new CountDownLatch(executorsCount);
+
+        JobRepresentation job = new JobRepresentation(jobName + " " + prefix + "-" + start + " to " + prefix + "-" + (start + count), count);
+        jobs.add(job);
+
+        List<UsersJob> usersJobs = new ArrayList<UsersJob>();
+        for (int s = start; s < (start + count); s += batch) {
+            int c = s + batch <= (start + count) ? batch : (start + count) - s;
+            UsersJob usersJob = initializer.instantiateJob();
+            usersJob.init(job, sessionFactory, realmName, s, c, prefix, latch);
+            usersJobs.add(usersJob);
+        }
+
+        // Run executors once all are initialized
+        for (UsersJob usersJob : usersJobs) {
+            executor.submit(usersJob);
+        }
+
+        if (!async) {
+            latch.await();
+        }
+    }
+
     @GET
     @Path("export")
     public void export(@QueryParam("dir") String dir) {
@@ -146,7 +241,7 @@ public class PerfTools {
         }
     }
 
-    public class Job {
+    public static class JobRepresentation {
         private final String description;
         private final int total;
         private AtomicInteger count = new AtomicInteger();
@@ -154,7 +249,7 @@ public class PerfTools {
         private AtomicLong started = new AtomicLong();
         private AtomicLong completed = new AtomicLong();
 
-        public Job(String description, int total) {
+        public JobRepresentation(String description, int total) {
             this.description = description;
             this.total = total;
         }