keycloak-memoizeit

KEYCLOAK-1109 Added KeycloakContext KEYCLOAK-1042 Access

4/15/2015 6:02:09 AM

Changes

services/src/main/java/org/keycloak/services/resources/flows/OAuthRedirect.java 76(+0 -76)

Details

diff --git a/broker/oidc/src/main/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProvider.java b/broker/oidc/src/main/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProvider.java
index c65e871..0a525a4 100755
--- a/broker/oidc/src/main/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProvider.java
+++ b/broker/oidc/src/main/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProvider.java
@@ -34,7 +34,7 @@ import org.keycloak.models.FederatedIdentityModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.services.messages.Messages;
-import org.keycloak.services.resources.flows.Flows;
+import org.keycloak.services.ErrorPage;
 
 import javax.ws.rs.GET;
 import javax.ws.rs.QueryParam;
@@ -217,7 +217,7 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
                 //logger.error("Failed " + getConfig().getAlias() + " broker login: " + error);
                 event.event(EventType.LOGIN);
                 event.error(error);
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
+                return ErrorPage.error(session, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
             }
 
             try {
@@ -239,7 +239,7 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
             }
             event.event(EventType.LOGIN);
             event.error(Errors.IDENTITY_PROVIDER_LOGIN_FAILURE);
-            return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
+            return ErrorPage.error(session, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
         }
 
         public SimpleHttp generateTokenRequest(String authorizationCode) {
diff --git a/broker/oidc/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProvider.java b/broker/oidc/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProvider.java
index c1b39a9..675361a 100755
--- a/broker/oidc/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProvider.java
+++ b/broker/oidc/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProvider.java
@@ -19,7 +19,6 @@ package org.keycloak.broker.oidc;
 
 import org.codehaus.jackson.JsonNode;
 import org.jboss.logging.Logger;
-import org.keycloak.RSATokenVerifier;
 import org.keycloak.broker.oidc.util.SimpleHttp;
 import org.keycloak.broker.provider.AuthenticationRequest;
 import org.keycloak.broker.provider.FederatedIdentity;
@@ -37,7 +36,7 @@ import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.messages.Messages;
 import org.keycloak.services.resources.IdentityBrokerService;
 import org.keycloak.services.resources.RealmsResource;
-import org.keycloak.services.resources.flows.Flows;
+import org.keycloak.services.ErrorPage;
 import org.keycloak.util.JsonSerialization;
 import org.keycloak.util.PemUtils;
 
@@ -116,14 +115,14 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider<OIDCIde
                 EventBuilder event = new EventBuilder(realm, session, clientConnection);
                 event.event(EventType.LOGOUT);
                 event.error(Errors.USER_SESSION_NOT_FOUND);
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
+                return ErrorPage.error(session, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
             }
             if (userSession.getState() != UserSessionModel.State.LOGGING_OUT) {
                 logger.error("usersession in different state");
                 EventBuilder event = new EventBuilder(realm, session, clientConnection);
                 event.event(EventType.LOGOUT);
                 event.error(Errors.USER_SESSION_NOT_FOUND);
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.SESSION_NOT_ACTIVE);
+                return ErrorPage.error(session, Messages.SESSION_NOT_ACTIVE);
             }
             return AuthenticationManager.finishBrowserLogout(session, realm, userSession, uriInfo, clientConnection, headers);
         }
diff --git a/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLEndpoint.java b/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLEndpoint.java
index d2b8a88..c40c0bb 100755
--- a/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLEndpoint.java
+++ b/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLEndpoint.java
@@ -19,7 +19,7 @@ import org.keycloak.protocol.saml.SamlProtocol;
 import org.keycloak.protocol.saml.SamlProtocolUtils;
 import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.messages.Messages;
-import org.keycloak.services.resources.flows.Flows;
+import org.keycloak.services.ErrorPage;
 import org.keycloak.saml.common.constants.GeneralConstants;
 import org.keycloak.saml.common.constants.JBossSAMLConstants;
 import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
@@ -130,18 +130,18 @@ public class SAMLEndpoint {
             if (!checkSsl()) {
                 event.event(EventType.LOGIN);
                 event.error(Errors.SSL_REQUIRED);
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.HTTPS_REQUIRED);
+                return ErrorPage.error(session, Messages.HTTPS_REQUIRED);
             }
             if (!realm.isEnabled()) {
                 event.event(EventType.LOGIN_ERROR);
                 event.error(Errors.REALM_DISABLED);
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.REALM_NOT_ENABLED);
+                return ErrorPage.error(session, Messages.REALM_NOT_ENABLED);
             }
 
             if (samlRequest == null && samlResponse == null) {
                 event.event(EventType.LOGIN);
                 event.error(Errors.INVALID_REQUEST);
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REQUEST );
+                return ErrorPage.error(session, Messages.INVALID_REQUEST);
 
             }
             return null;
@@ -177,7 +177,7 @@ public class SAMLEndpoint {
                 event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
                 event.error(Errors.INVALID_SAML_RESPONSE);
                 event.detail(Details.REASON, "invalid_destination");
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REQUEST);
+                return ErrorPage.error(session, Messages.INVALID_REQUEST);
             }
             if (config.isValidateSignature()) {
                 try {
@@ -186,7 +186,7 @@ public class SAMLEndpoint {
                     logger.error("validation failed", e);
                     event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
                     event.error(Errors.INVALID_SIGNATURE);
-                    return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REQUESTER);
+                    return ErrorPage.error(session, Messages.INVALID_REQUESTER);
                 }
             }
 
@@ -199,7 +199,7 @@ public class SAMLEndpoint {
             } else {
                 event.event(EventType.LOGIN);
                 event.error(Errors.INVALID_TOKEN);
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REQUEST);
+                return ErrorPage.error(session, Messages.INVALID_REQUEST);
             }
         }
 
