keycloak-aplcache

refactor flow first phase

6/18/2015 5:48:28 PM

Details

diff --git a/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java b/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
index fcc3a76..bbafc76 100755
--- a/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
+++ b/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
@@ -17,6 +17,7 @@ import org.keycloak.models.UserModel;
 import org.keycloak.models.UserSessionModel;
 import org.keycloak.protocol.oidc.TokenManager;
 import org.keycloak.services.ErrorPage;
+import org.keycloak.services.managers.Auth;
 import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.managers.BruteForceProtector;
 import org.keycloak.services.managers.ClientSessionCode;
@@ -25,6 +26,7 @@ import org.keycloak.services.messages.Messages;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 
 /**
@@ -414,6 +416,16 @@ public class AuthenticationProcessor {
 
     }
 
+    public FlowExecution createFlowExecution(String flowId) {
+        AuthenticationFlowModel flow = realm.getAuthenticationFlowById(flowId);
+        if (flow == null) {
+            logger.error("Unknown flow to execute with");
+            throw new AuthException(Error.INTERNAL_ERROR);
+        }
+        FlowExecution flowExecution = new FlowExecution();
+        flowExecution.executions = realm.getAuthenticationExecutions(flow.getId()).iterator();
+        return flowExecution;
+    }
 
     public Response authenticate() throws AuthException {
         checkClientSession();
@@ -428,7 +440,8 @@ public class AuthenticationProcessor {
         }
         UserModel authUser = clientSession.getAuthenticatedUser();
         validateUser(authUser);
-        Response challenge = processFlow(flowId);
+        FlowExecution flowExecution = createFlowExecution(this.flowId);
+        Response challenge = flowExecution.processFlow();
         if (challenge != null) return challenge;
         if (clientSession.getAuthenticatedUser() == null) {
             throw new AuthException(Error.UNKNOWN_USER);
@@ -458,7 +471,8 @@ public class AuthenticationProcessor {
         }
         UserModel authUser = clientSession.getAuthenticatedUser();
         validateUser(authUser);
-        Response challenge = processFlow(flowId);
+        FlowExecution flowExecution = createFlowExecution(this.flowId);
+        Response challenge = flowExecution.processFlow();
         if (challenge != null) return challenge;
 
         String username = clientSession.getAuthenticatedUser().getUsername();
@@ -482,155 +496,194 @@ public class AuthenticationProcessor {
 
     }
 
-    public Response processFlow(String flowId) {
-        AuthenticationFlowModel flow = realm.getAuthenticationFlowById(flowId);
-        if (flow == null) {
-            logger.error("Unknown flow to execute with");
-            throw new AuthException(Error.INTERNAL_ERROR);
+    public void validateUser(UserModel authenticatedUser) {
+        if (authenticatedUser != null) {
+            if (!authenticatedUser.isEnabled()) throw new AuthException(Error.USER_DISABLED);
+        }
+        if (realm.isBruteForceProtected()) {
+            if (protector.isTemporarilyDisabled(session, realm, authenticatedUser.getUsername())) {
+                throw new AuthException(Error.USER_TEMPORARILY_DISABLED);
+            }
+        }
+    }
+
+    protected Response authenticationComplete() {
+        String username = clientSession.getAuthenticatedUser().getUsername();
+        String rememberMe = clientSession.getNote(Details.REMEMBER_ME);
+        boolean remember = rememberMe != null && rememberMe.equalsIgnoreCase("true");
+        if (userSession == null) { // if no authenticator attached a usersession
+            userSession = session.sessions().createUserSession(realm, clientSession.getAuthenticatedUser(), username, connection.getRemoteAddr(), clientSession.getAuthMethod(), remember, null, null);
+            userSession.setState(UserSessionModel.State.LOGGING_IN);
+        }
+        if (remember) {
+            event.detail(Details.REMEMBER_ME, "true");
         }
-        List<AuthenticationExecutionModel> executions = realm.getAuthenticationExecutions(flowId);
-        if (executions == null) return null;
+        TokenManager.attachClientSession(userSession, clientSession);
+        event.user(userSession.getUser())
+             .detail(Details.USERNAME, username)
+             .session(userSession);
+
+        return AuthenticationManager.nextActionAfterAuthentication(session, userSession, clientSession, connection, request, uriInfo, event);
+
+    }
+
+     class FlowExecution {
         Response alternativeChallenge = null;
         AuthenticationExecutionModel challengedAlternativeExecution = null;
         boolean alternativeSuccessful = false;
-        for (AuthenticationExecutionModel model : executions) {
-            if (isProcessed(model)) {
-                logger.debug("execution is processed");
-                if (!alternativeSuccessful && model.isAlternative() && isSuccessful(model)) alternativeSuccessful = true;
-                continue;
-            }
-            Result context = null;
-            if (model.isAlternative() && alternativeSuccessful) {
-                clientSession.setAuthenticatorStatus(model.getId(), UserSessionModel.AuthenticatorStatus.SKIPPED);
-                continue;
+        Iterator<AuthenticationExecutionModel> executions;
+
+        public Response action(String actionExecution, Result actionResult) {
+            while (executions.hasNext()) {
+                AuthenticationExecutionModel model = executions.next();
+                if (isProcessed(model)) {
+                    logger.debug("execution is processed");
+                    if (!alternativeSuccessful && model.isAlternative() && isSuccessful(model)) alternativeSuccessful = true;
+                    continue;
+                }
+                if (!model.getId().equals(actionExecution)) {
+                    if (model.isAutheticatorFlow()) {
+                        FlowExecution flowExecution = createFlowExecution(model.getAuthenticator());
+                        return flowExecution.action(actionExecution, actionResult);
+                    } else {
+                        throw new AuthException("action is not current execution", Error.INTERNAL_ERROR);
+                    }
+                } else { // we found the action
+                    Response response = processResult(actionResult);
+                    if (response == null) return processFlow();
+                    else return response;
+                }
             }
-            if (model.isAutheticatorFlow()) {
-                Response flowResponse = processFlow(model.getAuthenticator());
-                if (flowResponse == null) {
-                    clientSession.setAuthenticatorStatus(model.getId(), UserSessionModel.AuthenticatorStatus.SUCCESS);
-                    if (model.isAlternative()) alternativeSuccessful = true;
+            throw new AuthException("action is not in current execution", Error.INTERNAL_ERROR);
+        }
+
+        public Response processFlow() {
+            while (executions.hasNext()) {
+                AuthenticationExecutionModel model = executions.next();
+                if (isProcessed(model)) {
+                    logger.debug("execution is processed");
+                    if (!alternativeSuccessful && model.isAlternative() && isSuccessful(model)) alternativeSuccessful = true;
+                    continue;
+                }
+                if (model.isAlternative() && alternativeSuccessful) {
+                    clientSession.setAuthenticatorStatus(model.getId(), UserSessionModel.AuthenticatorStatus.SKIPPED);
                     continue;
-                } else {
-                    return flowResponse;
                 }
+                if (model.isAutheticatorFlow()) {
+                    FlowExecution flowExecution = createFlowExecution(model.getAuthenticator());
+                    Response flowResponse = flowExecution.processFlow();
+                    if (flowResponse == null) {
+                        clientSession.setAuthenticatorStatus(model.getId(), UserSessionModel.AuthenticatorStatus.SUCCESS);
+                        if (model.isAlternative()) alternativeSuccessful = true;
+                        continue;
+                    } else {
+                        return flowResponse;
+                    }
 
-            }
+                }
 
-            AuthenticatorModel authenticatorModel = realm.getAuthenticatorById(model.getAuthenticator());
-            AuthenticatorFactory factory = (AuthenticatorFactory)session.getKeycloakSessionFactory().getProviderFactory(Authenticator.class, authenticatorModel.getProviderId());
-            Authenticator authenticator = factory.create(authenticatorModel);
-            logger.debugv("authenticator: {0}", authenticatorModel.getProviderId());
-            UserModel authUser = clientSession.getAuthenticatedUser();
+                AuthenticatorModel authenticatorModel = realm.getAuthenticatorById(model.getAuthenticator());
+                AuthenticatorFactory factory = (AuthenticatorFactory)session.getKeycloakSessionFactory().getProviderFactory(Authenticator.class, authenticatorModel.getProviderId());
+                Authenticator authenticator = factory.create(authenticatorModel);
+                logger.debugv("authenticator: {0}", authenticatorModel.getProviderId());
+                UserModel authUser = clientSession.getAuthenticatedUser();
 
-            if (authenticator.requiresUser() && authUser == null){
-                if (alternativeChallenge != null) {
-                    clientSession.setAuthenticatorStatus(challengedAlternativeExecution.getId(), UserSessionModel.AuthenticatorStatus.CHALLENGED);
-                    return alternativeChallenge;
+                if (authenticator.requiresUser() && authUser == null){
+                    if (alternativeChallenge != null) {
+                        clientSession.setAuthenticatorStatus(challengedAlternativeExecution.getId(), UserSessionModel.AuthenticatorStatus.CHALLENGED);
+                        return alternativeChallenge;
+                    }
+                    throw new AuthException("authenticator: " + authenticatorModel.getProviderId(), Error.UNKNOWN_USER);
                 }
-                throw new AuthException("authenticator: " + authenticatorModel.getProviderId(), Error.UNKNOWN_USER);
-            }
-            boolean configuredFor = false;
-            if (authenticator.requiresUser() && authUser != null) {
-                configuredFor = authenticator.configuredFor(session, realm, authUser);
-                if (!configuredFor) {
-                    if (model.isRequired()) {
-                        if (model.isUserSetupAllowed()) {
-                            logger.debugv("authenticator SETUP_REQUIRED: {0}", authenticatorModel.getProviderId());
-                            clientSession.setAuthenticatorStatus(model.getId(), UserSessionModel.AuthenticatorStatus.SETUP_REQUIRED);
-                            authenticator.setRequiredActions(session, realm, clientSession.getAuthenticatedUser());
+                boolean configuredFor = false;
+                if (authenticator.requiresUser() && authUser != null) {
+                    configuredFor = authenticator.configuredFor(session, realm, authUser);
+                    if (!configuredFor) {
+                        if (model.isRequired()) {
+                            if (model.isUserSetupAllowed()) {
+                                logger.debugv("authenticator SETUP_REQUIRED: {0}", authenticatorModel.getProviderId());
+                                clientSession.setAuthenticatorStatus(model.getId(), UserSessionModel.AuthenticatorStatus.SETUP_REQUIRED);
+                                authenticator.setRequiredActions(session, realm, clientSession.getAuthenticatedUser());
+                                continue;
+                            } else {
+                                throw new AuthException(Error.CREDENTIAL_SETUP_REQUIRED);
+                            }
+                        } else if (model.isOptional()) {
+                            clientSession.setAuthenticatorStatus(model.getId(), UserSessionModel.AuthenticatorStatus.SKIPPED);
                             continue;
-                        } else {
-                            throw new AuthException(Error.CREDENTIAL_SETUP_REQUIRED);
                         }
-                    } else if (model.isOptional()) {
-                        clientSession.setAuthenticatorStatus(model.getId(), UserSessionModel.AuthenticatorStatus.SKIPPED);
-                        continue;
                     }
                 }
+                Result context = new Result(model, authenticatorModel, authenticator);
+                authenticator.authenticate(context);
+                Response response = processResult(context);
+                if (response != null) return response;
             }
-            context = new Result(model, authenticatorModel, authenticator);
-            authenticator.authenticate(context);
-            Status result = context.getStatus();
-            if (result == Status.SUCCESS){
+            return null;
+        }
+
+
+        public Response processResult(Result result) {
+            AuthenticationExecutionModel execution = result.getExecution();
+            AuthenticatorModel authenticatorModel = result.getAuthenticatorModel();
+            Status status = result.getStatus();
+            if (status == Status.SUCCESS){
                 logger.debugv("authenticator SUCCESS: {0}", authenticatorModel.getProviderId());
-                clientSession.setAuthenticatorStatus(model.getId(), UserSessionModel.AuthenticatorStatus.SUCCESS);
-                if (model.isAlternative()) alternativeSuccessful = true;
-                continue;
-            } else if (result == Status.FAILED) {
+                clientSession.setAuthenticatorStatus(execution.getId(), UserSessionModel.AuthenticatorStatus.SUCCESS);
+                if (execution.isAlternative()) alternativeSuccessful = true;
+                return null;
+            } else if (status == Status.FAILED) {
                 logger.debugv("authenticator FAILED: {0}", authenticatorModel.getProviderId());
                 logUserFailure();
-                clientSession.setAuthenticatorStatus(model.getId(), UserSessionModel.AuthenticatorStatus.FAILED);
-                if (context.challenge != null) return context.challenge;
-                throw new AuthException(context.error);
-            } else if (result == Status.FORCE_CHALLENGE) {
-                clientSession.setAuthenticatorStatus(model.getId(), UserSessionModel.AuthenticatorStatus.CHALLENGED);
-                return context.challenge;
-            } else if (result == Status.CHALLENGE) {
+                clientSession.setAuthenticatorStatus(execution.getId(), UserSessionModel.AuthenticatorStatus.FAILED);
+                if (result.challenge != null) return result.challenge;
+                throw new AuthException(result.error);
+            } else if (status == Status.FORCE_CHALLENGE) {
+                clientSession.setAuthenticatorStatus(execution.getId(), UserSessionModel.AuthenticatorStatus.CHALLENGED);
+                return result.challenge;
+            } else if (status == Status.CHALLENGE) {
                 logger.debugv("authenticator CHALLENGE: {0}", authenticatorModel.getProviderId());
-                if (model.isRequired() || (model.isOptional() && configuredFor)) {
-                    clientSession.setAuthenticatorStatus(model.getId(), UserSessionModel.AuthenticatorStatus.CHALLENGED);
-                    return context.challenge;
+                if (execution.isRequired()) {
+                    clientSession.setAuthenticatorStatus(execution.getId(), UserSessionModel.AuthenticatorStatus.CHALLENGED);
+                    return result.challenge;
                 }
-                else if (model.isAlternative()) {
-                    alternativeChallenge = context.challenge;
-                    challengedAlternativeExecution = model;
+                UserModel authenticatedUser = clientSession.getAuthenticatedUser();
+                if (execution.isOptional() && authenticatedUser != null && result.getAuthenticator().configuredFor(session, realm, authenticatedUser)) {
+                    clientSession.setAuthenticatorStatus(execution.getId(), UserSessionModel.AuthenticatorStatus.CHALLENGED);
+                    return result.challenge;
+                }
+                if (execution.isAlternative()) {
+                    alternativeChallenge = result.challenge;
+                    challengedAlternativeExecution = execution;
                 } else {
-                    clientSession.setAuthenticatorStatus(model.getId(), UserSessionModel.AuthenticatorStatus.SKIPPED);
+                    clientSession.setAuthenticatorStatus(execution.getId(), UserSessionModel.AuthenticatorStatus.SKIPPED);
                 }
-                continue;
-            } else if (result == Status.FAILURE_CHALLENGE) {
+                return null;
+            } else if (status == Status.FAILURE_CHALLENGE) {
                 logger.debugv("authenticator FAILURE_CHALLENGE: {0}", authenticatorModel.getProviderId());
                 logUserFailure();
-                clientSession.setAuthenticatorStatus(model.getId(), UserSessionModel.AuthenticatorStatus.CHALLENGED);
-                return context.challenge;
-            } else if (result == Status.ATTEMPTED) {
+                clientSession.setAuthenticatorStatus(execution.getId(), UserSessionModel.AuthenticatorStatus.CHALLENGED);
+                return result.challenge;
+            } else if (status == Status.ATTEMPTED) {
                 logger.debugv("authenticator ATTEMPTED: {0}", authenticatorModel.getProviderId());
-                if (model.getRequirement() == AuthenticationExecutionModel.Requirement.REQUIRED) {
+                if (execution.getRequirement() == AuthenticationExecutionModel.Requirement.REQUIRED) {
                     throw new AuthException(Error.INVALID_CREDENTIALS);
                 }
-                clientSession.setAuthenticatorStatus(model.getId(), UserSessionModel.AuthenticatorStatus.ATTEMPTED);
-                continue;
+                clientSession.setAuthenticatorStatus(execution.getId(), UserSessionModel.AuthenticatorStatus.ATTEMPTED);
+                return null;
             } else {
                 logger.debugv("authenticator INTERNAL_ERROR: {0}", authenticatorModel.getProviderId());
                 logger.error("Unknown result status");
                 throw new AuthException(Error.INTERNAL_ERROR);
             }
-        }
-        return null;
-    }
 
+        }
 
 
-    public void validateUser(UserModel authenticatedUser) {
-        if (authenticatedUser != null) {
-            if (!authenticatedUser.isEnabled()) throw new AuthException(Error.USER_DISABLED);
-        }
-        if (realm.isBruteForceProtected()) {
-            if (protector.isTemporarilyDisabled(session, realm, authenticatedUser.getUsername())) {
-                throw new AuthException(Error.USER_TEMPORARILY_DISABLED);
-            }
-        }
     }
 
-    protected Response authenticationComplete() {
-        String username = clientSession.getAuthenticatedUser().getUsername();
-        String rememberMe = clientSession.getNote(Details.REMEMBER_ME);
-        boolean remember = rememberMe != null && rememberMe.equalsIgnoreCase("true");
-        if (userSession == null) { // if no authenticator attached a usersession
-            userSession = session.sessions().createUserSession(realm, clientSession.getAuthenticatedUser(), username, connection.getRemoteAddr(), clientSession.getAuthMethod(), remember, null, null);
-            userSession.setState(UserSessionModel.State.LOGGING_IN);
-        }
-        if (remember) {
-            event.detail(Details.REMEMBER_ME, "true");
-        }
-        TokenManager.attachClientSession(userSession, clientSession);
-        event.user(userSession.getUser())
-             .detail(Details.USERNAME, username)
-             .session(userSession);
 
-        return AuthenticationManager.nextActionAfterAuthentication(session, userSession, clientSession, connection, request, uriInfo, event);
 
-    }
 
 
 }
diff --git a/services/src/main/java/org/keycloak/authentication/Authenticator2.java b/services/src/main/java/org/keycloak/authentication/Authenticator2.java
new file mode 100755
index 0000000..f78d283
--- /dev/null
+++ b/services/src/main/java/org/keycloak/authentication/Authenticator2.java
@@ -0,0 +1,18 @@
+package org.keycloak.authentication;
+
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.provider.Provider;
+import sun.security.krb5.internal.AuthContext;
+
+/**
+* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+* @version $Revision: 1 $
+*/
+public interface Authenticator2 extends Authenticator {
+    void putAction(AuthContext context);
+    void postAction(AuthContext context);
+    void deleteAction(AuthContext context);
+    void getAction(AuthContext context);
+}