keycloak-aplcache

Merge pull request #3289 from patriot1burke/master refactor

10/5/2016 10:40:18 AM

Details

diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java
index c36f002..16987d4 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java
@@ -638,11 +638,6 @@ public class UserCacheSession implements UserCache {
     }
 
     @Override
-    public CredentialValidationOutput validCredentials(KeycloakSession session, RealmModel realm, UserCredentialModel... input) {
-        return getDelegate().validCredentials(session, realm, input);
-    }
-
-    @Override
     public void grantToAllUsers(RealmModel realm, RoleModel role) {
         realmInvalidations.add(realm.getId()); // easier to just invalidate whole realm
         getDelegate().grantToAllUsers(realm, role);
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 e03b736..6f85e38 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
@@ -708,12 +708,6 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
     }
 
     @Override
-    public CredentialValidationOutput validCredentials(KeycloakSession session, RealmModel realm, UserCredentialModel... input) {
-        // Not supported yet
-        return null;
-    }
-
-    @Override
     public void preRemove(RealmModel realm, ComponentModel component) {
 
     }
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 96a9d31..529aabe 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
@@ -518,12 +518,6 @@ public class MongoUserProvider implements UserProvider, UserCredentialStore {
     }
 
     @Override
-    public CredentialValidationOutput validCredentials(KeycloakSession session, RealmModel realm, UserCredentialModel... input) {
-        // Not supported yet
-        return null;
-    }
-
-    @Override
     public void addConsent(RealmModel realm, UserModel user, UserConsentModel consent) {
         String clientId = consent.getClient().getId();
         if (getConsentEntityByClientId(user, clientId) != null) {
diff --git a/server-spi/src/main/java/org/keycloak/models/CredentialValidationOutput.java b/server-spi/src/main/java/org/keycloak/models/CredentialValidationOutput.java
index e0faa22..83694bc 100644
--- a/server-spi/src/main/java/org/keycloak/models/CredentialValidationOutput.java
+++ b/server-spi/src/main/java/org/keycloak/models/CredentialValidationOutput.java
@@ -49,6 +49,11 @@ public class CredentialValidationOutput {
         return authStatus;
     }
 
+    /**
+     * State that is passed back by provider
+     *
+     * @return
+     */
     public Map<String, String> getState() {
         return state;
     }
diff --git a/server-spi/src/main/java/org/keycloak/models/UserCredentialManager.java b/server-spi/src/main/java/org/keycloak/models/UserCredentialManager.java
index 8dad996..f03ac8f 100644
--- a/server-spi/src/main/java/org/keycloak/models/UserCredentialManager.java
+++ b/server-spi/src/main/java/org/keycloak/models/UserCredentialManager.java
@@ -90,4 +90,17 @@ public interface UserCredentialManager extends UserCredentialStore {
      * @return
      */
     boolean isConfiguredLocally(RealmModel realm, UserModel user, String type);
+
+    /**
+     * Given a CredentialInput, authenticate the user.  This is used in the case where the credential must be processed
+     * to determine and find the user.  An example is Kerberos where the kerberos token might be validated and processed
+     * by a variety of different storage providers.
+     *
+     *
+     * @param session
+     * @param realm
+     * @param input
+     * @return
+     */
+    CredentialValidationOutput authenticate(KeycloakSession session, RealmModel realm, CredentialInput input);
 }
diff --git a/server-spi/src/main/java/org/keycloak/models/UserFederationManager.java b/server-spi/src/main/java/org/keycloak/models/UserFederationManager.java
index 771a03a..c722aa4 100755
--- a/server-spi/src/main/java/org/keycloak/models/UserFederationManager.java
+++ b/server-spi/src/main/java/org/keycloak/models/UserFederationManager.java
@@ -73,7 +73,7 @@ public class UserFederationManager implements UserProvider {
         return user;
     }
 
-    protected UserFederationProvider getFederationProvider(UserFederationProviderModel model) {
+    public UserFederationProvider getFederationProvider(UserFederationProviderModel model) {
         return KeycloakModelUtils.getFederationProviderInstance(session, model);
     }
 
@@ -485,40 +485,6 @@ public class UserFederationManager implements UserProvider {
     }
 
     @Override
-    public CredentialValidationOutput validCredentials(KeycloakSession session, RealmModel realm, UserCredentialModel... input) {
-        List<UserFederationProviderModel> fedProviderModels = realm.getUserFederationProviders();
-        List<UserFederationProvider> fedProviders = new ArrayList<UserFederationProvider>();
-        for (UserFederationProviderModel fedProviderModel : fedProviderModels) {
-            fedProviders.add(getFederationProvider(fedProviderModel));
-        }
-
-        CredentialValidationOutput result = null;
-        for (UserCredentialModel cred : input) {
-            UserFederationProvider providerSupportingCreds = null;
-
-            // Find first provider, which supports required credential type
-            for (UserFederationProvider fedProvider : fedProviders) {
-                if (fedProvider.getSupportedCredentialTypes().contains(cred.getType())) {
-                    providerSupportingCreds = fedProvider;
-                    break;
-                }
-            }
-
-            if (providerSupportingCreds == null) {
-                logger.warn("Don't have provider supporting credentials of type " + cred.getType());
-                return CredentialValidationOutput.failed();
-            }
-
-            logger.debug("Found provider [" + providerSupportingCreds + "] supporting credentials of type " + cred.getType());
-            CredentialValidationOutput currentResult = providerSupportingCreds.validCredentials(realm, cred);
-            result = (result == null) ? currentResult : result.merge(currentResult);
-        }
-
-        // For now, validCredentials(realm, input) is not supported for local userProviders
-        return (result != null) ? result : CredentialValidationOutput.failed();
-    }
-
-    @Override
     public void preRemove(RealmModel realm, ComponentModel component) {
         session.userStorage().preRemove(realm, component);
 
diff --git a/server-spi/src/main/java/org/keycloak/models/UserProvider.java b/server-spi/src/main/java/org/keycloak/models/UserProvider.java
index e1b64fa..3c796b5 100755
--- a/server-spi/src/main/java/org/keycloak/models/UserProvider.java
+++ b/server-spi/src/main/java/org/keycloak/models/UserProvider.java
@@ -75,10 +75,6 @@ public interface UserProvider extends Provider,
     void preRemove(RealmModel realm, ClientModel client);
     void preRemove(ProtocolMapperModel protocolMapper);
 
-
-    CredentialValidationOutput validCredentials(KeycloakSession session, RealmModel realm, UserCredentialModel... input);
-
-
     void close();
 
     void preRemove(RealmModel realm, ComponentModel component);
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/browser/SpnegoAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/browser/SpnegoAuthenticator.java
index 1d6e7ae..c88f492 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/browser/SpnegoAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/browser/SpnegoAuthenticator.java
@@ -86,7 +86,7 @@ public class SpnegoAuthenticator extends AbstractUsernameFormAuthenticator imple
         String spnegoToken = tokens[1];
         UserCredentialModel spnegoCredential = UserCredentialModel.kerberos(spnegoToken);
 
-        CredentialValidationOutput output = context.getSession().users().validCredentials(context.getSession(), context.getRealm(), spnegoCredential);
+        CredentialValidationOutput output = context.getSession().userCredentialManager().authenticate(context.getSession(), context.getRealm(), spnegoCredential);
 
         if (output.getAuthStatus() == CredentialValidationOutput.Status.AUTHENTICATED) {
             context.setUser(output.getAuthenticatedUser());
diff --git a/services/src/main/java/org/keycloak/credential/UserCredentialStoreManager.java b/services/src/main/java/org/keycloak/credential/UserCredentialStoreManager.java
index 065be1f..5801efd 100644
--- a/services/src/main/java/org/keycloak/credential/UserCredentialStoreManager.java
+++ b/services/src/main/java/org/keycloak/credential/UserCredentialStoreManager.java
@@ -17,18 +17,23 @@
 package org.keycloak.credential;
 
 import org.keycloak.common.util.reflections.Types;
+import org.keycloak.models.CredentialValidationOutput;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserCredentialManager;
+import org.keycloak.models.UserCredentialModel;
 import org.keycloak.models.UserFederationProvider;
+import org.keycloak.models.UserFederationProviderModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.cache.CachedUserModel;
 import org.keycloak.models.cache.OnUserCache;
+import org.keycloak.models.utils.CredentialValidation;
 import org.keycloak.provider.ProviderFactory;
 import org.keycloak.storage.StorageId;
 import org.keycloak.storage.UserStorageManager;
 import org.keycloak.storage.UserStorageProvider;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Iterator;
 import java.util.LinkedList;
@@ -247,6 +252,37 @@ public class UserCredentialStoreManager implements UserCredentialManager, OnUser
     }
 
     @Override
+    public CredentialValidationOutput authenticate(KeycloakSession session, RealmModel realm, CredentialInput input) {
+        List<UserFederationProviderModel> fedProviderModels = realm.getUserFederationProviders();
+        List<UserFederationProvider> fedProviders = new ArrayList<UserFederationProvider>();
+        for (UserFederationProviderModel fedProviderModel : fedProviderModels) {
+            UserFederationProvider provider = session.users().getFederationProvider(fedProviderModel);
+            if (input instanceof UserCredentialModel && provider != null && provider.supportsCredentialType(input.getType())) {
+                CredentialValidationOutput output = provider.validCredentials(realm, (UserCredentialModel)input);
+                if (output != null) return output;
+            }
+        }
+
+        List<CredentialAuthentication> list = UserStorageManager.getStorageProviders(session, realm, CredentialAuthentication.class);
+        for (CredentialAuthentication auth : list) {
+            if (auth.supportsCredentialAuthenticationFor(input.getType())) {
+                CredentialValidationOutput output = auth.authenticate(realm, input);
+                if (output != null) return output;
+            }
+        }
+
+        list = getCredentialProviders(realm, CredentialAuthentication.class);
+        for (CredentialAuthentication auth : list) {
+            if (auth.supportsCredentialAuthenticationFor(input.getType())) {
+                CredentialValidationOutput output = auth.authenticate(realm, input);
+                if (output != null) return output;
+            }
+        }
+
+        return null;
+    }
+
+    @Override
     public void onCache(RealmModel realm, CachedUserModel user, UserModel delegate) {
         List<OnUserCache> credentialProviders = getCredentialProviders(realm, OnUserCache.class);
         for (OnUserCache validator : credentialProviders) {
diff --git a/services/src/main/java/org/keycloak/storage/UserStorageManager.java b/services/src/main/java/org/keycloak/storage/UserStorageManager.java
index 90c8f72..6061323 100755
--- a/services/src/main/java/org/keycloak/storage/UserStorageManager.java
+++ b/services/src/main/java/org/keycloak/storage/UserStorageManager.java
@@ -37,7 +37,7 @@ import org.keycloak.models.UserProvider;
 import org.keycloak.models.cache.CachedUserModel;
 import org.keycloak.models.cache.OnUserCache;
 import org.keycloak.storage.federated.UserFederatedStorageProvider;
-import org.keycloak.storage.user.UserCredentialAuthenticationProvider;
+import org.keycloak.credential.CredentialAuthentication;
 import org.keycloak.storage.user.UserLookupProvider;
 import org.keycloak.storage.user.UserQueryProvider;
 import org.keycloak.storage.user.UserRegistrationProvider;
@@ -529,37 +529,6 @@ public class UserStorageManager implements UserProvider, OnUserCache {
     }
 
     @Override
-    public CredentialValidationOutput validCredentials(KeycloakSession session, RealmModel realm, UserCredentialModel... input) {
-        List<UserCredentialAuthenticationProvider> providers = getStorageProviders(session, realm, UserCredentialAuthenticationProvider.class);
-        if (providers.isEmpty()) return CredentialValidationOutput.failed();
-
-        CredentialValidationOutput result = null;
-        for (UserCredentialModel cred : input) {
-            UserCredentialAuthenticationProvider providerSupportingCreds = null;
-
-            // Find first provider, which supports required credential type
-            for (UserCredentialAuthenticationProvider provider : providers) {
-                if (provider.getSupportedCredentialAuthenticationTypes().contains(cred.getType())) {
-                    providerSupportingCreds = provider;
-                    break;
-                }
-            }
-
-            if (providerSupportingCreds == null) {
-                logger.warn("Don't have provider supporting credentials of type " + cred.getType());
-                return CredentialValidationOutput.failed();
-            }
-
-            logger.debug("Found provider [" + providerSupportingCreds + "] supporting credentials of type " + cred.getType());
-            CredentialValidationOutput currentResult = providerSupportingCreds.validCredential(session, realm, cred);
-            result = (result == null) ? currentResult : result.merge(currentResult);
-        }
-
-        // For now, validCredentials(realm, input) is not supported for local userProviders
-        return (result != null) ? result : CredentialValidationOutput.failed();
-    }
-
-    @Override
     public void preRemove(RealmModel realm, ComponentModel component) {
         if (!component.getProviderType().equals(UserStorageProvider.class.getName())) return;
         localStorage().preRemove(realm, component);
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ScriptAuthenticatorTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ScriptAuthenticatorTest.java
index 667c85f..61cc47c 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ScriptAuthenticatorTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ScriptAuthenticatorTest.java
@@ -22,20 +22,17 @@ import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
-import org.keycloak.authentication.AuthenticationFlow;
 import org.keycloak.authentication.authenticators.browser.ScriptBasedAuthenticatorFactory;
 import org.keycloak.authentication.authenticators.browser.UsernamePasswordFormFactory;
 import org.keycloak.events.Details;
 import org.keycloak.events.Errors;
 import org.keycloak.events.EventType;
 import org.keycloak.models.AuthenticationExecutionModel;
-import org.keycloak.representations.idm.AuthenticationExecutionExportRepresentation;
 import org.keycloak.representations.idm.AuthenticationExecutionRepresentation;
 import org.keycloak.representations.idm.AuthenticationFlowRepresentation;
 import org.keycloak.representations.idm.AuthenticatorConfigRepresentation;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.representations.idm.UserRepresentation;
-import org.keycloak.storage.user.UserCredentialAuthenticationProvider;
 import org.keycloak.testsuite.AssertEvents;
 import org.keycloak.testsuite.pages.LoginPage;
 import org.keycloak.testsuite.util.ExecutionBuilder;
@@ -45,8 +42,6 @@ import org.keycloak.testsuite.util.UserBuilder;
 
 import javax.ws.rs.core.Response;
 import java.io.IOException;
-import java.util.Arrays;
-import java.util.Collections;
 
 /**
  * Tests for {@link org.keycloak.authentication.authenticators.browser.ScriptBasedAuthenticator}