@@ -327,7 +327,7 @@ public class SAMLEndpoint {
                 event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
                 event.error(Errors.INVALID_SAML_RESPONSE);
                 event.detail(Details.REASON, "invalid_destination");
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_FEDERATED_IDENTITY_ACTION);
+                return ErrorPage.error(session, Messages.INVALID_FEDERATED_IDENTITY_ACTION);
             }
             if (config.isValidateSignature()) {
                 try {
@@ -336,7 +336,7 @@ public class SAMLEndpoint {
                     logger.error("validation failed", e);
                     event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
                     event.error(Errors.INVALID_SIGNATURE);
-                    return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_FEDERATED_IDENTITY_ACTION);
+                    return ErrorPage.error(session, Messages.INVALID_FEDERATED_IDENTITY_ACTION);
                 }
             }
             if (statusResponse instanceof ResponseType) {
@@ -355,20 +355,20 @@ public class SAMLEndpoint {
                 logger.error("no valid user session");
                 event.event(EventType.LOGOUT);
                 event.error(Errors.USER_SESSION_NOT_FOUND);
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
+                return ErrorPage.error(session, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
             }
             UserSessionModel userSession = session.sessions().getUserSession(realm, relayState);
             if (userSession == null) {
                 logger.error("no valid user session");
                 event.event(EventType.LOGOUT);
                 event.error(Errors.USER_SESSION_NOT_FOUND);
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
+                return ErrorPage.error(session, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
             }
             if (userSession.getState() != UserSessionModel.State.LOGGING_OUT) {
                 logger.error("usersession in different state");
                 event.event(EventType.LOGOUT);
                 event.error(Errors.USER_SESSION_NOT_FOUND);
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.SESSION_NOT_ACTIVE);
+                return ErrorPage.error(session, Messages.SESSION_NOT_ACTIVE);
             }
             return AuthenticationManager.finishBrowserLogout(session, realm, userSession, uriInfo, clientConnection, headers);
         }
diff --git a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-events-jboss-logging/main/module.xml b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-events-jboss-logging/main/module.xml
index b786cfc..00943ab 100755
--- a/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-events-jboss-logging/main/module.xml
+++ b/distribution/modules/src/main/resources/modules/org/keycloak/keycloak-events-jboss-logging/main/module.xml
@@ -12,6 +12,7 @@
         <module name="org.keycloak.keycloak-events-api"/>
         <module name="org.jboss.logging"/>
         <module name="javax.api"/>
+        <module name="javax.ws.rs.api"/>
     </dependencies>
 
 </module>
diff --git a/events/jboss-logging/pom.xml b/events/jboss-logging/pom.xml
index cf05f96..0f407d4 100755
--- a/events/jboss-logging/pom.xml
+++ b/events/jboss-logging/pom.xml
@@ -37,6 +37,11 @@
             <scope>provided</scope>
         </dependency>
         <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
             <scope>test</scope>
diff --git a/events/jboss-logging/src/main/java/org/keycloak/events/log/JBossLoggingEventListenerProvider.java b/events/jboss-logging/src/main/java/org/keycloak/events/log/JBossLoggingEventListenerProvider.java
index badc0ee..dba4304 100755
--- a/events/jboss-logging/src/main/java/org/keycloak/events/log/JBossLoggingEventListenerProvider.java
+++ b/events/jboss-logging/src/main/java/org/keycloak/events/log/JBossLoggingEventListenerProvider.java
@@ -3,23 +3,35 @@ package org.keycloak.events.log;
 import org.jboss.logging.Logger;
 import org.keycloak.events.Event;
 import org.keycloak.events.EventListenerProvider;
+import org.keycloak.models.KeycloakContext;
+import org.keycloak.models.KeycloakSession;
 
+import javax.ws.rs.core.Cookie;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.UriInfo;
 import java.util.Map;
+import java.util.logging.Level;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
 public class JBossLoggingEventListenerProvider implements EventListenerProvider {
 
+    private final KeycloakSession session;
     private final Logger logger;
+    private final Logger.Level successLevel;
+    private final Logger.Level errorLevel;
 
-    public JBossLoggingEventListenerProvider(Logger logger) {
+    public JBossLoggingEventListenerProvider(KeycloakSession session, Logger logger, Logger.Level successLevel, Logger.Level errorLevel) {
+        this.session = session;
         this.logger = logger;
+        this.successLevel = successLevel;
+        this.errorLevel = errorLevel;
     }
 
     @Override
     public void onEvent(Event event) {
-        Logger.Level level = event.getError() != null ? Logger.Level.WARN : Logger.Level.INFO;
+        Logger.Level level = event.getError() != null ? errorLevel : successLevel;
 
         if (logger.isEnabled(level)) {
             StringBuilder sb = new StringBuilder();
@@ -55,7 +67,31 @@ public class JBossLoggingEventListenerProvider implements EventListenerProvider 
                 }
             }
 
-            logger.log(level, sb.toString());
+            if (logger.isTraceEnabled()) {
+                KeycloakContext context = session.getContext();
+                UriInfo uriInfo = context.getUri();
+                HttpHeaders headers = context.getRequestHeaders();
+                if (uriInfo != null) {
+                    sb.append(", requestUri=");
+                    sb.append(uriInfo.getRequestUri().toString());
+                }
+
+                if (headers != null) {
+                    sb.append(", cookies=[");
+                    boolean f = true;
+                    for (Map.Entry<String, Cookie> e : headers.getCookies().entrySet()) {
+                        if (f) {
+                            f = false;
+                        } else {
+                            sb.append(", ");
+                        }
+                        sb.append(e.getValue().toString());
+                    }
+                    sb.append("]");
+                }
+            }
+
+            logger.log(logger.isTraceEnabled() ? Logger.Level.TRACE : level, sb.toString());
         }
     }
 
diff --git a/events/jboss-logging/src/main/java/org/keycloak/events/log/JBossLoggingEventListenerProviderFactory.java b/events/jboss-logging/src/main/java/org/keycloak/events/log/JBossLoggingEventListenerProviderFactory.java
index 1c91cea..07ae4e2 100755
--- a/events/jboss-logging/src/main/java/org/keycloak/events/log/JBossLoggingEventListenerProviderFactory.java
+++ b/events/jboss-logging/src/main/java/org/keycloak/events/log/JBossLoggingEventListenerProviderFactory.java
@@ -6,6 +6,9 @@ import org.keycloak.events.EventListenerProvider;
 import org.keycloak.events.EventListenerProviderFactory;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
+import sun.rmi.runtime.Log;
+
+import java.util.logging.Level;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -16,13 +19,18 @@ public class JBossLoggingEventListenerProviderFactory implements EventListenerPr
 
     private static final Logger logger = Logger.getLogger("org.keycloak.events");
 
+    private Logger.Level successLevel;
+    private Logger.Level errorLevel;
+
     @Override
     public EventListenerProvider create(KeycloakSession session) {
-        return new JBossLoggingEventListenerProvider(logger);
+        return new JBossLoggingEventListenerProvider(session, logger, successLevel, errorLevel);
     }
 
     @Override
     public void init(Config.Scope config) {
+        successLevel = Logger.Level.valueOf(config.get("success-level", "debug").toUpperCase());
+        errorLevel = Logger.Level.valueOf(config.get("error-level", "warn").toUpperCase());
     }
 
     @Override
diff --git a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/FreeMarkerAccountProvider.java b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/FreeMarkerAccountProvider.java
index cb3949a..fe38f2c 100755
--- a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/FreeMarkerAccountProvider.java
+++ b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/FreeMarkerAccountProvider.java
@@ -47,7 +47,7 @@ import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.UserSessionModel;
 import org.keycloak.models.utils.FormMessage;
-import org.keycloak.services.resources.flows.Urls;
+import org.keycloak.services.Urls;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
diff --git a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/AccountFederatedIdentityBean.java b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/AccountFederatedIdentityBean.java
index 685ff45..1c779ba 100755
--- a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/AccountFederatedIdentityBean.java
+++ b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/AccountFederatedIdentityBean.java
@@ -6,7 +6,7 @@ import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.services.resources.AccountService;
-import org.keycloak.services.resources.flows.Urls;
+import org.keycloak.services.Urls;
 
 import javax.ws.rs.core.UriBuilder;
 import java.net.URI;
diff --git a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/UrlBean.java b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/UrlBean.java
index de7e432..001ffde 100755
--- a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/UrlBean.java
+++ b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/UrlBean.java
@@ -2,7 +2,7 @@ package org.keycloak.account.freemarker.model;
 
 import org.keycloak.freemarker.Theme;
 import org.keycloak.models.RealmModel;
-import org.keycloak.services.resources.flows.Urls;
+import org.keycloak.services.Urls;
 
 import java.net.URI;
 
diff --git a/forms/login-api/src/main/java/org/keycloak/login/LoginFormsProvider.java b/forms/login-api/src/main/java/org/keycloak/login/LoginFormsProvider.java
index c3a71d9..8e5ef24 100755
--- a/forms/login-api/src/main/java/org/keycloak/login/LoginFormsProvider.java
+++ b/forms/login-api/src/main/java/org/keycloak/login/LoginFormsProvider.java
@@ -21,12 +21,6 @@ import org.keycloak.provider.Provider;
  */
 public interface LoginFormsProvider extends Provider {
 
-    public LoginFormsProvider setRealm(RealmModel realm);
-
-    public LoginFormsProvider setUriInfo(UriInfo uriInfo);
-
-    public LoginFormsProvider setHttpHeaders(HttpHeaders httpHeaders);
-
     public Response createResponse(UserModel.RequiredAction action);
 
     public Response createLogin();
@@ -67,14 +61,8 @@ public interface LoginFormsProvider extends Provider {
 
     public LoginFormsProvider setSuccess(String message, Object ... parameters);
 
-    public LoginFormsProvider setWarning(String message, Object ... parameters);
-
     public LoginFormsProvider setUser(UserModel user);
 
-    public LoginFormsProvider setClient(ClientModel client);
-
-    public LoginFormsProvider setQueryParams(MultivaluedMap<String, String> queryParams);
-
     public LoginFormsProvider setResponseHeader(String headerName, String headerValue);
 
     public LoginFormsProvider setFormData(MultivaluedMap<String, String> formData);
diff --git a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/FreeMarkerLoginFormsProvider.java b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/FreeMarkerLoginFormsProvider.java
index 228a146..7e5cb78 100755
--- a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/FreeMarkerLoginFormsProvider.java
+++ b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/FreeMarkerLoginFormsProvider.java
@@ -37,9 +37,8 @@ import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.utils.FormMessage;
 import org.keycloak.services.messages.Messages;
-import org.keycloak.services.resources.flows.Urls;
+import org.keycloak.services.Urls;
 
-import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
@@ -79,39 +78,20 @@ import java.util.concurrent.TimeUnit;
 
     private KeycloakSession session;
     private FreeMarkerUtil freeMarker;
-    private RealmModel realm;
 
     private UserModel user;
 
-    private ClientModel client;
     private ClientSessionModel clientSession;
 
-    private UriInfo uriInfo;
-
-    private HttpHeaders httpHeaders;
-
     public FreeMarkerLoginFormsProvider(KeycloakSession session, FreeMarkerUtil freeMarker) {
         this.session = session;
         this.freeMarker = freeMarker;
     }
 
-    public LoginFormsProvider setRealm(RealmModel realm) {
-        this.realm = realm;
-        return this;
-    }
-
-    public LoginFormsProvider setUriInfo(UriInfo uriInfo) {
-        this.uriInfo = uriInfo;
-        return this;
-    }
-
-    @Override
-    public LoginFormsProvider setHttpHeaders(HttpHeaders httpHeaders) {
-        this.httpHeaders = httpHeaders;
-        return this;
-    }
-
     public Response createResponse(UserModel.RequiredAction action) {
+        RealmModel realm = session.getContext().getRealm();
+        UriInfo uriInfo = session.getContext().getUri();
+
         String actionMessage;
         LoginFormsPages page;
 
@@ -150,13 +130,17 @@ import java.util.concurrent.TimeUnit;
         }
 
         if (messages == null) {
-            setWarning(actionMessage);
+            setMessage(MessageType.WARNING, actionMessage);
         }
 
         return createResponse(page);
     }
 
     private Response createResponse(LoginFormsPages page) {
+        RealmModel realm = session.getContext().getRealm();
+        ClientModel client = session.getContext().getClient();
+        UriInfo uriInfo = session.getContext().getUri();
+
         MultivaluedMap<String, String> queryParameterMap = queryParams != null ? queryParams : new MultivaluedMapImpl<String, String>();
 
         String requestURI = uriInfo.getBaseUri().getPath();
@@ -191,7 +175,7 @@ import java.util.concurrent.TimeUnit;
         }
 
         Properties messagesBundle;
-        Locale locale = LocaleHelper.getLocale(realm, user, uriInfo, httpHeaders);
+        Locale locale = LocaleHelper.getLocale(realm, user, uriInfo, session.getContext().getRequestHeaders());
         try {
             messagesBundle = theme.getMessages(locale);
             attributes.put("msg", new MessageFormatterMethod(locale, messagesBundle));
@@ -222,7 +206,7 @@ import java.util.concurrent.TimeUnit;
 
         if (realm != null) {
             attributes.put("realm", new RealmBean(realm));
-            attributes.put("social", new IdentityProviderBean(realm, baseUri, this.uriInfo));
+            attributes.put("social", new IdentityProviderBean(realm, baseUri, uriInfo));
             attributes.put("url", new UrlBean(realm, theme, baseUri, this.actionUri));
 
             if (realm.isInternationalizationEnabled()) {
@@ -365,22 +349,11 @@ import java.util.concurrent.TimeUnit;
         return this;
     }
 
-    @Override
-    public FreeMarkerLoginFormsProvider setWarning(String message, Object ... parameters) {
-        setMessage(MessageType.WARNING, message, parameters);
-        return this;
-    }
-
     public FreeMarkerLoginFormsProvider setUser(UserModel user) {
         this.user = user;
         return this;
     }
 
-    public FreeMarkerLoginFormsProvider setClient(ClientModel client) {
-        this.client = client;
-        return this;
-    }
-
     public FreeMarkerLoginFormsProvider setFormData(MultivaluedMap<String, String> formData) {
         this.formData = formData;
         return this;
@@ -412,12 +385,6 @@ import java.util.concurrent.TimeUnit;
     }
 
     @Override
-    public LoginFormsProvider setQueryParams(MultivaluedMap<String, String> queryParams) {
-        this.queryParams = queryParams;
-        return this;
-    }
-
-    @Override
     public LoginFormsProvider setActionUri(URI actionUri) {
         this.actionUri = actionUri;
         return this;
diff --git a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/IdentityProviderBean.java b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/IdentityProviderBean.java
index 65e0272..23c6e69 100755
--- a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/IdentityProviderBean.java
+++ b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/IdentityProviderBean.java
@@ -23,7 +23,7 @@ package org.keycloak.login.freemarker.model;
 
 import org.keycloak.models.IdentityProviderModel;
 import org.keycloak.models.RealmModel;
-import org.keycloak.services.resources.flows.Urls;
+import org.keycloak.services.Urls;
 
 import javax.ws.rs.core.UriInfo;
 import java.net.URI;
diff --git a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/UrlBean.java b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/UrlBean.java
index eb9a40b..4c25bb3 100755
--- a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/UrlBean.java
+++ b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/UrlBean.java
@@ -23,7 +23,7 @@ package org.keycloak.login.freemarker.model;
 
 import org.keycloak.freemarker.Theme;
 import org.keycloak.models.RealmModel;
-import org.keycloak.services.resources.flows.Urls;
+import org.keycloak.services.Urls;
 
 import java.net.URI;
 
diff --git a/model/api/pom.xml b/model/api/pom.xml
index 9653491..1b97730 100755
--- a/model/api/pom.xml
+++ b/model/api/pom.xml
@@ -15,6 +15,11 @@
 
     <dependencies>
         <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
             <groupId>net.iharder</groupId>
             <artifactId>base64</artifactId>
             <scope>provided</scope>
diff --git a/model/api/src/main/java/org/keycloak/models/KeycloakContext.java b/model/api/src/main/java/org/keycloak/models/KeycloakContext.java
new file mode 100644
index 0000000..ac13d3f
--- /dev/null
+++ b/model/api/src/main/java/org/keycloak/models/KeycloakContext.java
@@ -0,0 +1,23 @@
+package org.keycloak.models;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.UriInfo;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public interface KeycloakContext {
+
+    UriInfo getUri();
+
+    HttpHeaders getRequestHeaders();
+
+    RealmModel getRealm();
+
+    void setRealm(RealmModel realm);
+
+    ClientModel getClient();
+
+    void setClient(ClientModel client);
+
+}
diff --git a/model/api/src/main/java/org/keycloak/models/KeycloakSession.java b/model/api/src/main/java/org/keycloak/models/KeycloakSession.java
index 3dc38e5..b6f35e6 100755
--- a/model/api/src/main/java/org/keycloak/models/KeycloakSession.java
+++ b/model/api/src/main/java/org/keycloak/models/KeycloakSession.java
@@ -10,6 +10,8 @@ import java.util.Set;
  */
 public interface KeycloakSession {
 
+    KeycloakContext getContext();
+
     KeycloakTransactionManager getTransaction();
 
     <T extends Provider> T getProvider(Class<T> clazz);
diff --git a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index f830ac1..0671641 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -64,7 +64,7 @@ public class RepresentationToModel {
         if (rep.getFailureFactor() != null) newRealm.setFailureFactor(rep.getFailureFactor());
         if (rep.isEventsEnabled() != null) newRealm.setEventsEnabled(rep.isEventsEnabled());
         if (rep.getEventsExpiration() != null) newRealm.setEventsExpiration(rep.getEventsExpiration());
-        if (rep.getEventsListeners() != null) newRealm.setEventsListeners(new HashSet<String>(rep.getEventsListeners()));
+        if (rep.getEventsListeners() != null) newRealm.setEventsListeners(new HashSet<>(rep.getEventsListeners()));
 
         if (rep.getNotBefore() != null) newRealm.setNotBefore(rep.getNotBefore());
 
@@ -409,8 +409,8 @@ public class RepresentationToModel {
         if (rep.getEmailTheme() != null) realm.setEmailTheme(rep.getEmailTheme());
         if (rep.isEventsEnabled() != null) realm.setEventsEnabled(rep.isEventsEnabled());
         if (rep.getEventsExpiration() != null) realm.setEventsExpiration(rep.getEventsExpiration());
-        if (rep.getEventsListeners() != null) realm.setEventsListeners(new HashSet<String>(rep.getEventsListeners()));
-        if (rep.getEnabledEventTypes() != null) realm.setEnabledEventTypes(new HashSet<String>(rep.getEnabledEventTypes()));
+        if (rep.getEventsListeners() != null) realm.setEventsListeners(new HashSet<>(rep.getEventsListeners()));
+        if (rep.getEnabledEventTypes() != null) realm.setEnabledEventTypes(new HashSet<>(rep.getEnabledEventTypes()));
 
         if (rep.getPasswordPolicy() != null) realm.setPasswordPolicy(new PasswordPolicy(rep.getPasswordPolicy()));
 
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
index b38d5b9..747c43c 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
@@ -30,7 +30,7 @@ import org.keycloak.services.managers.ResourceAdminManager;
 import org.keycloak.services.messages.Messages;
 import org.keycloak.services.resources.RealmsResource;
 import org.keycloak.services.resources.admin.ClientAttributeCertificateResource;
-import org.keycloak.services.resources.flows.Flows;
+import org.keycloak.services.ErrorPage;
 import org.w3c.dom.Document;
 
 import javax.ws.rs.core.HttpHeaders;
@@ -152,7 +152,7 @@ public class SamlProtocol implements LoginProtocol {
               return builder.redirectBinding().response();
           }
         } catch (Exception e) {
-            return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.FAILED_TO_PROCESS_RESPONSE );
+            return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE);
         }
     }
 
@@ -309,7 +309,7 @@ public class SamlProtocol implements LoginProtocol {
             samlDocument = builder.buildDocument(samlModel);
         } catch (Exception e) {
             logger.error("failed", e);
-            return Flows.forwardToSecurityFailurePage(session, realm, uriInfo,headers, Messages.FAILED_TO_PROCESS_RESPONSE);
+            return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE);
         }
 
         SAML2BindingBuilder2 bindingBuilder = new SAML2BindingBuilder2();
@@ -331,7 +331,7 @@ public class SamlProtocol implements LoginProtocol {
                 publicKey = SamlProtocolUtils.getEncryptionValidationKey(client);
             } catch (Exception e) {
                 logger.error("failed", e);
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.FAILED_TO_PROCESS_RESPONSE);
+                return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE);
             }
             bindingBuilder.encrypt(publicKey);
         }
@@ -343,7 +343,7 @@ public class SamlProtocol implements LoginProtocol {
             }
         } catch (Exception e) {
             logger.error("failed", e);
-            return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.FAILED_TO_PROCESS_RESPONSE );
+            return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE);
         }
     }
 
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java
index 3b1ff99..ff936e5 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java
@@ -23,7 +23,7 @@ import org.keycloak.services.managers.ClientSessionCode;
 import org.keycloak.services.managers.HttpAuthenticationManager;
 import org.keycloak.services.messages.Messages;
 import org.keycloak.services.resources.RealmsResource;
-import org.keycloak.services.resources.flows.Flows;
+import org.keycloak.services.ErrorPage;
 import org.keycloak.util.StreamUtil;
 import org.keycloak.saml.common.constants.GeneralConstants;
 import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
