keycloak-aplcache

Details

diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java
index ce7ebf1..7a472aa 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java
@@ -54,9 +54,12 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
         entity.setTimestamp(Time.currentTime());
         entity.setClient(client.getId());
 
+
         tx.put(sessionCache, id, entity);
 
-        return wrap(realm, entity, false);
+        ClientSessionAdapter wrap = wrap(realm, entity, false);
+        wrap.setNote(ClientSessionModel.ACTION_KEY, KeycloakModelUtils.generateCodeSecret());
+        return wrap;
     }
 
     @Override
diff --git a/server-spi/src/main/java/org/keycloak/models/ClientSessionModel.java b/server-spi/src/main/java/org/keycloak/models/ClientSessionModel.java
index 293f38b..803473a 100755
--- a/server-spi/src/main/java/org/keycloak/models/ClientSessionModel.java
+++ b/server-spi/src/main/java/org/keycloak/models/ClientSessionModel.java
@@ -7,6 +7,7 @@ import java.util.Set;
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
 public interface ClientSessionModel {
+    public static final String ACTION_KEY = "action_key";
 
     public String getId();
     public RealmModel getRealm();
diff --git a/server-spi/src/main/java/org/keycloak/services/managers/ClientSessionCode.java b/server-spi/src/main/java/org/keycloak/services/managers/ClientSessionCode.java
index 91c388f..64386ab 100755
--- a/server-spi/src/main/java/org/keycloak/services/managers/ClientSessionCode.java
+++ b/server-spi/src/main/java/org/keycloak/services/managers/ClientSessionCode.java
@@ -22,8 +22,6 @@ import java.util.UUID;
  */
 public class ClientSessionCode {
 
-    public static final String ACTION_KEY = "action_key";
-
     private static final byte[] HASH_SEPERATOR = "//".getBytes();
 
     private final RealmModel realm;
@@ -211,7 +209,6 @@ public class ClientSessionCode {
 
     public void setAction(String action) {
         clientSession.setAction(action);
-        clientSession.setNote(ACTION_KEY, UUID.randomUUID().toString());
         clientSession.setTimestamp(Time.currentTime());
     }
 
@@ -237,7 +234,7 @@ public class ClientSessionCode {
             mac.init(codeSecretKey);
             mac.update(clientSession.getId().getBytes());
             mac.update(HASH_SEPERATOR);
-            mac.update(clientSession.getNote(ACTION_KEY).getBytes());
+            mac.update(clientSession.getNote(ClientSessionModel.ACTION_KEY).getBytes());
             return Base64Url.encode(mac.doFinal());
         } catch (Exception e) {
             throw new RuntimeException(e);
diff --git a/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java b/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
index 184df85..d40b96b 100755
--- a/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
+++ b/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
@@ -1,5 +1,6 @@
 package org.keycloak.authentication;
 
+import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.HttpRequest;
 import org.keycloak.common.ClientConnection;
 import org.keycloak.OAuth2Constants;
@@ -30,6 +31,7 @@ import org.keycloak.services.managers.ClientSessionCode;
 import org.keycloak.services.messages.Messages;
 import org.keycloak.services.resources.LoginActionsService;
 import org.keycloak.common.util.Time;
+import org.keycloak.services.util.CacheControlUtil;
 
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
@@ -575,9 +577,11 @@ public class AuthenticationProcessor {
                         .setConnection(connection)
                         .setEventBuilder(event)
                         .setRealm(realm)
+                        .setBrowserFlow(isBrowserFlow())
                         .setSession(session)
                         .setUriInfo(uriInfo)
                         .setRequest(request);
+                CacheControlUtil.noBackButtonCacheControlHeader();
                 return processor.authenticate();
 
             } else {
@@ -656,6 +660,17 @@ public class AuthenticationProcessor {
         }
     }
 
+
+    public Response redirectToFlow() {
+        String code = generateCode();
+
+        URI redirect = LoginActionsService.loginActionsBaseUrl(getUriInfo())
+                .path(flowPath)
+                .queryParam(OAuth2Constants.CODE, code).build(getRealm().getName());
+        return Response.status(302).location(redirect).build();
+
+    }
+
     public static Response redirectToRequiredActions(RealmModel realm, ClientSessionModel clientSession, UriInfo uriInfo) {
 
         // redirect to non-action url so browser refresh button works without reposting past data
diff --git a/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java b/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java
index 1b2e871..2ae084f 100755
--- a/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java
+++ b/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java
@@ -74,9 +74,10 @@ public abstract class AuthorizationEndpointBase {
      * @param clientSession for current request
      * @param protocol handler for protocol used to initiate login
      * @param isPassive set to true if login should be passive (without login screen shown)
+     * @param redirectToAuthentication if true redirect to flow url.  If initial call to protocol is a POST, you probably want to do this.  This is so we can disable the back button on browser
      * @return response to be returned to the browser
      */
-    protected Response handleBrowserAuthenticationRequest(ClientSessionModel clientSession, LoginProtocol protocol, boolean isPassive) {
+    protected Response handleBrowserAuthenticationRequest(ClientSessionModel clientSession, LoginProtocol protocol, boolean isPassive, boolean redirectToAuthentication) {
 
         List<IdentityProviderModel> identityProviders = realm.getIdentityProviders();
         for (IdentityProviderModel identityProvider : identityProviders) {
@@ -115,6 +116,9 @@ public abstract class AuthorizationEndpointBase {
         } else {
             try {
                 RestartLoginCookie.setRestartCookie(realm, clientConnection, uriInfo, clientSession);
+                if (redirectToAuthentication) {
+                    return processor.redirectToFlow();
+                }
                 return processor.authenticate();
             } catch (Exception e) {
                 return processor.handleBrowserException(e);
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
old mode 100644
new mode 100755
index 61db4f1..f4dd22a
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
@@ -28,6 +28,7 @@ import org.keycloak.services.Urls;
 import org.keycloak.services.managers.ClientSessionCode;
 import org.keycloak.services.messages.Messages;
 import org.keycloak.services.resources.LoginActionsService;
+import org.keycloak.services.util.CacheControlUtil;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -87,7 +88,8 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
         checkRedirectUri();
 
         createClientSession();
-
+        // So back button doesn't work
+        CacheControlUtil.noBackButtonCacheControlHeader();
         switch (action) {
             case REGISTER:
                 return buildRegister();
@@ -219,7 +221,6 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
         clientSession.setAuthMethod(OIDCLoginProtocol.LOGIN_PROTOCOL);
         clientSession.setRedirectUri(redirectUri);
         clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
-        clientSession.setNote(ClientSessionCode.ACTION_KEY, KeycloakModelUtils.generateCodeSecret());
         clientSession.setNote(OIDCLoginProtocol.RESPONSE_TYPE_PARAM, responseType);
         clientSession.setNote(OIDCLoginProtocol.REDIRECT_URI_PARAM, redirectUriParam);
         clientSession.setNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()));
@@ -249,7 +250,7 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
         this.event.event(EventType.LOGIN);
         clientSession.setNote(Details.AUTH_TYPE, CODE_AUTH_TYPE);
 
-        return handleBrowserAuthenticationRequest(clientSession, new OIDCLoginProtocol(session, realm, uriInfo, headers, event), prompt != null && prompt.equals("none"));
+        return handleBrowserAuthenticationRequest(clientSession, new OIDCLoginProtocol(session, realm, uriInfo, headers, event), prompt != null && prompt.equals("none"), false);
     }
 
     private Response buildRegister() {
diff --git a/services/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java b/services/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java
index 2885f38..7d30170 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileService.java
@@ -68,8 +68,8 @@ public class SamlEcpProfileService extends SamlService {
     }
 
     @Override
-    protected Response newBrowserAuthentication(ClientSessionModel clientSession, boolean isPassive, SamlProtocol samlProtocol) {
-        return super.newBrowserAuthentication(clientSession, isPassive, createEcpSamlProtocol());
+    protected Response newBrowserAuthentication(ClientSessionModel clientSession, boolean isPassive, boolean redirectToAuthentication, SamlProtocol samlProtocol) {
+        return super.newBrowserAuthentication(clientSession, isPassive, redirectToAuthentication, createEcpSamlProtocol());
     }
 
     private SamlProtocol createEcpSamlProtocol() {
diff --git a/services/src/main/java/org/keycloak/protocol/saml/SamlService.java b/services/src/main/java/org/keycloak/protocol/saml/SamlService.java
index 0260fc7..566cf87 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/SamlService.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/SamlService.java
@@ -18,6 +18,7 @@ import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 
 import org.jboss.logging.Logger;
+import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
 import org.keycloak.common.VerificationException;
 import org.keycloak.common.util.StreamUtil;
@@ -50,6 +51,7 @@ import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.managers.ClientSessionCode;
 import org.keycloak.services.messages.Messages;
 import org.keycloak.services.resources.RealmsResource;
+import org.keycloak.services.util.CacheControlUtil;
 
 /**
  * Resource class for the oauth/openid connect token service
@@ -66,6 +68,12 @@ public class SamlService extends AuthorizationEndpointBase {
     }
 
     public abstract class BindingProtocol {
+
+        // this is to support back button on browser
+        // if true, we redirect to authenticate URL otherwise back button behavior has bad side effects
+        // and we want to turn it off.
+        protected boolean redirectToAuthentication;
+
         protected Response basicChecks(String samlRequest, String samlResponse) {
             if (!checkSsl()) {
                 event.event(EventType.LOGIN);
@@ -229,7 +237,6 @@ public class SamlService extends AuthorizationEndpointBase {
             clientSession.setAuthMethod(SamlProtocol.LOGIN_PROTOCOL);
             clientSession.setRedirectUri(redirect);
             clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
-            clientSession.setNote(ClientSessionCode.ACTION_KEY, KeycloakModelUtils.generateCodeSecret());
             clientSession.setNote(SamlProtocol.SAML_BINDING, bindingType);
             clientSession.setNote(GeneralConstants.RELAY_STATE, relayState);
             clientSession.setNote(SamlProtocol.SAML_REQUEST_ID, requestAbstractType.getID());
@@ -248,7 +255,7 @@ public class SamlService extends AuthorizationEndpointBase {
                 }
             }
 
-            return newBrowserAuthentication(clientSession, requestAbstractType.isIsPassive());
+            return newBrowserAuthentication(clientSession, requestAbstractType.isIsPassive(), redirectToAuthentication);
         }
 
         protected String getBindingType(AuthnRequestType requestAbstractType) {
@@ -449,13 +456,13 @@ public class SamlService extends AuthorizationEndpointBase {
 
     }
 
-    protected Response newBrowserAuthentication(ClientSessionModel clientSession, boolean isPassive) {
+    protected Response newBrowserAuthentication(ClientSessionModel clientSession, boolean isPassive, boolean redirectToAuthentication) {
         SamlProtocol samlProtocol = new SamlProtocol().setEventBuilder(event).setHttpHeaders(headers).setRealm(realm).setSession(session).setUriInfo(uriInfo);
-        return newBrowserAuthentication(clientSession, isPassive, samlProtocol);
+        return newBrowserAuthentication(clientSession, isPassive, redirectToAuthentication, samlProtocol);
     }
 
-    protected Response newBrowserAuthentication(ClientSessionModel clientSession, boolean isPassive, SamlProtocol samlProtocol) {
-        return handleBrowserAuthenticationRequest(clientSession, samlProtocol, isPassive);
+    protected Response newBrowserAuthentication(ClientSessionModel clientSession, boolean isPassive, boolean redirectToAuthentication, SamlProtocol samlProtocol) {
+        return handleBrowserAuthenticationRequest(clientSession, samlProtocol, isPassive, redirectToAuthentication);
     }
 
     /**
@@ -463,21 +470,29 @@ public class SamlService extends AuthorizationEndpointBase {
     @GET
     public Response redirectBinding(@QueryParam(GeneralConstants.SAML_REQUEST_KEY) String samlRequest, @QueryParam(GeneralConstants.SAML_RESPONSE_KEY) String samlResponse, @QueryParam(GeneralConstants.RELAY_STATE) String relayState) {
         logger.debug("SAML GET");
+        CacheControlUtil.noBackButtonCacheControlHeader();
         return new RedirectBindingProtocol().execute(samlRequest, samlResponse, relayState);
     }
 
     /**
      */
     @POST
+    @NoCache
     @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
     public Response postBinding(@FormParam(GeneralConstants.SAML_REQUEST_KEY) String samlRequest, @FormParam(GeneralConstants.SAML_RESPONSE_KEY) String samlResponse, @FormParam(GeneralConstants.RELAY_STATE) String relayState) {
         logger.debug("SAML POST");
-        return new PostBindingProtocol().execute(samlRequest, samlResponse, relayState);
+        PostBindingProtocol postBindingProtocol = new PostBindingProtocol();
+        // this is to support back button on browser
+        // if true, we redirect to authenticate URL otherwise back button behavior has bad side effects
+        // and we want to turn it off.
+        postBindingProtocol.redirectToAuthentication = true;
+        return postBindingProtocol.execute(samlRequest, samlResponse, relayState);
     }
 
     @GET
     @Path("descriptor")
     @Produces(MediaType.APPLICATION_XML)
+    @NoCache
     public String getDescriptor() throws Exception {
         return getIDPMetadataDescriptor(uriInfo, realm);
 
@@ -499,6 +514,7 @@ public class SamlService extends AuthorizationEndpointBase {
     @Produces(MediaType.TEXT_HTML)
     public Response idpInitiatedSSO(@PathParam("client") String clientUrlName, @QueryParam("RelayState") String relayState) {
         event.event(EventType.LOGIN);
+        CacheControlUtil.noBackButtonCacheControlHeader();
         ClientModel client = null;
         for (ClientModel c : realm.getClients()) {
             String urlName = c.getAttribute(SamlProtocol.SAML_IDP_INITIATED_SSO_URL_NAME);
@@ -537,7 +553,6 @@ public class SamlService extends AuthorizationEndpointBase {
         ClientSessionModel clientSession = session.sessions().createClientSession(realm, client);
         clientSession.setAuthMethod(SamlProtocol.LOGIN_PROTOCOL);
         clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
-        clientSession.setNote(ClientSessionCode.ACTION_KEY, KeycloakModelUtils.generateCodeSecret());
         clientSession.setNote(SamlProtocol.SAML_BINDING, SamlProtocol.SAML_POST_BINDING);
         clientSession.setNote(SamlProtocol.SAML_IDP_INITIATED_LOGIN, "true");
         clientSession.setRedirectUri(redirect);
@@ -549,11 +564,12 @@ public class SamlService extends AuthorizationEndpointBase {
             clientSession.setNote(GeneralConstants.RELAY_STATE, relayState);
         }
 
-        return newBrowserAuthentication(clientSession, false);
+        return newBrowserAuthentication(clientSession, false, false);
 
     }
 
     @POST
+    @NoCache
     @Consumes({"application/soap+xml",MediaType.TEXT_XML})
     public Response soapBinding(InputStream inputStream) {
         SamlEcpProfileService bindingService = new SamlEcpProfileService(realm, event);
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 0f9a124..bb7aae3 100755
--- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
@@ -528,7 +528,8 @@ public class AuthenticationManager {
 
             // Skip grant screen if everything was already approved by this user
             if (realmRoles.size() > 0 || resourceRoles.size() > 0 || protocolMappers.size() > 0) {
-                accessCode.setAction(ClientSessionModel.Action.OAUTH_GRANT.name());
+                accessCode.setAction(ClientSessionModel.Action.REQUIRED_ACTIONS.name());
+                clientSession.setNote(CURRENT_REQUIRED_ACTION, ClientSessionModel.Action.OAUTH_GRANT.name());
 
                 return session.getProvider(LoginFormsProvider.class)
                         .setClientSessionCode(accessCode.getCode())
diff --git a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
old mode 100644
new mode 100755
index 937df16..f19151a
--- a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
+++ b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
@@ -17,6 +17,7 @@
  */
 package org.keycloak.services.resources;
 
+import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.HttpRequest;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
 import org.keycloak.OAuth2Constants;
@@ -61,6 +62,7 @@ import org.keycloak.services.ErrorResponse;
 import org.keycloak.services.ErrorPage;
 import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.Urls;
+import org.keycloak.services.util.CacheControlUtil;
 import org.keycloak.services.validation.Validation;
 import org.keycloak.broker.social.SocialIdentityProvider;
 import org.keycloak.common.util.ObjectUtil;
@@ -694,6 +696,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
         processor.setClientSession(clientSession)
                 .setFlowPath(LoginActionsService.AUTHENTICATE_PATH)
                 .setFlowId(flowId)
+                .setBrowserFlow(true)
                 .setConnection(clientConnection)
                 .setEventBuilder(event)
                 .setRealm(realmModel)
@@ -703,6 +706,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
         if (errorMessage != null) processor.setForwardedErrorMessage(new FormMessage(null, errorMessage));
 
         try {
+            CacheControlUtil.noBackButtonCacheControlHeader();
             return processor.authenticate();
         } catch (Exception e) {
             return processor.handleBrowserException(e);
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 e23f9df..969fa8e 100755
--- a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
+++ b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
@@ -67,6 +67,7 @@ import org.keycloak.services.Urls;
 import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.managers.ClientSessionCode;
 import org.keycloak.services.messages.Messages;
+import org.keycloak.services.util.CacheControlUtil;
 import org.keycloak.services.util.CookieHelper;
 
 import javax.ws.rs.Consumes;
@@ -155,6 +156,7 @@ public class LoginActionsService {
     public LoginActionsService(RealmModel realm, EventBuilder event) {
         this.realm = realm;
         this.event = event;
+        CacheControlUtil.noBackButtonCacheControlHeader();
     }
 
     private boolean checkSsl() {
@@ -175,20 +177,34 @@ public class LoginActionsService {
             if (!verifyCode(code)) {
                 return false;
             }
-            if (!verifyAction(requiredAction, actionType)) {
-                return false;
-            } else {
-                return true;
+            if (!clientCode.isValidAction(requiredAction)) {
+                if (ClientSessionModel.Action.REQUIRED_ACTIONS.name().equals(clientCode.getClientSession().getAction())) {
+                    response = redirectToRequiredActions(code);
+                    return false;
+                } else {
+                    invalidAction();
+                    return false;
+                }
             }
-        }
+            if (!isActionActive(actionType)) return false;
+            return true;
+       }
 
-        public boolean verifyAction(String requiredAction, ClientSessionCode.ActionType actionType) {
+        public boolean isValidAction(String requiredAction) {
             if (!clientCode.isValidAction(requiredAction)) {
-                event.client(clientCode.getClientSession().getClient());
-                event.error(Errors.INVALID_CODE);
-                response = ErrorPage.error(session, Messages.INVALID_CODE);
+                invalidAction();
                 return false;
             }
+            return true;
+        }
+
+        private void invalidAction() {
+            event.client(clientCode.getClientSession().getClient());
+            event.error(Errors.INVALID_CODE);
+            response = ErrorPage.error(session, Messages.INVALID_CODE);
+        }
+
+        public boolean isActionActive(ClientSessionCode.ActionType actionType) {
             if (!clientCode.isActionActive(actionType)) {
                 event.client(clientCode.getClientSession().getClient());
                 event.clone().error(Errors.EXPIRED_CODE);
@@ -256,8 +272,48 @@ public class LoginActionsService {
             session.getContext().setClient(client);
             return true;
         }
+
+        public boolean verifyRequiredAction(String code, String executedAction) {
+            if (!verifyCode(code)) {
+                return false;
+            }
+            if (!isValidAction(ClientSessionModel.Action.REQUIRED_ACTIONS.name())) return false;
+            if (!isActionActive(ClientSessionCode.ActionType.USER)) return false;
+
+            final ClientSessionModel clientSession = clientCode.getClientSession();
+
+            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 (!AuthenticationManager.isSessionValid(realm, userSession)) {
+                AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, true);
+                event.error(Errors.INVALID_CODE);
+                response = ErrorPage.error(session, Messages.SESSION_NOT_ACTIVE);
+                return false;
+            }
+
+            if (executedAction == null && userSession != null) { // do next required action only if user is already authenticated
+                initEvent(clientSession);
+                event.event(EventType.LOGIN);
+                response = AuthenticationManager.nextActionAfterAuthentication(session, userSession, clientSession, clientConnection, request, uriInfo, event);
+                return false;
+            }
+
+            if (!executedAction.equals(clientSession.getNote(AuthenticationManager.CURRENT_REQUIRED_ACTION))) {
+                logger.debug("required action doesn't match current required action");
+                clientSession.removeNote(AuthenticationManager.CURRENT_REQUIRED_ACTION);
+                response = redirectToRequiredActions(code);
+                return false;
+            }
+            return true;
+
+        }
     }
 
+
     /**
      * protocol independent login page entry point
      *
@@ -361,13 +417,11 @@ public class LoginActionsService {
             ClientModel client = realm.getClientByClientId(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
             ClientSessionModel clientSession = session.sessions().createClientSession(realm, client);
             clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
-            clientSession.setNote(ClientSessionCode.ACTION_KEY, KeycloakModelUtils.generateCodeSecret());
             //clientSession.setNote(AuthenticationManager.END_AFTER_REQUIRED_ACTIONS, "true");
             clientSession.setAuthMethod(OIDCLoginProtocol.LOGIN_PROTOCOL);
             String redirectUri = Urls.accountBase(uriInfo.getBaseUri()).path("/").build(realm.getName()).toString();
             clientSession.setRedirectUri(redirectUri);
             clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
-            clientSession.setNote(ClientSessionCode.ACTION_KEY, KeycloakModelUtils.generateCodeSecret());
             clientSession.setNote(OIDCLoginProtocol.RESPONSE_TYPE_PARAM, OAuth2Constants.CODE);
             clientSession.setNote(OIDCLoginProtocol.REDIRECT_URI_PARAM, redirectUri);
             clientSession.setNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()));
@@ -589,19 +643,12 @@ public class LoginActionsService {
     @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
     public Response processConsent(final MultivaluedMap<String, String> formData) {
         event.event(EventType.LOGIN);
-
-
-        if (!checkSsl()) {
-            return ErrorPage.error(session, Messages.HTTPS_REQUIRED);
-        }
-
         String code = formData.getFirst("code");
-
-        ClientSessionCode accessCode = ClientSessionCode.parse(code, session, realm);
-        if (accessCode == null || !accessCode.isValid(ClientSessionModel.Action.OAUTH_GRANT.name(), ClientSessionCode.ActionType.LOGIN)) {
-            event.error(Errors.INVALID_CODE);
-            return ErrorPage.error(session, Messages.INVALID_ACCESS_CODE);
+        Checks checks = new Checks();
+        if (!checks.verifyRequiredAction(code, ClientSessionModel.Action.OAUTH_GRANT.name())) {
+            return checks.response;
         }
+        ClientSessionCode accessCode = checks.clientCode;
         ClientSessionModel clientSession = accessCode.getClientSession();
 
         initEvent(clientSession);
@@ -610,11 +657,6 @@ public class LoginActionsService {
         UserModel user = userSession.getUser();
         ClientModel client = clientSession.getClient();
 
-        if (!AuthenticationManager.isSessionValid(realm, userSession)) {
-            AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, true);
-            event.error(Errors.INVALID_CODE);
-            return ErrorPage.error(session, Messages.SESSION_NOT_ACTIVE);
-        }
 
         if (formData.containsKey("cancel")) {
             LoginProtocol protocol = session.getProvider(LoginProtocol.class, clientSession.getAuthMethod());
@@ -810,29 +852,13 @@ public class LoginActionsService {
         event.event(EventType.CUSTOM_REQUIRED_ACTION);
         event.detail(Details.CUSTOM_REQUIRED_ACTION, action);
         Checks checks = new Checks();
-        if (!checks.verifyCode(code, ClientSessionModel.Action.REQUIRED_ACTIONS.name(), ClientSessionCode.ActionType.USER)) {
+        if (!checks.verifyRequiredAction(code, action)) {
             return checks.response;
         }
         final ClientSessionCode clientCode = checks.clientCode;
         final ClientSessionModel clientSession = clientCode.getClientSession();
 
         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 && userSession != null) { // do next required action only if user is already authenticated
-            initEvent(clientSession);
-            event.event(EventType.LOGIN);
-            return AuthenticationManager.nextActionAfterAuthentication(session, userSession, clientSession, clientConnection, request, uriInfo, event);
-        }
-
-        if (!action.equals(clientSession.getNote(AuthenticationManager.CURRENT_REQUIRED_ACTION))) {
-            logger.debug("required action doesn't match current required action");
-            clientSession.removeNote(AuthenticationManager.CURRENT_REQUIRED_ACTION);
-            redirectToRequiredActions(code);
-        }
 
         RequiredActionFactory factory = (RequiredActionFactory)session.getKeycloakSessionFactory().getProviderFactory(RequiredActionProvider.class, action);
         if (factory == null) {
diff --git a/services/src/main/java/org/keycloak/services/util/CacheControlUtil.java b/services/src/main/java/org/keycloak/services/util/CacheControlUtil.java
old mode 100644
new mode 100755
index 0e2f1e0..3c9199d
--- a/services/src/main/java/org/keycloak/services/util/CacheControlUtil.java
+++ b/services/src/main/java/org/keycloak/services/util/CacheControlUtil.java
@@ -1,5 +1,7 @@
 package org.keycloak.services.util;
 
+import org.jboss.resteasy.spi.HttpResponse;
+import org.jboss.resteasy.spi.ResteasyProviderFactory;
 import org.keycloak.Config;
 
 import javax.ws.rs.core.CacheControl;
@@ -9,6 +11,11 @@ import javax.ws.rs.core.CacheControl;
  */
 public class CacheControlUtil {
 
+    public static void noBackButtonCacheControlHeader() {
+        HttpResponse response = ResteasyProviderFactory.getContextData(HttpResponse.class);
+        response.getOutputHeaders().putSingle("Cache-Control", "no-store, must-revalidate, max-age=0");
+    }
+
     public static CacheControl getDefaultCacheControl() {
         CacheControl cacheControl = new CacheControl();
         cacheControl.setNoTransform(false);
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlAdapterTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlAdapterTest.java
index fb1fa58..c4acbd2 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlAdapterTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlAdapterTest.java
@@ -54,6 +54,11 @@ public class SamlAdapterTest {
     @Rule
     public SamlAdapterTestStrategy testStrategy = new SamlAdapterTestStrategy("http://localhost:8081/auth", "http://localhost:8081", keycloakRule);
 
+    //@Test
+    public void testIDE() throws Exception {
+        Thread.sleep(100000000);
+    }
+
     @Test
     public void testPostBadRealmSignature() {
         testStrategy.testPostBadRealmSignature();
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlAdapterTestStrategy.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlAdapterTestStrategy.java
index 9f07239..43c8189 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlAdapterTestStrategy.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlAdapterTestStrategy.java
@@ -99,15 +99,27 @@ public class SamlAdapterTestStrategy  extends ExternalResource {
 
 
 
-    protected void checkLoggedOut(String mainUrl) {
+    protected void checkLoggedOut(String mainUrl, boolean postBinding) {
         String pageSource = driver.getPageSource();
         System.out.println("*** logout pagesource ***");
         System.out.println(pageSource);
         System.out.println("driver url: " + driver.getCurrentUrl());
         Assert.assertTrue(pageSource.contains("request-path: /logout.jsp"));
         driver.navigate().to(mainUrl);
+        checkAtLoginPage(postBinding);
+    }
+
+    protected void checkAtLoginPage(boolean postBinding) {
+        if (postBinding) assertAtLoginPagePostBinding();
+        else assertAtLoginPageRedirectBinding();
+    }
+
+    protected void assertAtLoginPageRedirectBinding() {
         Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
     }
+    protected void assertAtLoginPagePostBinding() {
+        Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/login-actions/authenticate"));
+    }
 
     public void testSavedPostRequest() throws Exception {
         // test login to customer-portal which does a bearer request to customer-db
@@ -116,7 +128,7 @@ public class SamlAdapterTestStrategy  extends ExternalResource {
         Assert.assertTrue(driver.getCurrentUrl().startsWith(APP_SERVER_BASE_URL + "/input-portal"));
         inputPage.execute("hello");
 
-        assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+        assertAtLoginPagePostBinding();
         loginPage.login("bburke@redhat.com", "password");
         System.out.println("Current url: " + driver.getCurrentUrl());
         Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/input-portal/secured/post");
@@ -170,13 +182,13 @@ public class SamlAdapterTestStrategy  extends ExternalResource {
 
     public void testPostSimpleLoginLogout() {
         driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post/");
-        assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+        assertAtLoginPagePostBinding();
         loginPage.login("bburke", "password");
         assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post/");
         System.out.println(driver.getPageSource());
         Assert.assertTrue(driver.getPageSource().contains("bburke"));
         driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post?GLO=true");
-        checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post/");
+        checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post/", true);
     }
 
     public void testPostPassiveLoginLogout(boolean forbiddenIfNotauthenticated) {
@@ -213,7 +225,7 @@ public class SamlAdapterTestStrategy  extends ExternalResource {
 
     public void testPostSimpleUnauthorized(CheckAuthError error) {
         driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post/");
-        assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+        assertAtLoginPagePostBinding();
         loginPage.login("unauthorized", "password");
         assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post/");
         System.out.println(driver.getPageSource());
@@ -227,52 +239,52 @@ public class SamlAdapterTestStrategy  extends ExternalResource {
         System.out.println(driver.getPageSource());
         Assert.assertTrue(driver.getPageSource().contains("bburke"));
         driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post?GLO=true");
-        checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post/");
+        checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post/", true);
     }
 
     public void testPostSignedLoginLogout() {
         driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig/");
-        assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+        assertAtLoginPagePostBinding();
         loginPage.login("bburke", "password");
         assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post-sig/");
         Assert.assertTrue(driver.getPageSource().contains("bburke"));
         driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig?GLO=true");
-        checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post-sig/");
+        checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post-sig/", true);
 
     }
     public void testPostSignedLoginLogoutTransientNameID() {
         driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig-transient/");
-        assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+        assertAtLoginPagePostBinding();
         loginPage.login("bburke", "password");
         assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post-sig-transient/");
         System.out.println(driver.getPageSource());
         Assert.assertFalse(driver.getPageSource().contains("bburke"));
         Assert.assertTrue(driver.getPageSource().contains("principal=G-"));
         driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig-transient?GLO=true");
-        checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post-sig-transient/");
+        checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post-sig-transient/", true);
 
     }
     public void testPostSignedLoginLogoutPersistentNameID() {
         driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig-persistent/");
-        assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+        assertAtLoginPagePostBinding();
         loginPage.login("bburke", "password");
         assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post-sig-persistent/");
         System.out.println(driver.getPageSource());
         Assert.assertFalse(driver.getPageSource().contains("bburke"));
         Assert.assertTrue(driver.getPageSource().contains("principal=G-"));
         driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig-persistent?GLO=true");
-        checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post-sig-persistent/");
+        checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post-sig-persistent/", true);
 
     }
     public void testPostSignedLoginLogoutEmailNameID() {
         driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig-email/");
-        assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+        assertAtLoginPagePostBinding();
         loginPage.login("bburke", "password");
         assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post-sig-email/");
         System.out.println(driver.getPageSource());
         Assert.assertTrue(driver.getPageSource().contains("principal=bburke@redhat.com"));
         driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig-email?GLO=true");
-        checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post-sig-email/");
+        checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post-sig-email/", true);
 
     }
 
@@ -281,7 +293,7 @@ public class SamlAdapterTestStrategy  extends ExternalResource {
         // at the relay state
         SamlSPFacade.samlResponse = null;
         driver.navigate().to(APP_SERVER_BASE_URL + "/employee/");
-        Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
+        assertAtLoginPageRedirectBinding();
         System.out.println(driver.getCurrentUrl());
         loginPage.login("bburke", "password");
         assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/employee/");
@@ -304,7 +316,7 @@ public class SamlAdapterTestStrategy  extends ExternalResource {
             SendUsernameServlet.sentPrincipal = null;
             SendUsernameServlet.checkRoles = null;
             driver.navigate().to(APP_SERVER_BASE_URL + "/employee2/");
-            Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
+            assertAtLoginPagePostBinding();
             List<String> requiredRoles = new LinkedList<>();
             requiredRoles.add("manager");
             requiredRoles.add("user");
@@ -322,14 +334,14 @@ public class SamlAdapterTestStrategy  extends ExternalResource {
             Set<String> groupSet = new HashSet<>();
             assertEquals("level2@redhat.com", principal.getFriendlyAttribute("email"));
             driver.navigate().to(APP_SERVER_BASE_URL + "/employee2/?GLO=true");
-            checkLoggedOut(APP_SERVER_BASE_URL + "/employee2/");
+            checkLoggedOut(APP_SERVER_BASE_URL + "/employee2/", true);
 
         }
         {
             SendUsernameServlet.sentPrincipal = null;
             SendUsernameServlet.checkRoles = null;
             driver.navigate().to(APP_SERVER_BASE_URL + "/employee2/");
-            Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
+            assertAtLoginPagePostBinding();
             List<String> requiredRoles = new LinkedList<>();
             requiredRoles.add("manager");
             requiredRoles.add("employee");
@@ -345,7 +357,7 @@ public class SamlAdapterTestStrategy  extends ExternalResource {
             assertEquals("617", principal.getAttribute("phone"));
             Assert.assertNull(principal.getFriendlyAttribute("phone"));
             driver.navigate().to(APP_SERVER_BASE_URL + "/employee2/?GLO=true");
-            checkLoggedOut(APP_SERVER_BASE_URL + "/employee2/");
+            checkLoggedOut(APP_SERVER_BASE_URL + "/employee2/", true);
 
         }
         keycloakRule.update(new KeycloakRule.KeycloakSetup() {
@@ -374,7 +386,7 @@ public class SamlAdapterTestStrategy  extends ExternalResource {
             SendUsernameServlet.sentPrincipal = null;
             SendUsernameServlet.checkRoles = null;
             driver.navigate().to(APP_SERVER_BASE_URL + "/employee2/");
-            Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
+            assertAtLoginPagePostBinding();
             List<String> requiredRoles = new LinkedList<>();
             requiredRoles.add("el-jefe");
             requiredRoles.add("user");
@@ -394,23 +406,23 @@ public class SamlAdapterTestStrategy  extends ExternalResource {
 
     public void testRedirectSignedLoginLogout() {
         driver.navigate().to(APP_SERVER_BASE_URL + "/employee-sig/");
-        Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
+        assertAtLoginPageRedirectBinding();
         loginPage.login("bburke", "password");
         assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/employee-sig/");
         Assert.assertTrue(driver.getPageSource().contains("bburke"));
         driver.navigate().to(APP_SERVER_BASE_URL + "/employee-sig?GLO=true");
-        checkLoggedOut(APP_SERVER_BASE_URL + "/employee-sig/");
+        checkLoggedOut(APP_SERVER_BASE_URL + "/employee-sig/", false);
 
     }
 
     public void testRedirectSignedLoginLogoutFrontNoSSO() {
         driver.navigate().to(APP_SERVER_BASE_URL + "/employee-sig-front/");
-        Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
+        assertAtLoginPageRedirectBinding();
         loginPage.login("bburke", "password");
         assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/employee-sig-front/");
         Assert.assertTrue(driver.getPageSource().contains("bburke"));
         driver.navigate().to(APP_SERVER_BASE_URL + "/employee-sig-front?GLO=true");
-        checkLoggedOut(APP_SERVER_BASE_URL + "/employee-sig-front/");
+        checkLoggedOut(APP_SERVER_BASE_URL + "/employee-sig-front/", false);
 
     }
 
@@ -418,7 +430,7 @@ public class SamlAdapterTestStrategy  extends ExternalResource {
         // visit 1st app an logg in
         System.out.println("visit 1st app ");
         driver.navigate().to(APP_SERVER_BASE_URL + "/employee-sig/");
-        Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
+        assertAtLoginPageRedirectBinding();
         System.out.println("login to form");
         loginPage.login("bburke", "password");
         assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/employee-sig/");
@@ -439,28 +451,29 @@ public class SamlAdapterTestStrategy  extends ExternalResource {
         // logout of first app
         System.out.println("GLO");
         driver.navigate().to(APP_SERVER_BASE_URL + "/employee-sig?GLO=true");
-        checkLoggedOut(APP_SERVER_BASE_URL + "/employee-sig/");
+        checkLoggedOut(APP_SERVER_BASE_URL + "/employee-sig/", false);
         driver.navigate().to(APP_SERVER_BASE_URL + "/employee-sig-front/");
         String currentUrl = driver.getCurrentUrl();
         Assert.assertTrue(currentUrl.startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
         driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig/");
-        Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
+        assertAtLoginPagePostBinding();
 
     }
 
     public void testPostEncryptedLoginLogout() {
         driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-enc/");
-        assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+        assertAtLoginPagePostBinding();
         loginPage.login("bburke", "password");
         assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post-enc/");
         Assert.assertTrue(driver.getPageSource().contains("bburke"));
         driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-enc?GLO=true");
-        checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post-enc/");
+        checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post-enc/", true);
 
     }
     public void testPostBadClientSignature() {
         driver.navigate().to(APP_SERVER_BASE_URL + "/bad-client-sales-post-sig/");
-        assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+        System.out.println(driver.getCurrentUrl());
+        Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
         assertEquals(driver.getTitle(), "We're sorry...");
 
     }
@@ -471,7 +484,7 @@ public class SamlAdapterTestStrategy  extends ExternalResource {
     public void testPostBadRealmSignature() {
         ErrorServlet.authError = null;
         driver.navigate().to(APP_SERVER_BASE_URL + "/bad-realm-sales-post-sig/");
-        assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+        assertAtLoginPagePostBinding();
         loginPage.login("bburke", "password");
         assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/bad-realm-sales-post-sig/");
         System.out.println(driver.getPageSource());
@@ -484,13 +497,13 @@ public class SamlAdapterTestStrategy  extends ExternalResource {
     public void testMetadataPostSignedLoginLogout() throws Exception {
 
         driver.navigate().to(APP_SERVER_BASE_URL + "/sales-metadata/");
-        assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
+        assertAtLoginPagePostBinding();
         loginPage.login("bburke", "password");
         assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-metadata/");
         String pageSource = driver.getPageSource();
         Assert.assertTrue(pageSource.contains("bburke"));
         driver.navigate().to(APP_SERVER_BASE_URL + "/sales-metadata?GLO=true");
-        checkLoggedOut(APP_SERVER_BASE_URL + "/sales-metadata/");
+        checkLoggedOut(APP_SERVER_BASE_URL + "/sales-metadata/", true);
 
     }