keycloak-aplcache

Merge pull request #2096 from patriot1burke/master redirect

1/22/2016 9:40:45 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 0ea6ad9..184df85 100755
--- a/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
+++ b/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
@@ -57,6 +57,7 @@ public class AuthenticationProcessor {
     protected String flowPath;
     protected boolean browserFlow;
     protected BruteForceProtector protector;
+    protected boolean oneActionWasSuccessful;
     /**
      * This could be an error message forwarded from another authenticator
      */
@@ -761,6 +762,28 @@ public class AuthenticationProcessor {
         return challenge;
     }
 
+    /**
+     * Marks that at least one action was successful
+     *
+     */
+    public void setActionSuccessful() {
+        oneActionWasSuccessful = true;
+    }
+
+    public Response checkWasSuccessfulBrowserAction() {
+        if (oneActionWasSuccessful && isBrowserFlow()) {
+            // redirect to non-action url so browser refresh button works without reposting past data
+            String code = generateCode();
+
+            URI redirect = LoginActionsService.loginActionsBaseUrl(getUriInfo())
+                    .path(flowPath)
+                    .queryParam(OAuth2Constants.CODE, code).build(getRealm().getName());
+            return Response.status(302).location(redirect).build();
+        } else {
+            return null;
+        }
+    }
+
     public void attachSession() {
         String username = clientSession.getAuthenticatedUser().getUsername();
         String attemptedUsername = clientSession.getNote(AbstractUsernameFormAuthenticator.ATTEMPTED_USERNAME);
diff --git a/services/src/main/java/org/keycloak/authentication/DefaultAuthenticationFlow.java b/services/src/main/java/org/keycloak/authentication/DefaultAuthenticationFlow.java
index ff140b6..46e651f 100755
--- a/services/src/main/java/org/keycloak/authentication/DefaultAuthenticationFlow.java
+++ b/services/src/main/java/org/keycloak/authentication/DefaultAuthenticationFlow.java
@@ -68,6 +68,10 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow {
                 Response response = processResult(result);
                 if (response == null) {
                     processor.getClientSession().removeNote(AuthenticationProcessor.CURRENT_AUTHENTICATION_EXECUTION);
+                    if (result.status == FlowStatus.SUCCESS) {
+                        // we do this so that flow can redirect to a non-action URL
+                        processor.setActionSuccessful();
+                    }
                     return processFlow();
                 } else return response;
             }
@@ -153,6 +157,10 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow {
                     }
                 }
             }
+            // skip if action as successful already
+            Response redirect = processor.checkWasSuccessfulBrowserAction();
+            if (redirect != null) return redirect;
+
             AuthenticationProcessor.Result context = processor.createAuthenticatorContext(model, authenticator, executions);
             logger.debug("invoke authenticator.authenticate");
             authenticator.authenticate(context);
diff --git a/services/src/main/java/org/keycloak/authentication/FormAuthenticationFlow.java b/services/src/main/java/org/keycloak/authentication/FormAuthenticationFlow.java
index a83f49e..52262fa 100755
--- a/services/src/main/java/org/keycloak/authentication/FormAuthenticationFlow.java
+++ b/services/src/main/java/org/keycloak/authentication/FormAuthenticationFlow.java
@@ -221,6 +221,7 @@ public class FormAuthenticationFlow implements AuthenticationFlow {
         }
         processor.getClientSession().setExecutionStatus(actionExecution, ClientSessionModel.ExecutionStatus.SUCCESS);
         processor.getClientSession().removeNote(AuthenticationProcessor.CURRENT_AUTHENTICATION_EXECUTION);
+        processor.setActionSuccessful();
         return null;
     }
 
diff --git a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
index 2967b67..e46cbca 100755
--- a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
+++ b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
@@ -812,15 +812,16 @@ public class LoginActionsService {
         final ClientSessionCode clientCode = checks.clientCode;
         final ClientSessionModel clientSession = clientCode.getClientSession();
 
-        if (clientSession.getUserSession() == null) {
+        final UserSessionModel userSession = clientSession.getUserSession();
+        if (userSession == null) {
             logger.userSessionNull();
             event.error(Errors.USER_SESSION_NOT_FOUND);
             throw new WebApplicationException(ErrorPage.error(session, Messages.SESSION_NOT_ACTIVE));
         }
-        if (action == null && clientSession.getUserSession() != null) { // do next required action only if user is already authenticated
+        if (action == null && userSession != null) { // do next required action only if user is already authenticated
             initEvent(clientSession);
             event.event(EventType.LOGIN);
-            return AuthenticationManager.nextActionAfterAuthentication(session, clientSession.getUserSession(), clientSession, clientConnection, request, uriInfo, event);
+            return AuthenticationManager.nextActionAfterAuthentication(session, userSession, clientSession, clientConnection, request, uriInfo, event);
         }
 
         if (!action.equals(clientSession.getNote(AuthenticationManager.CURRENT_REQUIRED_ACTION))) {
@@ -841,7 +842,7 @@ public class LoginActionsService {
         event.event(EventType.CUSTOM_REQUIRED_ACTION);
 
 
-        RequiredActionContextResult context = new RequiredActionContextResult(clientSession.getUserSession(), clientSession, realm, event, session, request, clientSession.getUserSession().getUser(), factory) {
+        RequiredActionContextResult context = new RequiredActionContextResult(userSession, clientSession, realm, event, session, request, userSession.getUser(), factory) {
             @Override
             public void ignore() {
                 throw new RuntimeException("Cannot call ignore within processAction()");
@@ -850,16 +851,19 @@ public class LoginActionsService {
         provider.processAction(context);
         if (context.getStatus() == RequiredActionContext.Status.SUCCESS) {
             event.clone().success();
-            // do both
-            clientSession.removeRequiredAction(factory.getId());
-            clientSession.getUserSession().getUser().removeRequiredAction(factory.getId());
-            clientSession.removeNote(AuthenticationManager.CURRENT_REQUIRED_ACTION);
-            // redirect to a generic code URI so that browser refresh will work
-            //return redirectToRequiredActions(code);
-            event.removeDetail(Details.CUSTOM_REQUIRED_ACTION);
             initEvent(clientSession);
             event.event(EventType.LOGIN);
-            return AuthenticationManager.nextActionAfterAuthentication(session, clientSession.getUserSession(), clientSession, clientConnection, request, uriInfo, event);
+            clientSession.removeRequiredAction(factory.getId());
+            userSession.getUser().removeRequiredAction(factory.getId());
+            clientSession.removeNote(AuthenticationManager.CURRENT_REQUIRED_ACTION);
+
+            if (AuthenticationManager.isActionRequired(session, userSession, clientSession, clientConnection, request, uriInfo, event)) {
+                // redirect to a generic code URI so that browser refresh will work
+                return redirectToRequiredActions(code);
+            } else {
+                return AuthenticationManager.finishedRequiredActions(session, userSession, clientSession, clientConnection, request, uriInfo, event);
+
+            }
        }
         if (context.getStatus() == RequiredActionContext.Status.CHALLENGE) {
             return context.getChallenge();