@@ -102,18 +102,18 @@ public class SamlService {
             if (!checkSsl()) {
                 event.event(EventType.LOGIN);
                 event.error(Errors.SSL_REQUIRED);
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.HTTPS_REQUIRED );
+                return ErrorPage.error(session, Messages.HTTPS_REQUIRED);
             }
             if (!realm.isEnabled()) {
                 event.event(EventType.LOGIN_ERROR);
                 event.error(Errors.REALM_DISABLED);
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.REALM_NOT_ENABLED);
+                return ErrorPage.error(session, Messages.REALM_NOT_ENABLED);
             }
 
             if (samlRequest == null && samlResponse == null) {
                 event.event(EventType.LOGIN);
                 event.error(Errors.INVALID_TOKEN);
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REQUEST );
+                return ErrorPage.error(session, Messages.INVALID_REQUEST);
 
             }
             return null;
@@ -127,7 +127,7 @@ public class SamlService {
             if (!uriInfo.getAbsolutePath().toString().equals(statusResponse.getDestination())) {
                 event.error(Errors.INVALID_SAML_LOGOUT_RESPONSE);
                 event.detail(Details.REASON, "invalid_destination");
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REQUEST);
+                return ErrorPage.error(session, Messages.INVALID_REQUEST);
             }
 
             AuthenticationManager.AuthResult authResult = authManager.authenticateIdentityCookie(session, realm, uriInfo, clientConnection, headers, false);
@@ -135,7 +135,7 @@ public class SamlService {
                 logger.warn("Unknown saml response.");
                 event.event(EventType.LOGOUT);
                 event.error(Errors.INVALID_TOKEN);
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REQUEST);
+                return ErrorPage.error(session, Messages.INVALID_REQUEST);
             }
             // assume this is a logout response
             UserSessionModel userSession = authResult.getSession();
@@ -144,7 +144,7 @@ public class SamlService {
                 logger.warn("UserSession is not tagged as logging out.");
                 event.event(EventType.LOGOUT);
                 event.error(Errors.INVALID_SAML_LOGOUT_RESPONSE);
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REQUEST);
+                return ErrorPage.error(session, Messages.INVALID_REQUEST);
             }
             logger.debug("logout response");
             Response response = authManager.browserLogout(session, realm, userSession, uriInfo, clientConnection, headers);
@@ -157,7 +157,7 @@ public class SamlService {
             if (documentHolder == null) {
                 event.event(EventType.LOGIN);
                 event.error(Errors.INVALID_TOKEN);
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REQUEST);
+                return ErrorPage.error(session, Messages.INVALID_REQUEST);
             }
 
             SAML2Object samlObject = documentHolder.getSamlObject();
@@ -169,32 +169,34 @@ public class SamlService {
             if (client == null) {
                 event.event(EventType.LOGIN);
                 event.error(Errors.CLIENT_NOT_FOUND);
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.UNKNOWN_LOGIN_REQUESTER);
+                return ErrorPage.error(session, Messages.UNKNOWN_LOGIN_REQUESTER);
             }
 
             if (!client.isEnabled()) {
                 event.event(EventType.LOGIN);
                 event.error(Errors.CLIENT_DISABLED);
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.LOGIN_REQUESTER_NOT_ENABLED);
+                return ErrorPage.error(session, Messages.LOGIN_REQUESTER_NOT_ENABLED);
             }
             if ((client instanceof ClientModel) && ((ClientModel)client).isBearerOnly()) {
                 event.event(EventType.LOGIN);
                 event.error(Errors.NOT_ALLOWED);
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.BEARER_ONLY);
+                return ErrorPage.error(session, Messages.BEARER_ONLY);
             }
             if (client.isDirectGrantsOnly()) {
                 event.event(EventType.LOGIN);
                 event.error(Errors.NOT_ALLOWED);
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.DIRECT_GRANTS_ONLY );
+                return ErrorPage.error(session, Messages.DIRECT_GRANTS_ONLY);
             }
 
+            session.getContext().setClient(client);
+
             try {
                 verifySignature(documentHolder, client);
             } catch (VerificationException e) {
                 SamlService.logger.error("request validation failed", e);
                 event.event(EventType.LOGIN);
                 event.error(Errors.INVALID_SIGNATURE);
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REQUESTER);
+                return ErrorPage.error(session, Messages.INVALID_REQUESTER);
             }
             logger.debug("verified request");
             if (samlObject instanceof AuthnRequestType) {
@@ -212,7 +214,7 @@ public class SamlService {
             } else {
                 event.event(EventType.LOGIN);
                 event.error(Errors.INVALID_TOKEN);
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REQUEST);
+                return ErrorPage.error(session, Messages.INVALID_REQUEST);
             }
         }
 
@@ -226,7 +228,7 @@ public class SamlService {
             if (!uriInfo.getAbsolutePath().equals(requestAbstractType.getDestination())) {
                 event.error(Errors.INVALID_SAML_AUTHN_REQUEST);
                 event.detail(Details.REASON, "invalid_destination");
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REQUEST);
+                return ErrorPage.error(session, Messages.INVALID_REQUEST);
             }
             String bindingType = getBindingType(requestAbstractType);
             if ("true".equals(client.getAttribute(SamlProtocol.SAML_FORCE_POST_BINDING))) bindingType = SamlProtocol.SAML_POST_BINDING;
@@ -248,7 +250,7 @@ public class SamlService {
 
             if (redirect == null) {
                 event.error(Errors.INVALID_REDIRECT_URI);
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REDIRECT_URI );
+                return ErrorPage.error(session, Messages.INVALID_REDIRECT_URI);
             }
 
 
@@ -271,7 +273,7 @@ public class SamlService {
                 } else {
                     event.error(Errors.INVALID_SAML_AUTHN_REQUEST);
                     event.detail(Details.REASON, "unsupported_nameid_format");
-                    return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.UNSUPPORTED_NAME_ID_FORMAT);
+                    return ErrorPage.error(session, Messages.UNSUPPORTED_NAME_ID_FORMAT);
                 }
             }
 
@@ -283,7 +285,7 @@ public class SamlService {
             HttpAuthenticationManager.HttpAuthOutput httpAuthOutput = httpAuthManager.spnegoAuthenticate(headers);
             if (httpAuthOutput.getResponse() != null) return httpAuthOutput.getResponse();
 
-            LoginFormsProvider forms = Flows.forms(session, realm, clientSession.getClient(), uriInfo, headers)
+            LoginFormsProvider forms = session.getProvider(LoginFormsProvider.class)
                     .setClientSessionCode(new ClientSessionCode(realm, clientSession).getCode());
 
             // Attach state from SPNEGO authentication
@@ -335,7 +337,7 @@ public class SamlService {
             if (!uriInfo.getAbsolutePath().equals(logoutRequest.getDestination())) {
                 event.error(Errors.INVALID_SAML_LOGOUT_REQUEST);
                 event.detail(Details.REASON, "invalid_destination");
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REQUEST);
+                return ErrorPage.error(session, Messages.INVALID_REQUEST);
             }
 
             // authenticate identity cookie, but ignore an access token timeout as we're logging out anyways.
@@ -374,7 +376,7 @@ public class SamlService {
             if (redirectUri != null) {
                 redirectUri = RedirectUtils.verifyRedirectUri(uriInfo, redirectUri, realm, client);
                 if (redirectUri == null) {
-                    return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REDIRECT_URI );
+                    return ErrorPage.error(session, Messages.INVALID_REDIRECT_URI);
                 }
             }
             if (redirectUri != null) {
diff --git a/server/src/main/resources/META-INF/keycloak-server.json b/server/src/main/resources/META-INF/keycloak-server.json
index 1f92932..1d7b17f 100755
--- a/server/src/main/resources/META-INF/keycloak-server.json
+++ b/server/src/main/resources/META-INF/keycloak-server.json
@@ -14,6 +14,13 @@
         }
     },
 
+    "eventsListener": {
+        "jboss-logging" : {
+            "success-level": "debug",
+            "error-level": "warn"
+        }
+    },
+
     "realm": {
         "provider": "jpa"
     },
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
index e33cb67..8306b7a 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
@@ -25,8 +25,7 @@ import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.managers.ClientSessionCode;
 import org.keycloak.services.managers.HttpAuthenticationManager;
 import org.keycloak.services.messages.Messages;
-import org.keycloak.services.resources.flows.Flows;
-import org.keycloak.services.resources.flows.Urls;
+import org.keycloak.services.Urls;
 
 import javax.ws.rs.GET;
 import javax.ws.rs.core.Context;
@@ -116,7 +115,7 @@ public class AuthorizationEndpoint {
         action = Action.REGISTER;
 
         if (!realm.isRegistrationAllowed()) {
-            throw new ErrorPageException(session, realm, uriInfo, headers, Messages.REGISTRATION_NOT_ALLOWED);
+            throw new ErrorPageException(session, Messages.REGISTRATION_NOT_ALLOWED);
         }
 
         return this;
@@ -148,21 +147,21 @@ public class AuthorizationEndpoint {
     private void checkSsl() {
         if (!uriInfo.getBaseUri().getScheme().equals("https") && realm.getSslRequired().isRequired(clientConnection)) {
             event.error(Errors.SSL_REQUIRED);
-            throw new ErrorPageException(session, realm, uriInfo, headers, Messages.HTTPS_REQUIRED);
+            throw new ErrorPageException(session, Messages.HTTPS_REQUIRED);
         }
     }
 
     private void checkRealm() {
         if (!realm.isEnabled()) {
             event.error(Errors.REALM_DISABLED);
-            throw new ErrorPageException(session, realm, uriInfo, headers, Messages.REALM_NOT_ENABLED);
+            throw new ErrorPageException(session, Messages.REALM_NOT_ENABLED);
         }
     }
 
     private void checkClient() {
         if (clientId == null) {
             event.error(Errors.INVALID_REQUEST);
-            throw new ErrorPageException(session, realm, uriInfo, headers, Messages.MISSING_PARAMETER, OIDCLoginProtocol.CLIENT_ID_PARAM );
+            throw new ErrorPageException(session, Messages.MISSING_PARAMETER, OIDCLoginProtocol.CLIENT_ID_PARAM );
         }
 
         event.client(clientId);
@@ -170,18 +169,20 @@ public class AuthorizationEndpoint {
         client = realm.getClientByClientId(clientId);
         if (client == null) {
             event.error(Errors.CLIENT_NOT_FOUND);
-            throw new ErrorPageException(session, realm, uriInfo, headers, Messages.CLIENT_NOT_FOUND );
+            throw new ErrorPageException(session, Messages.CLIENT_NOT_FOUND );
         }
 
         if ((client instanceof ClientModel) && ((ClientModel) client).isBearerOnly()) {
             event.error(Errors.NOT_ALLOWED);
-            throw new ErrorPageException(session, realm, uriInfo, headers, Messages.BEARER_ONLY );
+            throw new ErrorPageException(session, Messages.BEARER_ONLY );
         }
 
         if (client.isDirectGrantsOnly()) {
             event.error(Errors.NOT_ALLOWED);
-            throw new ErrorPageException(session, realm, uriInfo, headers, Messages.DIRECT_GRANTS_ONLY);
+            throw new ErrorPageException(session, Messages.DIRECT_GRANTS_ONLY);
         }
+
+        session.getContext().setClient(client);
     }
 
     private void checkResponseType() {
@@ -190,7 +191,7 @@ public class AuthorizationEndpoint {
                 responseType = legacyResponseType;
             } else {
                 event.error(Errors.INVALID_REQUEST);
-                throw new ErrorPageException(session, realm, uriInfo, headers, Messages.MISSING_PARAMETER, OIDCLoginProtocol.RESPONSE_TYPE_PARAM );
+                throw new ErrorPageException(session, Messages.MISSING_PARAMETER, OIDCLoginProtocol.RESPONSE_TYPE_PARAM );
             }
         }
 
@@ -200,7 +201,7 @@ public class AuthorizationEndpoint {
             action = Action.CODE;
         } else {
             event.error(Errors.INVALID_REQUEST);
-            throw new ErrorPageException(session, realm, uriInfo, headers, Messages.INVALID_PARAMETER, OIDCLoginProtocol.RESPONSE_TYPE_PARAM );
+            throw new ErrorPageException(session, Messages.INVALID_PARAMETER, OIDCLoginProtocol.RESPONSE_TYPE_PARAM );
         }
     }
 
@@ -210,7 +211,7 @@ public class AuthorizationEndpoint {
         redirectUri = RedirectUtils.verifyRedirectUri(uriInfo, redirectUriParam, realm, client);
         if (redirectUri == null) {
             event.error(Errors.INVALID_REDIRECT_URI);
-            throw new ErrorPageException(session, realm, uriInfo, headers, Messages.INVALID_PARAMETER, OIDCLoginProtocol.REDIRECT_URI_PARAM);
+            throw new ErrorPageException(session, Messages.INVALID_PARAMETER, OIDCLoginProtocol.REDIRECT_URI_PARAM);
         }
     }
 
@@ -238,7 +239,7 @@ public class AuthorizationEndpoint {
             IdentityProviderModel identityProviderModel = realm.getIdentityProviderByAlias(idpHint);
 
             if (identityProviderModel == null) {
-                return Flows.forms(session, realm, null, uriInfo, headers)
+                return session.getProvider(LoginFormsProvider.class)
                         .setError(Messages.IDENTITY_PROVIDER_NOT_FOUND, idpHint)
                         .createErrorPage();
             }
@@ -272,14 +273,13 @@ public class AuthorizationEndpoint {
                     return buildRedirectToIdentityProvider(identityProviders.get(0).getAlias(), accessCode);
                 }
 
-                return Flows.forms(session, realm, null, uriInfo, headers).setError(Messages.IDENTITY_PROVIDER_NOT_UNIQUE, realm.getName()).createErrorPage();
+                return session.getProvider(LoginFormsProvider.class).setError(Messages.IDENTITY_PROVIDER_NOT_UNIQUE, realm.getName()).createErrorPage();
             }
 
-            return Flows.forms(session, realm, null, uriInfo, headers).setError(Messages.REALM_SUPPORTS_NO_CREDENTIALS, realm.getName()).createErrorPage();
+            return session.getProvider(LoginFormsProvider.class).setError(Messages.REALM_SUPPORTS_NO_CREDENTIALS, realm.getName()).createErrorPage();
         }
 
-        LoginFormsProvider forms = Flows.forms(session, realm, clientSession.getClient(), uriInfo, headers)
-                .setClientSessionCode(accessCode);
+        LoginFormsProvider forms = session.getProvider(LoginFormsProvider.class).setClientSessionCode(accessCode);
 
         // Attach state from SPNEGO authentication
         if (httpAuthOutput.getChallenge() != null) {
@@ -307,7 +307,7 @@ public class AuthorizationEndpoint {
     private Response buildRegister() {
         authManager.expireIdentityCookie(realm, uriInfo, clientConnection);
 
-        return Flows.forms(session, realm, client, uriInfo, headers)
+        return session.getProvider(LoginFormsProvider.class)
                 .setClientSessionCode(new ClientSessionCode(realm, clientSession).getCode())
                 .createRegistration();
     }
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java
index 5bab0e0..31cdca3 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java
@@ -24,7 +24,7 @@ import org.keycloak.services.ErrorResponseException;
 import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.messages.Messages;
 import org.keycloak.services.resources.Cors;
-import org.keycloak.services.resources.flows.Flows;
+import org.keycloak.services.ErrorPage;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.GET;
@@ -92,7 +92,7 @@ public class LogoutEndpoint {
                 event.event(EventType.LOGOUT);
                 event.detail(Details.REDIRECT_URI, redirect);
                 event.error(Errors.INVALID_REDIRECT_URI);
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_REDIRECT_URI);
+                return ErrorPage.error(session, Messages.INVALID_REDIRECT_URI);
             }
             redirect = validatedUri;
         }
@@ -112,7 +112,7 @@ public class LogoutEndpoint {
             if (error) {
                 event.event(EventType.LOGOUT);
                 event.error(Errors.INVALID_TOKEN);
-                return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.SESSION_NOT_ACTIVE);
+                return ErrorPage.error(session, Messages.SESSION_NOT_ACTIVE);
             }
         }
 
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java
index 60b1b98..43538ee 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java
@@ -27,7 +27,7 @@ import org.keycloak.services.ErrorResponseException;
 import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.managers.ClientSessionCode;
 import org.keycloak.services.resources.Cors;
