From f342a8c7a3954ad614c4dab09e1757666825e72d Mon Sep 17 00:00:00 2001 From: Bill Burke Date: Wed, 16 Jul 2014 12:05:15 -0400 Subject: [PATCH] move credential validation to UserProvider --- .../AbstractModelAuthenticationProvider.java | 2 +- .../keycloak/models/CredentialValidation.java | 53 ------- .../java/org/keycloak/models/RealmModel.java | 4 - .../keycloak/models/UserCredentialModel.java | 7 + .../org/keycloak/models/UserProvider.java | 3 +- .../models/utils/CredentialValidation.java | 130 ++++++++++++++++++ .../cache/DefaultCacheUserProvider.java | 11 ++ .../models/cache/NoCacheUserProvider.java | 15 +- .../keycloak/models/cache/RealmAdapter.java | 18 +-- .../keycloak/models/jpa/JpaUserProvider.java | 11 ++ .../org/keycloak/models/jpa/RealmAdapter.java | 18 +-- .../keycloak/adapters/MongoUserProvider.java | 12 ++ .../mongo/keycloak/adapters/RealmAdapter.java | 18 +-- .../org/keycloak/model/test/AdapterTest.java | 8 +- .../model/test/AuthProvidersLDAPTest.java | 2 +- .../model/test/MultipleRealmsTest.java | 24 ++-- .../managers/AuthenticationManager.java | 3 +- .../performance/ReadUsersWorker.java | 3 +- 18 files changed, 211 insertions(+), 131 deletions(-) delete mode 100755 model/api/src/main/java/org/keycloak/models/CredentialValidation.java create mode 100755 model/api/src/main/java/org/keycloak/models/utils/CredentialValidation.java 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 1ac023f386..63c0ec5536 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 @@ -52,7 +52,7 @@ public abstract class AbstractModelAuthenticationProvider implements Authenticat RealmModel realm = getRealm(currentRealm, config); UserModel user = KeycloakModelUtils.findUserByNameOrEmail(keycloakSession, realm, username); - boolean result = realm.validatePassword(user, password); + boolean result = keycloakSession.users().validCredentials(realm, user, UserCredentialModel.password(password)); return result ? AuthProviderStatus.SUCCESS : AuthProviderStatus.INVALID_CREDENTIALS; } diff --git a/model/api/src/main/java/org/keycloak/models/CredentialValidation.java b/model/api/src/main/java/org/keycloak/models/CredentialValidation.java deleted file mode 100755 index 9f8dea74d1..0000000000 --- a/model/api/src/main/java/org/keycloak/models/CredentialValidation.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.keycloak.models; - -import org.keycloak.models.utils.Pbkdf2PasswordEncoder; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class CredentialValidation { - - private static int hashIterations(RealmModel realm) { - PasswordPolicy policy = realm.getPasswordPolicy(); - if (policy != null) { - return policy.getHashIterations(); - } - return -1; - - } - - /** - * Will update password if hash iteration policy has changed - * - * @param realm - * @param user - * @param password - * @return - */ - public static boolean validatePassword(RealmModel realm, UserModel user, String password) { - boolean validated = false; - UserCredentialValueModel passwordCred = null; - for (UserCredentialValueModel cred : user.getCredentialsDirectly()) { - if (cred.getType().equals(UserCredentialModel.PASSWORD)) { - validated = new Pbkdf2PasswordEncoder(cred.getSalt()).verify(password, cred.getValue(), cred.getHashIterations()); - passwordCred = cred; - } - } - if (validated) { - int iterations = hashIterations(realm); - if (iterations > -1 && iterations != passwordCred.getHashIterations()) { - UserCredentialValueModel newCred = new UserCredentialValueModel(); - newCred.setType(passwordCred.getType()); - newCred.setDevice(passwordCred.getDevice()); - newCred.setSalt(passwordCred.getSalt()); - newCred.setHashIterations(iterations); - newCred.setValue(new Pbkdf2PasswordEncoder(newCred.getSalt()).encode(password, iterations)); - user.updateCredentialDirectly(newCred); - } - - } - return validated; - - } -} 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 d515c988b6..d437c9bc78 100755 --- a/model/api/src/main/java/org/keycloak/models/RealmModel.java +++ b/model/api/src/main/java/org/keycloak/models/RealmModel.java @@ -106,10 +106,6 @@ public interface RealmModel extends RoleContainerModel { void setPasswordPolicy(PasswordPolicy policy); - boolean validatePassword(UserModel user, String password); - - boolean validateTOTP(UserModel user, String password, String token); - RoleModel getRoleById(String id); List getDefaultRoles(); diff --git a/model/api/src/main/java/org/keycloak/models/UserCredentialModel.java b/model/api/src/main/java/org/keycloak/models/UserCredentialModel.java index d096b97320..4c5275b923 100755 --- a/model/api/src/main/java/org/keycloak/models/UserCredentialModel.java +++ b/model/api/src/main/java/org/keycloak/models/UserCredentialModel.java @@ -35,6 +35,13 @@ public class UserCredentialModel { return model; } + public static UserCredentialModel totp(String key) { + UserCredentialModel model = new UserCredentialModel(); + model.setType(TOTP); + model.setValue(key); + return model; + } + public static UserCredentialModel generateSecret() { UserCredentialModel model = new UserCredentialModel(); model.setType(SECRET); diff --git a/model/api/src/main/java/org/keycloak/models/UserProvider.java b/model/api/src/main/java/org/keycloak/models/UserProvider.java index b5a9a26f7f..4898642379 100755 --- a/model/api/src/main/java/org/keycloak/models/UserProvider.java +++ b/model/api/src/main/java/org/keycloak/models/UserProvider.java @@ -33,6 +33,7 @@ public interface UserProvider extends Provider { void preRemove(RealmModel realm); void preRemove(RoleModel role); - + boolean validCredentials(RealmModel realm, UserModel user, List input); + boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input); void close(); } diff --git a/model/api/src/main/java/org/keycloak/models/utils/CredentialValidation.java b/model/api/src/main/java/org/keycloak/models/utils/CredentialValidation.java new file mode 100755 index 0000000000..901571ff3f --- /dev/null +++ b/model/api/src/main/java/org/keycloak/models/utils/CredentialValidation.java @@ -0,0 +1,130 @@ +package org.keycloak.models.utils; + +import org.keycloak.models.PasswordPolicy; +import org.keycloak.models.RealmModel; +import org.keycloak.models.UserCredentialModel; +import org.keycloak.models.UserCredentialValueModel; +import org.keycloak.models.UserModel; + +import java.util.List; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class CredentialValidation { + + private static int hashIterations(RealmModel realm) { + PasswordPolicy policy = realm.getPasswordPolicy(); + if (policy != null) { + return policy.getHashIterations(); + } + return -1; + + } + + /** + * Will update password if hash iteration policy has changed + * + * @param realm + * @param user + * @param password + * @return + */ + public static boolean validPassword(RealmModel realm, UserModel user, String password) { + boolean validated = false; + UserCredentialValueModel passwordCred = null; + for (UserCredentialValueModel cred : user.getCredentialsDirectly()) { + if (cred.getType().equals(UserCredentialModel.PASSWORD)) { + validated = new Pbkdf2PasswordEncoder(cred.getSalt()).verify(password, cred.getValue(), cred.getHashIterations()); + passwordCred = cred; + } + } + if (validated) { + int iterations = hashIterations(realm); + if (iterations > -1 && iterations != passwordCred.getHashIterations()) { + UserCredentialValueModel newCred = new UserCredentialValueModel(); + newCred.setType(passwordCred.getType()); + newCred.setDevice(passwordCred.getDevice()); + newCred.setSalt(passwordCred.getSalt()); + newCred.setHashIterations(iterations); + newCred.setValue(new Pbkdf2PasswordEncoder(newCred.getSalt()).encode(password, iterations)); + user.updateCredentialDirectly(newCred); + } + + } + return validated; + + } + + public static boolean validTOTP(RealmModel realm, UserModel user, String otp) { + UserCredentialValueModel passwordCred = null; + for (UserCredentialValueModel cred : user.getCredentialsDirectly()) { + if (cred.getType().equals(UserCredentialModel.TOTP)) { + if (new TimeBasedOTP().validate(otp, cred.getValue().getBytes())) { + return true; + } + } + } + return false; + + } + public static boolean validSecret(RealmModel realm, UserModel user, String secret) { + for (UserCredentialValueModel cred : user.getCredentialsDirectly()) { + if (cred.getType().equals(UserCredentialModel.SECRET)) { + if (cred.getValue().equals(secret)) return true; + } + } + return false; + + } + + /** + * Must validate all credentials. FYI, password hashes may be rehashed and updated based on realm hash password policies. + * + * @param realm + * @param user + * @param credentials + * @return + */ + public static boolean validCredentials(RealmModel realm, UserModel user, List credentials) { + for (UserCredentialModel credential : credentials) { + if (!validCredential(realm, user, credential)) return false; + } + return true; + } + + /** + * Must validate all credentials. FYI, password hashes may be rehashed and updated based on realm hash password policies. + * + * @param realm + * @param user + * @param credentials + * @return + */ + public static boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... credentials) { + for (UserCredentialModel credential : credentials) { + if (!validCredential(realm, user, credential)) return false; + } + return true; + } + + private static boolean validCredential(RealmModel realm, UserModel user, UserCredentialModel credential) { + if (credential.getType().equals(UserCredentialModel.PASSWORD)) { + if (!validPassword(realm, user, credential.getValue())) { + return false; + } + } else if (credential.getType().equals(UserCredentialModel.TOTP)) { + if (!validTOTP(realm, user, credential.getValue())) { + return false; + } + } else if (credential.getType().equals(UserCredentialModel.SECRET)) { + if (!validSecret(realm, user, credential.getValue())) { + return false; + } + } else { + return false; + } + return true; + } +} diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheUserProvider.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheUserProvider.java index f44bbd561f..dbb465c761 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheUserProvider.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheUserProvider.java @@ -5,6 +5,7 @@ import org.keycloak.models.KeycloakTransaction; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; import org.keycloak.models.SocialLinkModel; +import org.keycloak.models.UserCredentialModel; import org.keycloak.models.UserModel; import org.keycloak.models.UserProvider; import org.keycloak.models.cache.entities.CachedUser; @@ -231,6 +232,16 @@ public class DefaultCacheUserProvider implements CacheUserProvider { return getDelegate().removeSocialLink(realm, user, socialProvider); } + @Override + public boolean validCredentials(RealmModel realm, UserModel user, List input) { + return getDelegate().validCredentials(realm, user, input); + } + + @Override + public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) { + return getDelegate().validCredentials(realm, user, input); + } + @Override public void preRemove(RealmModel realm) { realmInvalidations.add(realm.getId()); diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheUserProvider.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheUserProvider.java index 36f5669325..ce2858d432 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheUserProvider.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheUserProvider.java @@ -1,16 +1,13 @@ package org.keycloak.models.cache; import org.keycloak.models.KeycloakSession; -import org.keycloak.models.KeycloakTransaction; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; import org.keycloak.models.SocialLinkModel; +import org.keycloak.models.UserCredentialModel; import org.keycloak.models.UserModel; import org.keycloak.models.UserProvider; -import org.keycloak.models.cache.entities.CachedUser; -import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -114,6 +111,16 @@ public class NoCacheUserProvider implements CacheUserProvider { return getDelegate().removeSocialLink(realm, user, socialProvider); } + @Override + public boolean validCredentials(RealmModel realm, UserModel user, List input) { + return getDelegate().validCredentials(realm, user, input); + } + + @Override + public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) { + return getDelegate().validCredentials(realm, user, input); + } + @Override public void preRemove(RealmModel realm) { getDelegate().preRemove(realm); 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 94121a027b..acf9fb6651 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 @@ -3,7 +3,7 @@ package org.keycloak.models.cache; import org.keycloak.models.ApplicationModel; import org.keycloak.models.AuthenticationProviderModel; import org.keycloak.models.ClientModel; -import org.keycloak.models.CredentialValidation; +import org.keycloak.models.utils.CredentialValidation; import org.keycloak.models.OAuthClientModel; import org.keycloak.models.PasswordPolicy; import org.keycloak.models.RealmModel; @@ -375,22 +375,6 @@ public class RealmAdapter implements RealmModel { updated.setPasswordPolicy(policy); } - @Override - public boolean validatePassword(UserModel user, String password) { - return CredentialValidation.validatePassword(this, user, password); - } - - @Override - public boolean validateTOTP(UserModel user, String password, String token) { - if (!validatePassword(user, password)) return false; - for (UserCredentialValueModel cred : user.getCredentialsDirectly()) { - if (cred.getType().equals(UserCredentialModel.TOTP)) { - return new TimeBasedOTP().validate(token, cred.getValue().getBytes()); - } - } - return false; - } - @Override public RoleModel getRoleById(String id) { if (updated != null) return updated.getRoleById(id); diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java index 01e32ecf72..ccdec22045 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java @@ -5,6 +5,7 @@ import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; import org.keycloak.models.SocialLinkModel; +import org.keycloak.models.UserCredentialModel; import org.keycloak.models.UserModel; import org.keycloak.models.UserProvider; import org.keycloak.models.jpa.entities.RealmEntity; @@ -12,6 +13,7 @@ import org.keycloak.models.jpa.entities.RoleEntity; import org.keycloak.models.jpa.entities.SocialLinkEntity; import org.keycloak.models.jpa.entities.UserEntity; import org.keycloak.models.jpa.entities.UserRoleMappingEntity; +import org.keycloak.models.utils.CredentialValidation; import org.keycloak.models.utils.KeycloakModelUtils; import javax.persistence.EntityManager; @@ -274,4 +276,13 @@ public class JpaUserProvider implements UserProvider { return (entity != null) ? new SocialLinkModel(entity.getSocialProvider(), entity.getSocialUserId(), entity.getSocialUsername()) : null; } + @Override + public boolean validCredentials(RealmModel realm, UserModel user, List input) { + return CredentialValidation.validCredentials(realm, user, input); + } + + @Override + public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) { + return CredentialValidation.validCredentials(realm, user, input); + } } 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 6157ee9f6a..06a302db4d 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 @@ -3,7 +3,7 @@ package org.keycloak.models.jpa; import org.keycloak.models.ApplicationModel; import org.keycloak.models.AuthenticationProviderModel; import org.keycloak.models.ClientModel; -import org.keycloak.models.CredentialValidation; +import org.keycloak.models.utils.CredentialValidation; import org.keycloak.models.KeycloakSession; import org.keycloak.models.OAuthClientModel; import org.keycloak.models.PasswordPolicy; @@ -795,22 +795,6 @@ public class RealmAdapter implements RealmModel { return role.getContainer().removeRole(role); } - @Override - public boolean validatePassword(UserModel user, String password) { - return CredentialValidation.validatePassword(this, user, password); - } - - @Override - public boolean validateTOTP(UserModel user, String password, String token) { - if (!validatePassword(user, password)) return false; - for (UserCredentialValueModel cred : user.getCredentialsDirectly()) { - if (cred.getType().equals(UserCredentialModel.TOTP)) { - return new TimeBasedOTP().validate(token, cred.getValue().getBytes()); - } - } - return false; - } - @Override public PasswordPolicy getPasswordPolicy() { if (passwordPolicy == null) { diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java index f14f645a11..f9411e1550 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java @@ -9,10 +9,12 @@ import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; import org.keycloak.models.SocialLinkModel; +import org.keycloak.models.UserCredentialModel; import org.keycloak.models.UserModel; import org.keycloak.models.UserProvider; import org.keycloak.models.entities.SocialLinkEntity; import org.keycloak.models.mongo.keycloak.entities.MongoUserEntity; +import org.keycloak.models.utils.CredentialValidation; import java.util.ArrayList; import java.util.Collections; @@ -311,4 +313,14 @@ public class MongoUserProvider implements UserProvider { public void preRemove(RoleModel role) { // todo not sure what to do for this } + + @Override + public boolean validCredentials(RealmModel realm, UserModel user, List input) { + return CredentialValidation.validCredentials(realm, user, input); + } + + @Override + public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) { + return CredentialValidation.validCredentials(realm, user, input); + } } 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 410bc9fa8c..00e690a076 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 @@ -7,7 +7,7 @@ import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext; import org.keycloak.models.ApplicationModel; import org.keycloak.models.AuthenticationProviderModel; import org.keycloak.models.ClientModel; -import org.keycloak.models.CredentialValidation; +import org.keycloak.models.utils.CredentialValidation; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmProvider; import org.keycloak.models.OAuthClientModel; @@ -723,22 +723,6 @@ public class RealmAdapter extends AbstractMongoAdapter impleme return result; } - @Override - public boolean validatePassword(UserModel user, String password) { - return CredentialValidation.validatePassword(this, user, password); - } - - @Override - public boolean validateTOTP(UserModel user, String password, String token) { - if (!validatePassword(user, password)) return false; - for (UserCredentialValueModel cred : user.getCredentialsDirectly()) { - if (cred.getType().equals(UserCredentialModel.TOTP)) { - return new TimeBasedOTP().validate(token, cred.getValue().getBytes()); - } - } - return false; - } - protected void updateRealm() { super.updateMongoEntity(); } 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 edb4e4020a..ab40eb88d1 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 @@ -15,6 +15,7 @@ import org.keycloak.models.SocialLinkModel; import org.keycloak.models.UserCredentialModel; import org.keycloak.models.UserCredentialValueModel; import org.keycloak.models.UserModel; +import org.keycloak.models.UserProvider; import org.keycloak.models.utils.RepresentationToModel; import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.services.managers.RealmManager; @@ -129,16 +130,17 @@ public class AdapterTest extends AbstractModelTest { @Test public void testCredentialValidation() throws Exception { test1CreateRealm(); - UserModel user = realmManager.getSession().users().addUser(realmModel, "bburke"); + UserProvider userProvider = realmManager.getSession().users(); + UserModel user = userProvider.addUser(realmModel, "bburke"); UserCredentialModel cred = new UserCredentialModel(); cred.setType(CredentialRepresentation.PASSWORD); cred.setValue("geheim"); user.updateCredential(cred); - Assert.assertTrue(realmModel.validatePassword(user, "geheim")); + Assert.assertTrue(userProvider.validCredentials(realmModel, user, UserCredentialModel.password("geheim"))); List creds = user.getCredentialsDirectly(); Assert.assertEquals(creds.get(0).getHashIterations(), 1); realmModel.setPasswordPolicy( new PasswordPolicy("hashIterations(200)")); - Assert.assertTrue(realmModel.validatePassword(user, "geheim")); + Assert.assertTrue(userProvider.validCredentials(realmModel, user, UserCredentialModel.password("geheim"))); creds = user.getCredentialsDirectly(); Assert.assertEquals(creds.get(0).getHashIterations(), 200); realmModel.setPasswordPolicy( new PasswordPolicy("hashIterations(1)")); 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 90c074c11c..0ebecd61ca 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 @@ -158,7 +158,7 @@ public class AuthProvidersLDAPTest extends AbstractModelTest { Assert.assertEquals(AuthenticationManager.AuthenticationStatus.SUCCESS, am.authenticateForm(session, null, realm, formData)); // Password updated just in LDAP, so validating directly in realm should fail - Assert.assertFalse(realm.validatePassword(john, "password-updated")); + Assert.assertFalse(session.users().validCredentials(realm, john, UserCredentialModel.password("password-updated"))); // Switch to not allow updating passwords in ldap AuthProvidersExternalModelTest.setPasswordUpdateForProvider(false, AuthProviderConstants.PROVIDER_NAME_PICKETLINK, realm); 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 3aa4d4bfab..73cc6ad121 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 @@ -9,6 +9,7 @@ import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; import org.keycloak.models.UserCredentialModel; import org.keycloak.models.UserModel; +import org.keycloak.models.UserProvider; /** * @author Marek Posolda @@ -31,8 +32,9 @@ public class MultipleRealmsTest extends AbstractModelTest { @Test public void testUsers() { - UserModel r1user1 = realmManager.getSession().users().getUserByUsername("user1", realm1); - UserModel r2user1 = realmManager.getSession().users().getUserByUsername("user1", realm2); + UserProvider userProvider = realmManager.getSession().users(); + UserModel r1user1 = userProvider.getUserByUsername("user1", realm1); + UserModel r2user1 = userProvider.getUserByUsername("user1", realm2); Assert.assertEquals(r1user1.getUsername(), r2user1.getUsername()); Assert.assertNotEquals(r1user1.getId(), r2user1.getId()); @@ -40,22 +42,22 @@ public class MultipleRealmsTest extends AbstractModelTest { r1user1.updateCredential(UserCredentialModel.password("pass1")); r2user1.updateCredential(UserCredentialModel.password("pass2")); - Assert.assertTrue(realm1.validatePassword(r1user1, "pass1")); - Assert.assertFalse(realm1.validatePassword(r1user1, "pass2")); - Assert.assertFalse(realm2.validatePassword(r2user1, "pass1")); - Assert.assertTrue(realm2.validatePassword(r2user1, "pass2")); + Assert.assertTrue(userProvider.validCredentials(realm1, r1user1, UserCredentialModel.password("pass1"))); + Assert.assertFalse(userProvider.validCredentials(realm1, r1user1, UserCredentialModel.password("pass2"))); + Assert.assertFalse(userProvider.validCredentials(realm2, r2user1, UserCredentialModel.password("pass1"))); + Assert.assertTrue(userProvider.validCredentials(realm2, r2user1, UserCredentialModel.password("pass2"))); // Test searching - Assert.assertEquals(2, realmManager.getSession().users().searchForUser("user", realm1).size()); + Assert.assertEquals(2, userProvider.searchForUser("user", realm1).size()); commit(); realm1 = model.getRealm("id1"); realm2 = model.getRealm("id2"); - realmManager.getSession().users().removeUser(realm1, "user1"); - realmManager.getSession().users().removeUser(realm1, "user2"); - Assert.assertEquals(0, realmManager.getSession().users().searchForUser("user", realm1).size()); - Assert.assertEquals(2, realmManager.getSession().users().searchForUser("user", realm2).size()); + userProvider.removeUser(realm1, "user1"); + userProvider.removeUser(realm1, "user2"); + Assert.assertEquals(0, userProvider.searchForUser("user", realm1).size()); + Assert.assertEquals(2, userProvider.searchForUser("user", realm2).size()); } @Test 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 8ce0a51fc9..b2e3cc2515 100755 --- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java +++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java @@ -11,6 +11,7 @@ import org.keycloak.models.AuthenticationLinkModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.RequiredCredentialModel; +import org.keycloak.models.UserCredentialModel; import org.keycloak.models.UserModel; import org.keycloak.models.UserSessionModel; import org.keycloak.models.utils.KeycloakModelUtils; @@ -296,7 +297,7 @@ public class AuthenticationManager { } logger.debug("validating TOTP"); - if (!realm.validateTOTP(user, password, token)) { + if (!session.users().validCredentials(realm, user, UserCredentialModel.totp(token))) { return AuthenticationStatus.INVALID_CREDENTIALS; } } else { diff --git a/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/ReadUsersWorker.java b/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/ReadUsersWorker.java index a858767c60..d9c36d5f1d 100755 --- a/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/ReadUsersWorker.java +++ b/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/ReadUsersWorker.java @@ -6,6 +6,7 @@ import org.apache.log.Logger; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.SocialLinkModel; +import org.keycloak.models.UserCredentialModel; import org.keycloak.models.UserModel; import java.util.concurrent.atomic.AtomicInteger; @@ -101,7 +102,7 @@ public class ReadUsersWorker implements Worker { // Validate password (shoould be same as username) if (readPassword) { - realm.validatePassword(user, username); + session.users().validCredentials(realm, user, UserCredentialModel.password(username)); } // Read socialLinks of user