-import org.keycloak.services.resources.flows.Urls;
+import org.keycloak.services.Urls;
 
 import javax.ws.rs.OPTIONS;
 import javax.ws.rs.POST;
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java
index ba2f99c..f337163 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java
@@ -36,7 +36,7 @@ import org.keycloak.representations.AccessToken;
 import org.keycloak.services.ErrorResponseException;
 import org.keycloak.services.managers.AppAuthManager;
 import org.keycloak.services.resources.Cors;
-import org.keycloak.services.resources.flows.Urls;
+import org.keycloak.services.Urls;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.FormParam;
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/ValidateTokenEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/ValidateTokenEndpoint.java
index 249aa30..1e074b8 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/ValidateTokenEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/ValidateTokenEndpoint.java
@@ -15,10 +15,9 @@ import org.keycloak.models.RealmModel;
 import org.keycloak.protocol.oidc.TokenManager;
 import org.keycloak.representations.AccessToken;
 import org.keycloak.services.ErrorResponseException;
-import org.keycloak.services.resources.flows.Urls;
+import org.keycloak.services.Urls;
 
 import javax.ws.rs.GET;
-import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.*;
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java
index 6c327b1..666586f 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java
@@ -18,7 +18,6 @@ import org.keycloak.protocol.oidc.endpoints.ValidateTokenEndpoint;
 import org.keycloak.protocol.oidc.representations.JSONWebKeySet;
 import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.resources.RealmsResource;
-import org.keycloak.services.resources.flows.Flows;
 
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
@@ -204,7 +203,7 @@ public class OIDCLoginProtocolService {
     @Path("oauth/oob")
     @GET
     public Response installedAppUrnCallback(final @QueryParam("code") String code, final @QueryParam("error") String error, final @QueryParam("error_description") String errorDescription) {
-        LoginFormsProvider forms = Flows.forms(session, realm, null, uriInfo, headers);
+        LoginFormsProvider forms = session.getProvider(LoginFormsProvider.class);
         if (code != null) {
             return forms.setClientSessionCode(code).createCode();
         } else {
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProvider.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProvider.java
index 6cf2d50..80aee4a 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProvider.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProvider.java
@@ -1,18 +1,17 @@
 package org.keycloak.protocol.oidc;
 
 import org.keycloak.OAuth2Constants;
+import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.protocol.oidc.representations.OIDCConfigurationRepresentation;
 import org.keycloak.services.resources.RealmsResource;
-import org.keycloak.services.resources.flows.Urls;
+import org.keycloak.services.Urls;
 import org.keycloak.wellknown.WellKnownProvider;
 
 import javax.ws.rs.core.UriBuilder;
 import javax.ws.rs.core.UriInfo;
-import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Set;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -29,8 +28,17 @@ public class OIDCWellKnownProvider implements WellKnownProvider {
 
     public static final List<String> DEFAULT_RESPONSE_MODES_SUPPORTED = list("query");
 
+    private KeycloakSession session;
+
+    public OIDCWellKnownProvider(KeycloakSession session) {
+        this.session = session;
+    }
+
     @Override
-    public Object getConfig(RealmModel realm, UriInfo uriInfo) {
+    public Object getConfig() {
+        UriInfo uriInfo = session.getContext().getUri();
+        RealmModel realm = session.getContext().getRealm();
+
         UriBuilder uriBuilder = RealmsResource.protocolUrl(uriInfo);
 
         OIDCConfigurationRepresentation config = new OIDCConfigurationRepresentation();
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProviderFactory.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProviderFactory.java
index e49a993..cf913f1 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProviderFactory.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProviderFactory.java
@@ -11,16 +11,13 @@ import org.keycloak.wellknown.WellKnownProviderFactory;
  */
 public class OIDCWellKnownProviderFactory implements WellKnownProviderFactory {
 
-    private WellKnownProvider provider;
-
     @Override
     public WellKnownProvider create(KeycloakSession session) {
-        return provider;
+        return new OIDCWellKnownProvider(session);
     }
 
     @Override
     public void init(Config.Scope config) {
-        provider = new OIDCWellKnownProvider();
     }
 
     @Override
@@ -29,7 +26,6 @@ public class OIDCWellKnownProviderFactory implements WellKnownProviderFactory {
 
     @Override
     public void close() {
-        provider = null;
     }
 
     @Override
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/utils/RedirectUtils.java b/services/src/main/java/org/keycloak/protocol/oidc/utils/RedirectUtils.java
index 68da825..df650f6 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/utils/RedirectUtils.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/utils/RedirectUtils.java
@@ -4,7 +4,7 @@ import org.jboss.logging.Logger;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.Constants;
 import org.keycloak.models.RealmModel;
-import org.keycloak.services.resources.flows.Urls;
+import org.keycloak.services.Urls;
 
 import javax.ws.rs.core.UriInfo;
 import java.net.URI;
diff --git a/services/src/main/java/org/keycloak/services/DefaultKeycloakContext.java b/services/src/main/java/org/keycloak/services/DefaultKeycloakContext.java
new file mode 100644
index 0000000..1b0e567
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/DefaultKeycloakContext.java
@@ -0,0 +1,50 @@
+package org.keycloak.services;
+
+import org.jboss.resteasy.spi.ResteasyProviderFactory;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakContext;
+import org.keycloak.models.RealmModel;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.UriInfo;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class DefaultKeycloakContext implements KeycloakContext {
+
+    private RealmModel realm;
+
+    private ClientModel client;
+
+    @Override
+    public UriInfo getUri() {
+        return ResteasyProviderFactory.getContextData(UriInfo.class);
+    }
+
+    @Override
+    public HttpHeaders getRequestHeaders() {
+        return ResteasyProviderFactory.getContextData(HttpHeaders.class);
+    }
+
+    @Override
+    public RealmModel getRealm() {
+        return realm;
+    }
+
+    @Override
+    public void setRealm(RealmModel realm) {
+        this.realm = realm;
+    }
+
+    @Override
+    public ClientModel getClient() {
+        return client;
+    }
+
+    @Override
+    public void setClient(ClientModel client) {
+        this.client = client;
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java b/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java
index e83f84d..190750f 100755
--- a/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java
+++ b/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java
@@ -1,5 +1,8 @@
 package org.keycloak.services;
 
+import org.jboss.resteasy.spi.HttpRequest;
+import org.jboss.resteasy.spi.ResteasyProviderFactory;
+import org.keycloak.models.KeycloakContext;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
 import org.keycloak.models.KeycloakTransactionManager;
@@ -12,6 +15,7 @@ import org.keycloak.models.cache.CacheUserProvider;
 import org.keycloak.provider.Provider;
 import org.keycloak.provider.ProviderFactory;
 
+import javax.ws.rs.core.UriInfo;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedList;
@@ -32,11 +36,18 @@ public class DefaultKeycloakSession implements KeycloakSession {
     private UserProvider userModel;
     private UserSessionProvider sessionProvider;
     private UserFederationManager federationManager;
+    private KeycloakContext context;
 
     public DefaultKeycloakSession(DefaultKeycloakSessionFactory factory) {
         this.factory = factory;
         this.transactionManager = new DefaultKeycloakTransactionManager();
         federationManager = new UserFederationManager(this);
+        context = new DefaultKeycloakContext();
+    }
+
+    @Override
+    public KeycloakContext getContext() {
+        return context;
     }
 
     private RealmProvider getRealmProvider() {
diff --git a/services/src/main/java/org/keycloak/services/ErrorPageException.java b/services/src/main/java/org/keycloak/services/ErrorPageException.java
index 634ea7a..1b9d070 100644
--- a/services/src/main/java/org/keycloak/services/ErrorPageException.java
+++ b/services/src/main/java/org/keycloak/services/ErrorPageException.java
@@ -1,13 +1,9 @@
 package org.keycloak.services;
 
 import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.services.resources.flows.Flows;
 
 import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -15,24 +11,18 @@ import javax.ws.rs.core.UriInfo;
 public class ErrorPageException extends WebApplicationException {
 
     private final KeycloakSession session;
-    private final RealmModel realm;
-    private final UriInfo uriInfo;
-    private final HttpHeaders httpHeaders;
     private final String errorMessage;
     private final Object[] parameters;
 
-    public ErrorPageException(KeycloakSession session, RealmModel realm, UriInfo uriInfo, HttpHeaders headers, String errorMessage, Object ... parameters) {
+    public ErrorPageException(KeycloakSession session, String errorMessage, Object... parameters) {
         this.session = session;
-        this.realm = realm;
-        this.uriInfo = uriInfo;
-        this.httpHeaders = headers;
         this.errorMessage = errorMessage;
         this.parameters = parameters;
     }
 
     @Override
     public Response getResponse() {
-        return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, httpHeaders, errorMessage, parameters);
+        return ErrorPage.error(session, errorMessage, parameters);
     }
 
 }
diff --git a/services/src/main/java/org/keycloak/services/ErrorResponseException.java b/services/src/main/java/org/keycloak/services/ErrorResponseException.java
index 0dd3e13..6216d58 100644
--- a/services/src/main/java/org/keycloak/services/ErrorResponseException.java
+++ b/services/src/main/java/org/keycloak/services/ErrorResponseException.java
@@ -1,14 +1,10 @@
 package org.keycloak.services;
 
 import org.keycloak.OAuth2Constants;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.services.resources.flows.Flows;
 
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
 import java.util.HashMap;
 import java.util.Map;
 
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 8cd9483..bd512df 100755
--- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
@@ -30,8 +30,7 @@ import org.keycloak.representations.idm.CredentialRepresentation;
 import org.keycloak.services.resources.IdentityBrokerService;
 import org.keycloak.services.resources.LoginActionsService;
 import org.keycloak.services.resources.RealmsResource;
-import org.keycloak.services.resources.flows.Flows;
-import org.keycloak.services.resources.flows.Urls;
+import org.keycloak.services.Urls;
 import org.keycloak.services.util.CookieHelper;
 import org.keycloak.services.validation.Validation;
 import org.keycloak.util.Time;
@@ -401,7 +400,7 @@ public class AuthenticationManager {
             if (action != null) {
                 accessCode.setRequiredAction(action);
 
-                LoginFormsProvider loginFormsProvider = Flows.forms(session, realm, client, uriInfo, request.getHttpHeaders()).setClientSessionCode(accessCode.getCode())
+                LoginFormsProvider loginFormsProvider = session.getProvider(LoginFormsProvider.class).setClientSessionCode(accessCode.getCode())
                         .setUser(user);
                 if (action.equals(UserModel.RequiredAction.VERIFY_EMAIL)) {
                     event.clone().event(EventType.SEND_VERIFY_EMAIL).detail(Details.EMAIL, user.getEmail()).success();
@@ -425,10 +424,9 @@ public class AuthenticationManager {
                 }
             }
 
-            return Flows.forms(session, realm, client, uriInfo, request.getHttpHeaders())
+            return session.getProvider(LoginFormsProvider.class)
                     .setClientSessionCode(accessCode.getCode())
                     .setAccessRequest(realmRoles, resourceRoles)
-                    .setClient(client)
                     .createOAuthGrant(clientSession);
         }
 
diff --git a/services/src/main/java/org/keycloak/services/managers/HttpAuthenticationManager.java b/services/src/main/java/org/keycloak/services/managers/HttpAuthenticationManager.java
index 1cca55c..0deb28f 100755
--- a/services/src/main/java/org/keycloak/services/managers/HttpAuthenticationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/HttpAuthenticationManager.java
@@ -25,7 +25,7 @@ import org.keycloak.constants.KerberosConstants;
 import org.keycloak.protocol.oidc.TokenManager;
 import org.keycloak.representations.idm.CredentialRepresentation;
 import org.keycloak.services.messages.Messages;
-import org.keycloak.services.resources.flows.Flows;
+import org.keycloak.services.ErrorPage;
 
 /**
  * Handle HTTP authentication types requiring complex handshakes with multiple HTTP request/responses
@@ -114,7 +114,7 @@ public class HttpAuthenticationManager {
         Response response;
         if (!user.isEnabled()) {
             event.error(Errors.USER_DISABLED);
-            response = Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.ACCOUNT_DISABLED);
+            response = ErrorPage.error(session, Messages.ACCOUNT_DISABLED);
         } else {
             UserSessionModel userSession = session.sessions().createUserSession(realm, user, user.getUsername(), clientConnection.getRemoteAddr(), authMethod, false, null, null);
 
diff --git a/services/src/main/java/org/keycloak/services/managers/RealmManager.java b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
index 53b460a..58f11e9 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -132,6 +132,8 @@ public class RealmManager {
         realm.setMaxDeltaTimeSeconds(60 * 60 * 12); // 12 hours
         realm.setFailureFactor(30);
         realm.setSslRequired(SslRequired.EXTERNAL);
+
+        realm.setEventsListeners(Collections.singleton("jboss-logging"));
     }
 
     public boolean removeRealm(RealmModel realm) {
diff --git a/services/src/main/java/org/keycloak/services/resources/AccountService.java b/services/src/main/java/org/keycloak/services/resources/AccountService.java
index 71fb570..3fb84c6 100755
--- a/services/src/main/java/org/keycloak/services/resources/AccountService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java
@@ -24,7 +24,9 @@ package org.keycloak.services.resources;
 import org.jboss.logging.Logger;
 import org.jboss.resteasy.spi.BadRequestException;
 import org.jboss.resteasy.spi.HttpRequest;
+import org.keycloak.AbstractOAuthClient;
 import org.keycloak.ClientConnection;
+import org.keycloak.OAuth2Constants;
 import org.keycloak.account.AccountPages;
 import org.keycloak.account.AccountProvider;
 import org.keycloak.events.Details;
@@ -32,6 +34,7 @@ import org.keycloak.events.Event;
 import org.keycloak.events.EventBuilder;
 import org.keycloak.events.EventStoreProvider;
 import org.keycloak.events.EventType;
+import org.keycloak.login.LoginFormsProvider;
 import org.keycloak.models.*;
 import org.keycloak.models.utils.FormMessage;
 import org.keycloak.models.utils.ModelToRepresentation;
@@ -47,9 +50,7 @@ import org.keycloak.services.managers.Auth;
 import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.managers.ClientSessionCode;
 import org.keycloak.services.messages.Messages;
-import org.keycloak.services.resources.flows.Flows;
-import org.keycloak.services.resources.flows.OAuthRedirect;
-import org.keycloak.services.resources.flows.Urls;
+import org.keycloak.services.Urls;
 import org.keycloak.services.util.CookieHelper;
 import org.keycloak.services.util.ResolveRelative;
 import org.keycloak.services.validation.Validation;
@@ -66,6 +67,7 @@ import javax.ws.rs.core.Cookie;
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.NewCookie;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriBuilder;
 import javax.ws.rs.core.UriInfo;
@@ -230,7 +232,7 @@ public class AccountService {
             try {
                 require(AccountRoles.MANAGE_ACCOUNT);
             } catch (ForbiddenException e) {
-                return Flows.forms(session, realm, null, uriInfo, headers).setError(Messages.NO_ACCESS).createErrorPage();
+                return session.getProvider(LoginFormsProvider.class).setError(Messages.NO_ACCESS).createErrorPage();
             }
 
             setReferrerOnPage();
@@ -873,4 +875,42 @@ public class AccountService {
         }
     }
 
+    class OAuthRedirect extends AbstractOAuthClient {
+
+        /**
+         * closes client
+         */
+        public void stop() {
+        }
+
+        public Response redirect(UriInfo uriInfo, String redirectUri) {
+            String state = getStateCode();
+
+            UriBuilder uriBuilder = UriBuilder.fromUri(authUrl)
+                    .queryParam(OAuth2Constants.CLIENT_ID, clientId)
+                    .queryParam(OAuth2Constants.REDIRECT_URI, redirectUri)
+                    .queryParam(OAuth2Constants.STATE, state)
+                    .queryParam(OAuth2Constants.RESPONSE_TYPE, OAuth2Constants.CODE);
+            if (scope != null) {
+                uriBuilder.queryParam(OAuth2Constants.SCOPE, scope);
+            }
+
+            URI url = uriBuilder.build();
+
+            // todo httpOnly!
+            NewCookie cookie = new NewCookie(getStateCookieName(), state, getStateCookiePath(uriInfo), null, null, -1, isSecure);
+            logger.debug("NewCookie: " + cookie.toString());
+            logger.debug("Oauth Redirect to: " + url);
+            return Response.status(302)
+                    .location(url)
+                    .cookie(cookie).build();
+        }
+
+        private String getStateCookiePath(UriInfo uriInfo) {
+            if (stateCookiePath != null) return stateCookiePath;
+            return uriInfo.getBaseUri().getRawPath();
+        }
+
+    }
+
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java
index 24d76b2..e8c5447 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java
@@ -26,7 +26,7 @@ import org.keycloak.services.managers.ClientManager;
 import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.services.resources.KeycloakApplication;
-import org.keycloak.services.resources.flows.Urls;
+import org.keycloak.services.Urls;
 
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java
index f0decf3..98eb743 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java
@@ -23,7 +23,7 @@ import org.keycloak.services.managers.ClientManager;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.services.managers.ResourceAdminManager;
 import org.keycloak.services.resources.KeycloakApplication;
-import org.keycloak.services.resources.flows.Flows;
+import org.keycloak.services.ErrorResponse;
 import org.keycloak.util.JsonSerialization;
 import org.keycloak.util.Time;
 
@@ -100,7 +100,7 @@ public class ClientResource {
             RepresentationToModel.updateClient(rep, client);
             return Response.noContent().build();
         } catch (ModelDuplicateException e) {
-            return Flows.errors().exists("Client " + rep.getClientId() + " already exists");
+            return ErrorResponse.exists("Client " + rep.getClientId() + " already exists");
         }
     }
 
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java
index 270b7ac..b68bfc7 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java
@@ -11,7 +11,7 @@ import org.keycloak.models.RealmModel;
 import org.keycloak.models.utils.ModelToRepresentation;
 import org.keycloak.models.utils.RepresentationToModel;
 import org.keycloak.representations.idm.ClientRepresentation;
-import org.keycloak.services.resources.flows.Flows;
+import org.keycloak.services.ErrorResponse;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.GET;
@@ -91,7 +91,7 @@ public class ClientsResource {
             ClientModel clientModel = RepresentationToModel.createClient(session, realm, rep, true);
             return Response.created(uriInfo.getAbsolutePathBuilder().path(getClientPath(clientModel)).build()).build();
         } catch (ModelDuplicateException e) {
-            return Flows.errors().exists("Client " + rep.getClientId() + " already exists");
+            return ErrorResponse.exists("Client " + rep.getClientId() + " already exists");
         }
     }
 
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java
index bbb32b4..fc87343 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java
@@ -16,7 +16,7 @@ import org.keycloak.models.utils.ModelToRepresentation;
 import org.keycloak.models.utils.RepresentationToModel;
 import org.keycloak.provider.ProviderFactory;
 import org.keycloak.representations.idm.IdentityProviderRepresentation;
-import org.keycloak.services.resources.flows.Flows;
+import org.keycloak.services.ErrorResponse;
 import org.keycloak.social.SocialIdentityProvider;
 
 import javax.ws.rs.Consumes;
@@ -96,7 +96,7 @@ public class IdentityProviderResource {
 
             return Response.noContent().build();
         } catch (ModelDuplicateException e) {
-            return Flows.errors().exists("Identity Provider " + providerRep.getAlias() + " already exists");
+            return ErrorResponse.exists("Identity Provider " + providerRep.getAlias() + " already exists");
         }
     }
 
@@ -169,7 +169,7 @@ public class IdentityProviderResource {
             IdentityProviderFactory factory = getIdentityProviderFactory();
             return factory.create(identityProviderModel).export(uriInfo, realm, format);
         } catch (Exception e) {
-            return Flows.errors().error("Could not export public broker configuration for identity provider [" + identityProviderModel.getProviderId() + "].", Response.Status.NOT_FOUND);
+            return ErrorResponse.error("Could not export public broker configuration for identity provider [" + identityProviderModel.getProviderId() + "].", Response.Status.NOT_FOUND);
         }
     }
 
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java
index ef0e94b..34cdc78 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java
@@ -17,7 +17,7 @@ import org.keycloak.models.utils.RepresentationToModel;
 import org.keycloak.provider.ProviderFactory;
 import org.keycloak.representations.idm.IdentityProviderRepresentation;
 import org.keycloak.services.managers.ResourceAdminManager;
-import org.keycloak.services.resources.flows.Flows;
+import org.keycloak.services.ErrorResponse;
 import org.keycloak.social.SocialIdentityProvider;
 
 import javax.ws.rs.Consumes;
@@ -132,7 +132,7 @@ public class IdentityProvidersResource {
 
             return Response.created(uriInfo.getAbsolutePathBuilder().path(representation.getProviderId()).build()).build();
         } catch (ModelDuplicateException e) {
-            return Flows.errors().exists("Identity Provider " + representation.getAlias() + " already exists");
+            return ErrorResponse.exists("Identity Provider " + representation.getAlias() + " already exists");
         }
     }
 
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
index 5fea57d..6031c2e 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
@@ -29,7 +29,7 @@ import org.keycloak.services.managers.LDAPConnectionTestManager;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.services.managers.ResourceAdminManager;
 import org.keycloak.services.managers.UsersSyncManager;
-import org.keycloak.services.resources.flows.Flows;
+import org.keycloak.services.ErrorResponse;
 import org.keycloak.timer.TimerProvider;
 
 import javax.ws.rs.Consumes;
@@ -191,11 +191,11 @@ public class RealmAdminResource {
 
             return Response.noContent().build();
         } catch (PatternSyntaxException e) {
-            return Flows.errors().exists("Specified regex pattern(s) is invalid.");
+            return ErrorResponse.exists("Specified regex pattern(s) is invalid.");
         } catch (ModelDuplicateException e) {
-            return Flows.errors().exists("Realm " + rep.getRealm() + " already exists.");
+            return ErrorResponse.exists("Realm " + rep.getRealm() + " already exists.");
         }  catch (Exception e) {
-            return Flows.errors().exists("Failed to update " + rep.getRealm() + " Realm.");
+            return ErrorResponse.exists("Failed to update " + rep.getRealm() + " Realm.");
         }
     }
 
@@ -442,7 +442,7 @@ public class RealmAdminResource {
         auth.init(RealmAuth.Resource.REALM).requireManage();
 
         boolean result = new LDAPConnectionTestManager().testLDAP(action, connectionUrl, bindDn, bindCredential);
-        return result ? Response.noContent().build() : Flows.errors().error("LDAP test error", Response.Status.BAD_REQUEST);
+        return result ? Response.noContent().build() : ErrorResponse.error("LDAP test error", Response.Status.BAD_REQUEST);
     }
 
     @Path("identity-provider")
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java
index 21fc79e..c9fea3d 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java
@@ -18,7 +18,7 @@ import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.services.ForbiddenException;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.services.resources.KeycloakApplication;
-import org.keycloak.services.resources.flows.Flows;
+import org.keycloak.services.ErrorResponse;
 import org.keycloak.util.JsonSerialization;
 
 import javax.ws.rs.Consumes;
@@ -131,7 +131,7 @@ public class RealmsAdminResource {
 
             return Response.created(location).build();
         } catch (ModelDuplicateException e) {
-            return Flows.errors().exists("Realm " + rep.getRealm() + " already exists");
+            return ErrorResponse.exists("Realm " + rep.getRealm() + " already exists");
         }
     }
 
@@ -166,7 +166,7 @@ public class RealmsAdminResource {
             try {
                 realm = realmManager.importRealm(rep);
             } catch (ModelDuplicateException e) {
-                return Flows.errors().exists("Realm " + rep.getRealm() + " already exists");
+                return ErrorResponse.exists("Realm " + rep.getRealm() + " already exists");
             }
 
             grantPermissionsToRealmCreator(realm);
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java
index 66d37a9..fa0064f 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java
@@ -9,7 +9,7 @@ import org.keycloak.models.RoleContainerModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.utils.ModelToRepresentation;
 import org.keycloak.representations.idm.RoleRepresentation;
-import org.keycloak.services.resources.flows.Flows;
+import org.keycloak.services.ErrorResponse;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
@@ -79,7 +79,7 @@ public class RoleContainerResource extends RoleResource {
             role.setDescription(rep.getDescription());
             return Response.created(uriInfo.getAbsolutePathBuilder().path(role.getName()).build()).build();
         } catch (ModelDuplicateException e) {
-            return Flows.errors().exists("Role with name " + rep.getName() + " already exists");
+            return ErrorResponse.exists("Role with name " + rep.getName() + " already exists");
         }
     }
 
@@ -144,7 +144,7 @@ public class RoleContainerResource extends RoleResource {
             updateRole(rep, role);
             return Response.noContent().build();
         } catch (ModelDuplicateException e) {
-            return Flows.errors().exists("Role with name " + rep.getName() + " already exists");
+            return ErrorResponse.exists("Role with name " + rep.getName() + " already exists");
         }
     }
 
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
index bbf202c..a1dd22d 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
@@ -36,8 +36,8 @@ import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.managers.ClientSessionCode;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.services.managers.UserManager;
-import org.keycloak.services.resources.flows.Flows;
-import org.keycloak.services.resources.flows.Urls;
+import org.keycloak.services.ErrorResponse;
+import org.keycloak.services.Urls;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
@@ -123,9 +123,9 @@ public class UsersResource {
 
             return Response.noContent().build();
         } catch (ModelDuplicateException e) {
-            return Flows.errors().exists("User exists with same username or email");
+            return ErrorResponse.exists("User exists with same username or email");
         } catch (ModelReadOnlyException re) {
-            return Flows.errors().exists("User is read only!");
+            return ErrorResponse.exists("User is read only!");
         }
     }
 
@@ -143,10 +143,10 @@ public class UsersResource {
 
         // Double-check duplicated username and email here due to federation
         if (session.users().getUserByUsername(rep.getUsername(), realm) != null) {
-            return Flows.errors().exists("User exists with same username");
+            return ErrorResponse.exists("User exists with same username");
         }
         if (rep.getEmail() != null && session.users().getUserByEmail(rep.getEmail(), realm) != null) {
-            return Flows.errors().exists("User exists with same email");
+            return ErrorResponse.exists("User exists with same email");
         }
 
         try {
@@ -162,7 +162,7 @@ public class UsersResource {
             if (session.getTransaction().isActive()) {
                 session.getTransaction().setRollbackOnly();
             }
-            return Flows.errors().exists("User exists with same username or email");
+            return ErrorResponse.exists("User exists with same username or email");
         }
     }
 
@@ -287,7 +287,7 @@ public class UsersResource {
             throw new NotFoundException("User not found");
         }
         if (session.users().getFederatedIdentity(user, provider, realm) != null) {
-            return Flows.errors().exists("User is already linked with provider");
+            return ErrorResponse.exists("User is already linked with provider");
         }
 
         FederatedIdentityModel socialLink = new FederatedIdentityModel(provider, rep.getUserId(), rep.getUserName());
@@ -352,7 +352,7 @@ public class UsersResource {
         if (removed) {
             return Response.noContent().build();
         } else {
-            return Flows.errors().error("User couldn't be deleted", Response.Status.BAD_REQUEST);
+            return ErrorResponse.error("User couldn't be deleted", Response.Status.BAD_REQUEST);
         }
     }
 
@@ -702,19 +702,19 @@ public class UsersResource {
 
         UserModel user = session.users().getUserByUsername(username, realm);
         if (user == null) {
-            return Flows.errors().error("User not found", Response.Status.NOT_FOUND);
+            return ErrorResponse.error("User not found", Response.Status.NOT_FOUND);
         }
 
         if (!user.isEnabled()) {
-            return Flows.errors().error("User is disabled", Response.Status.BAD_REQUEST);
+            return ErrorResponse.error("User is disabled", Response.Status.BAD_REQUEST);
         }
 
         if (user.getEmail() == null) {
-            return Flows.errors().error("User email missing", Response.Status.BAD_REQUEST);
+            return ErrorResponse.error("User email missing", Response.Status.BAD_REQUEST);
         }
 
         if(redirectUri != null && clientId == null){
-            return Flows.errors().error("Client id missing", Response.Status.BAD_REQUEST);
+            return ErrorResponse.error("Client id missing", Response.Status.BAD_REQUEST);
         }
 
         if(clientId == null){
@@ -723,14 +723,14 @@ public class UsersResource {
 
         ClientModel client = realm.getClientByClientId(clientId);
         if (client == null || !client.isEnabled()) {
-            return Flows.errors().error(clientId + " not enabled", Response.Status.INTERNAL_SERVER_ERROR);
+            return ErrorResponse.error(clientId + " not enabled", Response.Status.INTERNAL_SERVER_ERROR);
         }
 
         String redirect;
         if(redirectUri != null){
             redirect = RedirectUtils.verifyRedirectUri(uriInfo, redirectUri, realm, client);
             if(redirect == null){
-                return Flows.errors().error("Invalid redirect uri.", Response.Status.BAD_REQUEST);
+                return ErrorResponse.error("Invalid redirect uri.", Response.Status.BAD_REQUEST);
             }
         }else{
             redirect = Urls.accountBase(uriInfo.getBaseUri()).path("/").build(realm.getName()).toString();
@@ -760,7 +760,7 @@ public class UsersResource {
             return Response.ok().build();
         } catch (EmailException e) {
             logger.error("Failed to send password reset email", e);
-            return Flows.errors().error("Failed to send email", Response.Status.INTERNAL_SERVER_ERROR);
+            return ErrorResponse.error("Failed to send email", Response.Status.INTERNAL_SERVER_ERROR);
         }
     }
 
diff --git a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
index f8e5e8f..051aa04 100755
--- a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
+++ b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
@@ -30,6 +30,7 @@ import org.keycloak.events.Details;
 import org.keycloak.events.Errors;
 import org.keycloak.events.EventBuilder;
 import org.keycloak.events.EventType;
+import org.keycloak.login.LoginFormsProvider;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.FederatedIdentityModel;
@@ -45,8 +46,9 @@ import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.managers.AuthenticationManager.AuthResult;
 import org.keycloak.services.managers.ClientSessionCode;
 import org.keycloak.services.messages.Messages;
-import org.keycloak.services.resources.flows.Flows;
-import org.keycloak.services.resources.flows.Urls;
+import org.keycloak.services.ErrorResponse;
+import org.keycloak.services.ErrorPage;
+import org.keycloak.services.Urls;
 import org.keycloak.services.validation.Validation;
 import org.keycloak.social.SocialIdentityProvider;
 import org.keycloak.util.ObjectUtil;
@@ -185,15 +187,16 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
                     return badRequest("Invalid client.");
                 }
 
+                session.getContext().setClient(clientModel);
+
                 if (!clientModel.isAllowedRetrieveTokenFromIdentityProvider(providerId)) {
                     return corsResponse(badRequest("Client [" + audience + "] not authorized to retrieve tokens from identity provider [" + providerId + "]."), clientModel);
                 }
 
                 if (clientModel.isConsentRequired()) {
-                    return corsResponse(Flows.forms(this.session, this.realmModel, clientModel, this.uriInfo, headers)
+                    return corsResponse(session.getProvider(LoginFormsProvider.class)
                             .setClientSessionCode(authManager.extractAuthorizationHeaderToken(this.request.getHttpHeaders()))
                             .setAccessRequest("Your information from " + providerId + " identity provider.")
-                            .setClient(clientModel)
                             .setActionUri(this.uriInfo.getRequestUri())
                             .createOAuthGrant(null), clientModel);
                 }
@@ -411,7 +414,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
         }
 
         fireErrorEvent(message, throwable);
-        return Flows.forwardToSecurityFailurePage(this.session, this.realmModel, this.uriInfo, headers, message, parameters);
+        return ErrorPage.error(this.session, message, parameters);
     }
 
     private Response redirectToLoginPage(Throwable t, ClientSessionCode clientCode) {
@@ -422,7 +425,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
         }
 
         fireErrorEvent(message);
-        return Flows.forms(this.session, this.realmModel, clientCode.getClientSession().getClient(), this.uriInfo, headers)
+        return session.getProvider(LoginFormsProvider.class)
                 .setClientSessionCode(clientCode.getCode())
                 .setError(message)
                 .createLogin();
@@ -430,7 +433,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
 
     private Response badRequest(String message) {
         fireErrorEvent(message);
-        return Flows.errors().error(message, Status.BAD_REQUEST);
+        return ErrorResponse.error(message, Status.BAD_REQUEST);
     }
 
     public static IdentityProvider getIdentityProvider(KeycloakSession session, RealmModel realm, String alias) {
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 106be1c..f3f5937 100755
--- a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
+++ b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
@@ -53,8 +53,8 @@ import org.keycloak.representations.idm.CredentialRepresentation;
 import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.managers.ClientSessionCode;
 import org.keycloak.services.messages.Messages;
-import org.keycloak.services.resources.flows.Flows;
-import org.keycloak.services.resources.flows.Urls;
+import org.keycloak.services.ErrorPage;
+import org.keycloak.services.Urls;
 import org.keycloak.services.util.CookieHelper;
 import org.keycloak.services.validation.Validation;
 
@@ -162,7 +162,7 @@ public class LoginActionsService {
                 return false;
             } else if (!clientCode.isValid(requiredAction)) {
                 event.error(Errors.INVALID_CODE);
-                response = Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_CODE);
+                response = ErrorPage.error(session, Messages.INVALID_CODE);
                 return false;
             } else {
                 return true;
@@ -174,7 +174,7 @@ public class LoginActionsService {
                 return false;
             } else if (!(clientCode.isValid(requiredAction) || clientCode.isValid(alternativeRequiredAction))) {
                 event.error(Errors.INVALID_CODE);
-                response = Flows.forwardToSecurityFailurePage(session, realm, uriInfo,headers, Messages.INVALID_CODE);
+                response = ErrorPage.error(session, Messages.INVALID_CODE);
                 return false;
             } else {
                 return true;
@@ -184,20 +184,21 @@ public class LoginActionsService {
         public boolean check(String code) {
             if (!checkSsl()) {
                 event.error(Errors.SSL_REQUIRED);
-                response = Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.HTTPS_REQUIRED);
+                response = ErrorPage.error(session, Messages.HTTPS_REQUIRED);
                 return false;
             }
             if (!realm.isEnabled()) {
                 event.error(Errors.REALM_DISABLED);
-                response = Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.REALM_NOT_ENABLED);
+                response = ErrorPage.error(session, Messages.REALM_NOT_ENABLED);
                 return false;
             }
             clientCode = ClientSessionCode.parse(code, session, realm);
             if (clientCode == null) {
                 event.error(Errors.INVALID_CODE);
-                response = Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.UNKNOWN_CODE);
+                response = ErrorPage.error(session, Messages.UNKNOWN_CODE);
                 return false;
             }
+            session.getContext().setClient(clientCode.getClientSession().getClient());
             return true;
         }
     }
@@ -226,10 +227,9 @@ public class LoginActionsService {
             clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE);
         }
 
-        LoginFormsProvider forms = Flows.forms(session, realm, clientSession.getClient(), uriInfo, headers)
-                .setClientSessionCode(clientSessionCode.getCode());
-
-        return forms.createLogin();
+        return session.getProvider(LoginFormsProvider.class)
+                .setClientSessionCode(clientSessionCode.getCode())
+                .createLogin();
     }
 
     /**
@@ -244,7 +244,7 @@ public class LoginActionsService {
         event.event(EventType.REGISTER);
         if (!realm.isRegistrationAllowed()) {
             event.error(Errors.REGISTRATION_DISABLED);
-            return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.REGISTRATION_NOT_ALLOWED);
+            return ErrorPage.error(session, Messages.REGISTRATION_NOT_ALLOWED);
         }
 
         Checks checks = new Checks();
@@ -258,7 +258,7 @@ public class LoginActionsService {
 
         authManager.expireIdentityCookie(realm, uriInfo, clientConnection);
 
-        return Flows.forms(session, realm, clientSession.getClient(), uriInfo, headers)
+        return session.getProvider(LoginFormsProvider.class)
                 .setClientSessionCode(clientSessionCode.getCode())
                 .createRegistration();
     }
@@ -278,17 +278,17 @@ public class LoginActionsService {
         event.event(EventType.LOGIN);
         if (!checkSsl()) {
             event.error(Errors.SSL_REQUIRED);
-            return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.HTTPS_REQUIRED);
+            return ErrorPage.error(session, Messages.HTTPS_REQUIRED);
         }
 
         if (!realm.isEnabled()) {
             event.error(Errors.REALM_DISABLED);
-            return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.REALM_NOT_ENABLED);
+            return ErrorPage.error(session, Messages.REALM_NOT_ENABLED);
         }
         ClientSessionCode clientCode = ClientSessionCode.parse(code, session, realm);
         if (clientCode == null) {
             event.error(Errors.INVALID_CODE);
-            return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.UNKNOWN_CODE);
+            return ErrorPage.error(session, Messages.UNKNOWN_CODE);
         }
 
         ClientSessionModel clientSession = clientCode.getClientSession();
@@ -297,7 +297,8 @@ public class LoginActionsService {
         if (!clientCode.isValid(ClientSessionModel.Action.AUTHENTICATE) || clientSession.getUserSession() != null) {
             clientCode.setAction(ClientSessionModel.Action.AUTHENTICATE);
             event.client(clientSession.getClient()).error(Errors.EXPIRED_CODE);
-            return Flows.forms(this.session, realm, clientSession.getClient(), uriInfo, headers).setError(Messages.EXPIRED_CODE)
+            return session.getProvider(LoginFormsProvider.class)
+                    .setError(Messages.EXPIRED_CODE)
                     .setClientSessionCode(clientCode.getCode())
                     .createLogin();
         }
@@ -320,13 +321,15 @@ public class LoginActionsService {
         ClientModel client = clientSession.getClient();
         if (client == null) {
             event.error(Errors.CLIENT_NOT_FOUND);
-            return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.UNKNOWN_LOGIN_REQUESTER);
+            return ErrorPage.error(session, Messages.UNKNOWN_LOGIN_REQUESTER);
         }
         if (!client.isEnabled()) {
             event.error(Errors.CLIENT_NOT_FOUND);
-            return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.LOGIN_REQUESTER_NOT_ENABLED);
+            return ErrorPage.error(session, Messages.LOGIN_REQUESTER_NOT_ENABLED);
         }
 
+        session.getContext().setClient(clientSession.getClient());
+
         if (formData.containsKey("cancel")) {
             event.error(Errors.REJECTED_BY_USER);
             LoginProtocol protocol = session.getProvider(LoginProtocol.class, clientSession.getAuthMethod());
@@ -358,14 +361,14 @@ public class LoginActionsService {
                 return authManager.nextActionAfterAuthentication(session, userSession, clientSession, clientConnection, request, uriInfo, event);
             case ACCOUNT_TEMPORARILY_DISABLED:
                 event.error(Errors.USER_TEMPORARILY_DISABLED);
-                return Flows.forms(this.session, realm, client, uriInfo, headers)
+                return session.getProvider(LoginFormsProvider.class)
                         .setError(Messages.ACCOUNT_TEMPORARILY_DISABLED)
                         .setFormData(formData)
                         .setClientSessionCode(clientCode.getCode())
                         .createLogin();
             case ACCOUNT_DISABLED:
                 event.error(Errors.USER_DISABLED);
-                return Flows.forms(this.session, realm, client, uriInfo, headers)
+                return session.getProvider(LoginFormsProvider.class)
                         .setError(Messages.ACCOUNT_DISABLED)
                         .setClientSessionCode(clientCode.getCode())
                         .setFormData(formData).createLogin();
@@ -375,19 +378,21 @@ public class LoginActionsService {
                 String passwordToken = new JWSBuilder().jsonContent(new PasswordToken(realm.getName(), user.getId())).rsa256(realm.getPrivateKey());
                 formData.add(CredentialRepresentation.PASSWORD_TOKEN, passwordToken);
 
-                return Flows.forms(this.session, realm, client, uriInfo, headers)
+                return session.getProvider(LoginFormsProvider.class)
                         .setFormData(formData)
                         .setClientSessionCode(clientCode.getCode())
                         .createLoginTotp();
             case INVALID_USER:
                 event.error(Errors.USER_NOT_FOUND);
-                return Flows.forms(this.session, realm, client, uriInfo, headers).setError(Messages.INVALID_USER)
+                return session.getProvider(LoginFormsProvider.class)
+                        .setError(Messages.INVALID_USER)
                         .setFormData(formData)
                         .setClientSessionCode(clientCode.getCode())
                         .createLogin();
             default:
                 event.error(Errors.INVALID_USER_CREDENTIALS);
-                return Flows.forms(this.session, realm, client, uriInfo, headers).setError(Messages.INVALID_USER)
+                return session.getProvider(LoginFormsProvider.class)
+                        .setError(Messages.INVALID_USER)
                         .setFormData(formData)
                         .setClientSessionCode(clientCode.getCode())
                         .createLogin();
@@ -409,25 +414,25 @@ public class LoginActionsService {
         event.event(EventType.REGISTER);
         if (!checkSsl()) {
             event.error(Errors.SSL_REQUIRED);
-            return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.HTTPS_REQUIRED);
+            return ErrorPage.error(session, Messages.HTTPS_REQUIRED);
         }
 
         if (!realm.isEnabled()) {
             event.error(Errors.REALM_DISABLED);
-            return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.REALM_NOT_ENABLED);
+            return ErrorPage.error(session, Messages.REALM_NOT_ENABLED);
         }
         if (!realm.isRegistrationAllowed()) {
             event.error(Errors.REGISTRATION_DISABLED);
-            return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.REGISTRATION_NOT_ALLOWED);
+            return ErrorPage.error(session, Messages.REGISTRATION_NOT_ALLOWED);
         }
         ClientSessionCode clientCode = ClientSessionCode.parse(code, session, realm);
         if (clientCode == null) {
             event.error(Errors.INVALID_CODE);
-            return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.UNKNOWN_CODE);
+            return ErrorPage.error(session, Messages.UNKNOWN_CODE);
         }
         if (!clientCode.isValid(ClientSessionModel.Action.AUTHENTICATE)) {
             event.error(Errors.INVALID_CODE);
-            return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_CODE);
+            return ErrorPage.error(session, Messages.INVALID_CODE);
         }
 
         String username = formData.getFirst(Validation.FIELD_USERNAME);
@@ -446,19 +451,20 @@ public class LoginActionsService {
 
         if (!realm.isEnabled()) {
             event.error(Errors.REALM_DISABLED);
-            return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.REALM_NOT_ENABLED);
+            return ErrorPage.error(session, Messages.REALM_NOT_ENABLED);
         }
         ClientModel client = clientSession.getClient();
         if (client == null) {
             event.error(Errors.CLIENT_NOT_FOUND);
-            return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.UNKNOWN_LOGIN_REQUESTER);
+            return ErrorPage.error(session, Messages.UNKNOWN_LOGIN_REQUESTER);
         }
 
         if (!client.isEnabled()) {
             event.error(Errors.CLIENT_DISABLED);
-            return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.LOGIN_REQUESTER_NOT_ENABLED);
+            return ErrorPage.error(session, Messages.LOGIN_REQUESTER_NOT_ENABLED);
         }
 
+        session.getContext().setClient(client);
 
         List<String> requiredCredentialTypes = new LinkedList<String>();
         for (RequiredCredentialModel m : realm.getRequiredCredentials()) {
@@ -470,7 +476,7 @@ public class LoginActionsService {
 
         if (errors != null && !errors.isEmpty()) {
             event.error(Errors.INVALID_REGISTRATION);
-            return Flows.forms(session, realm, client, uriInfo, headers)
+            return session.getProvider(LoginFormsProvider.class)
                     .setErrors(errors)
                     .setFormData(formData)
                     .setClientSessionCode(clientCode.getCode())
@@ -480,7 +486,7 @@ public class LoginActionsService {
         // Validate that user with this username doesn't exist in realm or any federation provider
         if (session.users().getUserByUsername(username, realm) != null) {
             event.error(Errors.USERNAME_IN_USE);
-            return Flows.forms(session, realm, client, uriInfo, headers)
+            return session.getProvider(LoginFormsProvider.class)
                     .setError(Messages.USERNAME_EXISTS)
                     .setFormData(formData)
                     .setClientSessionCode(clientCode.getCode())
@@ -490,7 +496,7 @@ public class LoginActionsService {
         // Validate that user with this email doesn't exist in realm or any federation provider
         if (email != null && session.users().getUserByEmail(email, realm) != null) {
             event.error(Errors.EMAIL_IN_USE);
-            return Flows.forms(session, realm, client, uriInfo, headers)
+            return session.getProvider(LoginFormsProvider.class)
                     .setError(Messages.EMAIL_EXISTS)
                     .setFormData(formData)
                     .setClientSessionCode(clientCode.getCode())
@@ -527,7 +533,7 @@ public class LoginActionsService {
             // User already registered, but force him to update password
             if (!passwordUpdateSuccessful) {
                 user.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
-                return Flows.forms(session, realm, client, uriInfo, headers)
+                return session.getProvider(LoginFormsProvider.class)
                         .setError(passwordUpdateError, passwordUpdateErrorParameters)
                         .setClientSessionCode(clientCode.getCode())
                         .createResponse(UserModel.RequiredAction.UPDATE_PASSWORD);
@@ -556,7 +562,7 @@ public class LoginActionsService {
 
 
         if (!checkSsl()) {
-            return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.HTTPS_REQUIRED);
+            return ErrorPage.error(session, Messages.HTTPS_REQUIRED);
         }
 
         String code = formData.getFirst("code");
@@ -564,7 +570,7 @@ public class LoginActionsService {
         ClientSessionCode accessCode = ClientSessionCode.parse(code, session, realm);
         if (accessCode == null || !accessCode.isValid(ClientSessionModel.Action.OAUTH_GRANT)) {
             event.error(Errors.INVALID_CODE);
-            return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.INVALID_ACCESS_CODE);
+            return ErrorPage.error(session, Messages.INVALID_ACCESS_CODE);
         }
         ClientSessionModel clientSession = accessCode.getClientSession();
         event.detail(Details.CODE_ID, clientSession.getId());
@@ -588,7 +594,7 @@ public class LoginActionsService {
         if (!AuthenticationManager.isSessionValid(realm, userSession)) {
             AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers);
             event.error(Errors.INVALID_CODE);
-            return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.SESSION_NOT_ACTIVE);
+            return ErrorPage.error(session, Messages.SESSION_NOT_ACTIVE);
         }
         event.session(userSession);
 
@@ -625,8 +631,10 @@ public class LoginActionsService {
 
         List<FormMessage> errors = Validation.validateUpdateProfileForm(formData);
         if (errors != null && !errors.isEmpty()) {
-            return Flows.forms(session, realm, null, uriInfo, headers).setUser(user).setErrors(errors)
+            return session.getProvider(LoginFormsProvider.class)
                     .setClientSessionCode(accessCode.getCode())
+                    .setUser(user)
+                    .setErrors(errors)
                     .createResponse(RequiredAction.UPDATE_PROFILE);
         }
 
@@ -643,7 +651,9 @@ public class LoginActionsService {
 
             // check for duplicated email
             if (userByEmail != null && !userByEmail.getId().equals(user.getId())) {
-                return Flows.forms(session, realm, null, uriInfo, headers).setUser(user).setError(Messages.EMAIL_EXISTS)
+                return session.getProvider(LoginFormsProvider.class)
+                        .setUser(user)
+                        .setError(Messages.EMAIL_EXISTS)
                         .setClientSessionCode(accessCode.getCode())
                         .createResponse(RequiredAction.UPDATE_PROFILE);
             }
@@ -682,7 +692,7 @@ public class LoginActionsService {
         String totp = formData.getFirst("totp");
         String totpSecret = formData.getFirst("totpSecret");
 
-        LoginFormsProvider loginForms = Flows.forms(session, realm, null, uriInfo, headers).setUser(user);
+        LoginFormsProvider loginForms = session.getProvider(LoginFormsProvider.class).setUser(user);
         if (Validation.isEmpty(totp)) {
             return loginForms.setError(Messages.MISSING_TOTP)
                     .setClientSessionCode(accessCode.getCode())
@@ -727,7 +737,8 @@ public class LoginActionsService {
         String passwordNew = formData.getFirst("password-new");
         String passwordConfirm = formData.getFirst("password-confirm");
 
-        LoginFormsProvider loginForms = Flows.forms(session, realm, null, uriInfo, headers).setUser(user);
+        LoginFormsProvider loginForms = session.getProvider(LoginFormsProvider.class)
+                .setUser(user);
         if (Validation.isEmpty(passwordNew)) {
             return loginForms.setError(Messages.MISSING_PASSWORD)
                     .setClientSessionCode(accessCode.getCode())
@@ -757,7 +768,9 @@ public class LoginActionsService {
         if (clientSession.getAction().equals(ClientSessionModel.Action.RECOVER_PASSWORD)) {
             String actionCookieValue = getActionCookie();
             if (actionCookieValue == null || !actionCookieValue.equals(userSession.getId())) {
-                return Flows.forms(session, realm, clientSession.getClient(), uriInfo, headers).setSuccess(Messages.ACCOUNT_PASSWORD_UPDATED).createInfoPage();
+                return session.getProvider(LoginFormsProvider.class)
+                        .setSuccess(Messages.ACCOUNT_PASSWORD_UPDATED)
+                        .createInfoPage();
             }
         }
 
@@ -789,7 +802,9 @@ public class LoginActionsService {
 
             String actionCookieValue = getActionCookie();
             if (actionCookieValue == null || !actionCookieValue.equals(userSession.getId())) {
-                return Flows.forms(session, realm, clientSession.getClient(), uriInfo, headers).setSuccess(Messages.EMAIL_VERIFIED).createInfoPage();
+                return session.getProvider(LoginFormsProvider.class)
+                        .setSuccess(Messages.EMAIL_VERIFIED)
+                        .createInfoPage();
             }
 
             event = event.clone().removeDetail(Details.EMAIL).event(EventType.LOGIN);
@@ -807,7 +822,7 @@ public class LoginActionsService {
 
             createActionCookie(realm, uriInfo, clientConnection, userSession.getId());
 
-            return Flows.forms(session, realm, null, uriInfo, headers)
+            return session.getProvider(LoginFormsProvider.class)
                     .setClientSessionCode(accessCode.getCode())
                     .setUser(userSession.getUser())
                     .createResponse(RequiredAction.VERIFY_EMAIL);
@@ -824,11 +839,11 @@ public class LoginActionsService {
                 return checks.response;
             }
             ClientSessionCode accessCode = checks.clientCode;
-            return Flows.forms(session, realm, null, uriInfo, headers)
+            return session.getProvider(LoginFormsProvider.class)
                     .setClientSessionCode(accessCode.getCode())
                     .createResponse(RequiredAction.UPDATE_PASSWORD);
         } else {
-            return Flows.forms(session, realm, null, uriInfo, headers)
+            return session.getProvider(LoginFormsProvider.class)
                     .setClientSessionCode(code)
                     .createPasswordReset();
         }
@@ -841,16 +856,16 @@ public class LoginActionsService {
                                       final MultivaluedMap<String, String> formData) {
         event.event(EventType.SEND_RESET_PASSWORD);
         if (!checkSsl()) {
-            return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.HTTPS_REQUIRED);
+            return ErrorPage.error(session, Messages.HTTPS_REQUIRED);
         }
         if (!realm.isEnabled()) {
             event.error(Errors.REALM_DISABLED);
-            return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.REALM_NOT_ENABLED);
+            return ErrorPage.error(session, Messages.REALM_NOT_ENABLED);
         }
         ClientSessionCode accessCode = ClientSessionCode.parse(code, session, realm);
         if (accessCode == null) {
             event.error(Errors.INVALID_CODE);
-            return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.UNKNOWN_CODE);
+            return ErrorPage.error(session, Messages.UNKNOWN_CODE);
         }
         ClientSessionModel clientSession = accessCode.getClientSession();
 
@@ -858,12 +873,14 @@ public class LoginActionsService {
 
         ClientModel client = clientSession.getClient();
         if (client == null) {
-            return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.UNKNOWN_LOGIN_REQUESTER);
+            return ErrorPage.error(session, Messages.UNKNOWN_LOGIN_REQUESTER);
         }
         if (!client.isEnabled()) {
-            return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.LOGIN_REQUESTER_NOT_ENABLED);
+            return ErrorPage.error(session, Messages.LOGIN_REQUESTER_NOT_ENABLED);
         }
 
+        session.getContext().setClient(client);
+
         event.client(client.getClientId())
                 .detail(Details.REDIRECT_URI, clientSession.getRedirectUri())
                 .detail(Details.RESPONSE_TYPE, "code")
@@ -904,7 +921,8 @@ public class LoginActionsService {
             } catch (EmailException e) {
                 event.error(Errors.EMAIL_SEND_FAILED);
                 logger.error("Failed to send password reset email", e);
-                return Flows.forms(this.session, realm, client, uriInfo, headers).setError(Messages.EMAIL_SENT_ERROR)
+                return session.getProvider(LoginFormsProvider.class)
+                        .setError(Messages.EMAIL_SENT_ERROR)
                         .setClientSessionCode(accessCode.getCode())
                         .createErrorPage();
             }
@@ -912,7 +930,10 @@ public class LoginActionsService {
             createActionCookie(realm, uriInfo, clientConnection, userSession.getId());
         }
 
-        return Flows.forms(session, realm, client,  uriInfo, headers).setSuccess(Messages.EMAIL_SENT).setClientSessionCode(accessCode.getCode()).createPasswordReset();
+        return session.getProvider(LoginFormsProvider.class)
+                .setSuccess(Messages.EMAIL_SENT)
+                .setClientSessionCode(accessCode.getCode())
+                .createPasswordReset();
     }
 
     private String getActionCookie() {
diff --git a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
index 571f111..b3dd570 100755
--- a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
@@ -24,7 +24,6 @@ import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Context;
-import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriBuilder;
@@ -39,17 +38,6 @@ public class RealmsResource {
     protected static Logger logger = Logger.getLogger(RealmsResource.class);
 
     @Context
-    protected UriInfo uriInfo;
-
-    @Context
-    protected HttpHeaders headers;
-
-    /*
-    @Context
-    protected ResourceContext resourceContext;
-    */
-
-    @Context
     protected KeycloakSession session;
 
     @Context
@@ -62,18 +50,10 @@ public class RealmsResource {
         return uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(RealmsResource.class, "getRealmResource");
     }
 
-    public static UriBuilder realmBaseUrl(UriBuilder base) {
-        return base.path(RealmsResource.class).path(RealmsResource.class, "getRealmResource");
-    }
-
     public static UriBuilder accountUrl(UriBuilder base) {
         return base.path(RealmsResource.class).path(RealmsResource.class, "getAccountService");
     }
 
-    public static UriBuilder protocolUrl(UriBuilder base) {
-        return base.path(RealmsResource.class).path(RealmsResource.class, "getProtocol");
-    }
-
     public static UriBuilder protocolUrl(UriInfo uriInfo) {
         return uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(RealmsResource.class, "getProtocol");
     }
@@ -87,9 +67,8 @@ public class RealmsResource {
     public Object getLoginStatusIframe(final @PathParam("realm") String name,
                                        @QueryParam("client_id") String client_id,
                                        @QueryParam("origin") String origin) {
-        // backward compatibility
-        RealmManager realmManager = new RealmManager(session);
-        RealmModel realm = locateRealm(name, realmManager);
+        RealmModel realm = init(name);
+
         EventBuilder event = new EventBuilder(realm, session, clientConnection);
         AuthenticationManager authManager = new AuthenticationManager(protector);
 
@@ -104,8 +83,8 @@ public class RealmsResource {
     @Path("{realm}/protocol/{protocol}")
     public Object getProtocol(final @PathParam("realm") String name,
                                             final @PathParam("protocol") String protocol) {
-        RealmManager realmManager = new RealmManager(session);
-        RealmModel realm = locateRealm(name, realmManager);
+        RealmModel realm = init(name);
+
         EventBuilder event = new EventBuilder(realm, session, clientConnection);
         AuthenticationManager authManager = new AuthenticationManager(protector);
 
@@ -125,8 +104,7 @@ public class RealmsResource {
 
     @Path("{realm}/login-actions")
     public LoginActionsService getLoginActionsService(final @PathParam("realm") String name) {
-        RealmManager realmManager = new RealmManager(session);
-        RealmModel realm = locateRealm(name, realmManager);
+        RealmModel realm = init(name);
         EventBuilder event = new EventBuilder(realm, session, clientConnection);
         AuthenticationManager authManager = new AuthenticationManager(protector);
         LoginActionsService service = new LoginActionsService(realm, authManager, event);
@@ -136,26 +114,26 @@ public class RealmsResource {
 
     @Path("{realm}/clients-managements")
     public ClientsManagementService getClientsManagementService(final @PathParam("realm") String name) {
-        RealmManager realmManager = new RealmManager(session);
-        RealmModel realm = locateRealm(name, realmManager);
+        RealmModel realm = init(name);
         EventBuilder event = new EventBuilder(realm, session, clientConnection);
         ClientsManagementService service = new ClientsManagementService(realm, event);
         ResteasyProviderFactory.getInstance().injectProperties(service);
         return service;
     }
 
-    protected RealmModel locateRealm(String name, RealmManager realmManager) {
-        RealmModel realm = realmManager.getRealmByName(name);
+    private RealmModel init(String realmName) {
+        RealmManager realmManager = new RealmManager(session);
+        RealmModel realm = realmManager.getRealmByName(realmName);
         if (realm == null) {
             throw new NotFoundException("Realm does not exist");
         }
+        session.getContext().setRealm(realm);
         return realm;
     }
 
     @Path("{realm}/account")
     public AccountService getAccountService(final @PathParam("realm") String name) {
-        RealmManager realmManager = new RealmManager(session);
-        RealmModel realm = locateRealm(name, realmManager);
+        RealmModel realm = init(name);
 
         ClientModel client = realm.getClientNameMap().get(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
         if (client == null || !client.isEnabled()) {
@@ -172,8 +150,7 @@ public class RealmsResource {
 
     @Path("{realm}")
     public PublicRealmResource getRealmResource(final @PathParam("realm") String name) {
-        RealmManager realmManager = new RealmManager(session);
-        RealmModel realm = locateRealm(name, realmManager);
+        RealmModel realm = init(name);
         PublicRealmResource realmResource = new PublicRealmResource(realm);
         ResteasyProviderFactory.getInstance().injectProperties(realmResource);
         return realmResource;
@@ -181,8 +158,7 @@ public class RealmsResource {
 
     @Path("{realm}/broker")
     public IdentityBrokerService getBrokerService(final @PathParam("realm") String name) {
-        RealmManager realmManager = new RealmManager(session);
-        RealmModel realm = locateRealm(name, realmManager);
+        RealmModel realm = init(name);
 
         IdentityBrokerService brokerService = new IdentityBrokerService(realm);
         ResteasyProviderFactory.getInstance().injectProperties(brokerService);
@@ -195,12 +171,12 @@ public class RealmsResource {
     @GET
     @Path("{realm}/.well-known/{provider}")
     @Produces(MediaType.APPLICATION_JSON)
-    public Response getWellKnown(final @PathParam("realm") String realmName,
+    public Response getWellKnown(final @PathParam("realm") String name,
                               final @PathParam("provider") String providerName) {
-        RealmManager realmManager = new RealmManager(session);
-        RealmModel realm = locateRealm(realmName, realmManager);
+        init(name);
+
         WellKnownProvider wellKnown = session.getProvider(WellKnownProvider.class, providerName);
-        return Response.ok(wellKnown.getConfig(realm, uriInfo)).build();
+        return Response.ok(wellKnown.getConfig()).build();
     }
 
 }
diff --git a/services/src/main/java/org/keycloak/wellknown/WellKnownProvider.java b/services/src/main/java/org/keycloak/wellknown/WellKnownProvider.java
index d4b80d7..ed9021f 100755
--- a/services/src/main/java/org/keycloak/wellknown/WellKnownProvider.java
+++ b/services/src/main/java/org/keycloak/wellknown/WellKnownProvider.java
@@ -1,16 +1,12 @@
 package org.keycloak.wellknown;
 
-import org.keycloak.models.RealmModel;
 import org.keycloak.provider.Provider;
 
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
 public interface WellKnownProvider extends Provider {
 
-    Object getConfig(RealmModel realm, UriInfo uriInfo);
+    Object getConfig();
 
 }
diff --git a/social/twitter/src/main/java/org/keycloak/social/twitter/TwitterIdentityProvider.java b/social/twitter/src/main/java/org/keycloak/social/twitter/TwitterIdentityProvider.java
index fea19e9..9d1d411 100755
--- a/social/twitter/src/main/java/org/keycloak/social/twitter/TwitterIdentityProvider.java
+++ b/social/twitter/src/main/java/org/keycloak/social/twitter/TwitterIdentityProvider.java
@@ -37,7 +37,7 @@ import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.services.managers.ClientSessionCode;
 import org.keycloak.services.messages.Messages;
-import org.keycloak.services.resources.flows.Flows;
+import org.keycloak.services.ErrorPage;
 import org.keycloak.social.SocialIdentityProvider;
 import twitter4j.Twitter;
 import twitter4j.TwitterFactory;
@@ -158,7 +158,7 @@ public class TwitterIdentityProvider extends AbstractIdentityProvider<OAuth2Iden
             EventBuilder event = new EventBuilder(realm, session, clientConnection);
             event.event(EventType.LOGIN);
             event.error("twitter_login_failed");
-            return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.UNEXPECTED_ERROR_HANDLING_RESPONSE);
+            return ErrorPage.error(session, Messages.UNEXPECTED_ERROR_HANDLING_RESPONSE);
         }
 
         private ClientSessionCode parseClientSessionCode(String code) {
diff --git a/testsuite/integration/pom.xml b/testsuite/integration/pom.xml
index 2cefe1b..8aa46ca 100755
--- a/testsuite/integration/pom.xml
+++ b/testsuite/integration/pom.xml
@@ -44,6 +44,11 @@
             <version>${project.version}</version>
         </dependency>
         <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>event-listener-sysout-example</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
             <groupId>log4j</groupId>
             <artifactId>log4j</artifactId>
         </dependency>
diff --git a/testsuite/integration/src/main/resources/log4j.properties b/testsuite/integration/src/main/resources/log4j.properties
index cfd1259..d94d2f9 100755
--- a/testsuite/integration/src/main/resources/log4j.properties
+++ b/testsuite/integration/src/main/resources/log4j.properties
@@ -6,6 +6,9 @@ log4j.appender.stdout.layout.ConversionPattern=%d{HH:mm:ss,SSS} %-5p [%c] %m%n
 
 log4j.logger.org.keycloak=info
 
+# Enable to view events
+# log4j.logger.org.keycloak.events=debug
+
 # Enable to view loaded SPI and Providers
 # log4j.logger.org.keycloak.services.DefaultKeycloakSessionFactory=debug
 # log4j.logger.org.keycloak.provider.ProviderManager=debug
diff --git a/testsuite/integration/src/main/resources/META-INF/keycloak-server.json b/testsuite/integration/src/main/resources/META-INF/keycloak-server.json
index 188db1e..2c56c58 100755
--- a/testsuite/integration/src/main/resources/META-INF/keycloak-server.json
+++ b/testsuite/integration/src/main/resources/META-INF/keycloak-server.json
@@ -7,6 +7,13 @@
         "provider": "${keycloak.eventStore.provider:jpa}"
     },
 
+    "eventsListener": {
+        "jboss-logging" : {
+            "success-level": "debug",
+            "error-level": "warn"
+        }
+    },
+
     "realm": {
         "provider": "${keycloak.realm.provider:jpa}"
     },
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java
index 9026ebc..ea06aac 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java
@@ -38,7 +38,7 @@ import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.UserModel.RequiredAction;
 import org.keycloak.representations.IDToken;
-import org.keycloak.services.resources.flows.Urls;
+import org.keycloak.services.Urls;
 import org.keycloak.testsuite.OAuthClient;
 import org.keycloak.testsuite.OAuthClient.AccessTokenResponse;
 import org.keycloak.testsuite.broker.util.UserSessionStatusServlet.UserSessionStatus;
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AccountFederatedIdentityPage.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AccountFederatedIdentityPage.java
index 2e3556e..4c02798 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AccountFederatedIdentityPage.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AccountFederatedIdentityPage.java
@@ -2,7 +2,7 @@ package org.keycloak.testsuite.pages;
 
 import javax.ws.rs.core.UriBuilder;
 
-import org.keycloak.services.resources.flows.Urls;
+import org.keycloak.services.Urls;
 import org.keycloak.testsuite.Constants;
 import org.openqa.selenium.By;
 
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AccountLogPage.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AccountLogPage.java
index 846b526..2a7c307 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AccountLogPage.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AccountLogPage.java
@@ -21,7 +21,7 @@
  */
 package org.keycloak.testsuite.pages;
 
-import org.keycloak.services.resources.flows.Urls;
+import org.keycloak.services.Urls;
 import org.keycloak.testsuite.Constants;
 import org.openqa.selenium.By;
 import org.openqa.selenium.WebElement;
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AccountSessionsPage.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AccountSessionsPage.java
index 5467a48..bfadc6d 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AccountSessionsPage.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AccountSessionsPage.java
@@ -21,7 +21,7 @@
  */
 package org.keycloak.testsuite.pages;
 
-import org.keycloak.services.resources.flows.Urls;
+import org.keycloak.services.Urls;
 import org.keycloak.testsuite.Constants;
 import org.openqa.selenium.By;
 import org.openqa.selenium.WebElement;
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/LoginPage.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/LoginPage.java
index 1f0b7a2..2be207c 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/LoginPage.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/LoginPage.java
@@ -103,11 +103,6 @@ public class LoginPage extends AbstractPage {
         return loginErrorMessage != null ? loginErrorMessage.getText() : null;
     }
 
-    public String getWarning() {
-        return loginWarningMessage != null ? loginWarningMessage.getText() : null;
-    }
-
-
     public boolean isCurrent() {
         return driver.getTitle().equals("Log in to test") || driver.getTitle().equals("Anmeldung bei test");
     }