keycloak-uncached
Changes
integration/adapter-core/src/main/java/org/keycloak/adapters/BearerTokenRequestAuthenticator.java 10(+10 -0)
integration/adapter-core/src/main/java/org/keycloak/adapters/OAuthRequestAuthenticator.java 29(+25 -4)
integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/jbossweb/KeycloakAuthenticatorValve.java 13(+12 -1)
integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/AbstractKeycloakJettyAuthenticator.java 52(+40 -12)
integration/tomcat/tomcat6/src/main/java/org/keycloak/adapters/tomcat/KeycloakAuthenticatorValve.java 14(+13 -1)
integration/tomcat/tomcat7/src/main/java/org/keycloak/adapters/tomcat/KeycloakAuthenticatorValve.java 13(+12 -1)
integration/tomcat/tomcat8/pom.xml 13(+13 -0)
integration/tomcat/tomcat8/src/main/java/org/keycloak/adapters/tomcat/KeycloakAuthenticatorValve.java 34(+33 -1)
integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/AbstractKeycloakAuthenticatorValve.java 10(+9 -1)
integration/undertow/src/main/java/org/keycloak/adapters/undertow/AbstractUndertowKeycloakAuthMech.java 23(+22 -1)
integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakServletExtension.java 24(+17 -7)
integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthMech.java 38(+36 -2)
integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowAuthenticationMechanism.java 4(+2 -2)
integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyAuthenticationMechanism.java 4(+2 -2)
integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyKeycloakServletExtension.java 2(+1 -1)
testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java 3(+3 -0)
Details
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/AuthChallenge.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/AuthChallenge.java
index 4682808..10f960e 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/AuthChallenge.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/AuthChallenge.java
@@ -11,4 +11,11 @@ public interface AuthChallenge {
* @return challenge sent
*/
boolean challenge(HttpFacade exchange);
+
+ /**
+ * Whether or not an error page should be displayed if possible
+ *
+ * @return
+ */
+ boolean errorPage();
}
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/BearerTokenRequestAuthenticator.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/BearerTokenRequestAuthenticator.java
index ccbe596..81b1d42 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/BearerTokenRequestAuthenticator.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/BearerTokenRequestAuthenticator.java
@@ -110,6 +110,11 @@ public class BearerTokenRequestAuthenticator {
protected AuthChallenge clientCertChallenge() {
return new AuthChallenge() {
@Override
+ public boolean errorPage() {
+ return false;
+ }
+
+ @Override
public boolean challenge(HttpFacade exchange) {
// do the same thing as client cert auth
return false;
@@ -130,6 +135,11 @@ public class BearerTokenRequestAuthenticator {
final String challenge = header.toString();
return new AuthChallenge() {
@Override
+ public boolean errorPage() {
+ return false;
+ }
+
+ @Override
public boolean challenge(HttpFacade facade) {
facade.getResponse().setStatus(401);
facade.getResponse().addHeader("WWW-Authenticate", challenge);
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/OAuthRequestAuthenticator.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/OAuthRequestAuthenticator.java
index f5451c8..d780f5d 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/OAuthRequestAuthenticator.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/OAuthRequestAuthenticator.java
@@ -146,13 +146,29 @@ public class OAuthRequestAuthenticator {
protected AuthChallenge loginRedirect() {
final String state = getStateCode();
final String redirect = getRedirectUri(state);
- return new AuthChallenge() {
- @Override
- public boolean challenge(HttpFacade exchange) {
- if (redirect == null) {
+ if (redirect == null) {
+ return new AuthChallenge() {
+ @Override
+ public boolean challenge(HttpFacade exchange) {
exchange.getResponse().setStatus(403);
return true;
}
+
+ @Override
+ public boolean errorPage() {
+ return true;
+ }
+ };
+ }
+ return new AuthChallenge() {
+
+ @Override
+ public boolean errorPage() {
+ return false;
+ }
+
+ @Override
+ public boolean challenge(HttpFacade exchange) {
tokenStore.saveRequest();
log.debug("Sending redirect to login page: " + redirect);
exchange.getResponse().setStatus(302);
@@ -219,6 +235,11 @@ public class OAuthRequestAuthenticator {
protected AuthChallenge challenge(final int code) {
return new AuthChallenge() {
@Override
+ public boolean errorPage() {
+ return true;
+ }
+
+ @Override
public boolean challenge(HttpFacade exchange) {
exchange.getResponse().setStatus(code);
return true;
diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/jbossweb/KeycloakAuthenticatorValve.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/jbossweb/KeycloakAuthenticatorValve.java
index 71e0f19..91cbb87 100755
--- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/jbossweb/KeycloakAuthenticatorValve.java
+++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/jbossweb/KeycloakAuthenticatorValve.java
@@ -11,6 +11,7 @@ import org.keycloak.adapters.tomcat.GenericPrincipalFactory;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
import java.security.Principal;
import java.util.List;
@@ -22,10 +23,20 @@ import java.util.List;
*/
public class KeycloakAuthenticatorValve extends AbstractKeycloakAuthenticatorValve {
public boolean authenticate(Request request, HttpServletResponse response, LoginConfig config) throws java.io.IOException {
- return authenticateInternal(request, response);
+ return authenticateInternal(request, response, config);
}
@Override
+ protected boolean forwardToErrorPageInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException {
+ if (loginConfig == null) return false;
+ LoginConfig config = (LoginConfig)loginConfig;
+ if (config.getErrorPage() == null) return false;
+ forwardToErrorPage(request, (Response)response, config);
+ return true;
+ }
+
+
+ @Override
public void start() throws LifecycleException {
StandardContext standardContext = (StandardContext) context;
standardContext.addLifecycleListener(this);
diff --git a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/AbstractKeycloakJettyAuthenticator.java b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/AbstractKeycloakJettyAuthenticator.java
index 2e78eed..fc01385 100755
--- a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/AbstractKeycloakJettyAuthenticator.java
+++ b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/AbstractKeycloakJettyAuthenticator.java
@@ -1,14 +1,18 @@
package org.keycloak.adapters.jetty;
+import org.apache.http.HttpVersion;
import org.eclipse.jetty.security.DefaultUserIdentity;
import org.eclipse.jetty.security.ServerAuthException;
import org.eclipse.jetty.security.UserAuthentication;
import org.eclipse.jetty.security.authentication.DeferredAuthentication;
+import org.eclipse.jetty.security.authentication.FormAuthenticator;
import org.eclipse.jetty.security.authentication.LoginAuthenticator;
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.util.URIUtil;
import org.jboss.logging.Logger;
import org.keycloak.KeycloakPrincipal;
import org.keycloak.KeycloakSecurityContext;
@@ -37,6 +41,7 @@ import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
+import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Set;
@@ -52,6 +57,7 @@ public abstract class AbstractKeycloakJettyAuthenticator extends LoginAuthentica
protected NodesRegistrationManagement nodesRegistrationManagement;
protected AdapterConfig adapterConfig;
protected KeycloakConfigResolver configResolver;
+ protected String errorPage;
public AbstractKeycloakJettyAuthenticator() {
super();
@@ -66,7 +72,7 @@ public abstract class AbstractKeycloakJettyAuthenticator extends LoginAuthentica
}
public AdapterTokenStore getTokenStore(Request request, HttpFacade facade, KeycloakDeployment resolvedDeployment) {
- AdapterTokenStore store = (AdapterTokenStore)request.getAttribute(TOKEN_STORE_NOTE);
+ AdapterTokenStore store = (AdapterTokenStore) request.getAttribute(TOKEN_STORE_NOTE);
if (store != null) {
return store;
}
@@ -84,8 +90,8 @@ public abstract class AbstractKeycloakJettyAuthenticator extends LoginAuthentica
public abstract AdapterTokenStore createSessionTokenStore(Request request, KeycloakDeployment resolvedDeployment);
public void logoutCurrent(Request request) {
- AdapterDeploymentContext deploymentContext = (AdapterDeploymentContext)request.getAttribute(AdapterDeploymentContext.class.getName());
- KeycloakSecurityContext ksc = (KeycloakSecurityContext)request.getAttribute(KeycloakSecurityContext.class.getName());
+ AdapterDeploymentContext deploymentContext = (AdapterDeploymentContext) request.getAttribute(AdapterDeploymentContext.class.getName());
+ KeycloakSecurityContext ksc = (KeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName());
if (ksc != null) {
JettyHttpFacade facade = new JettyHttpFacade(request, null);
KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
@@ -115,11 +121,25 @@ public abstract class AbstractKeycloakJettyAuthenticator extends LoginAuthentica
public void setConfiguration(AuthConfiguration configuration) {
//super.setConfiguration(configuration);
initializeKeycloak();
+ String error = configuration.getInitParameter(FormAuthenticator.__FORM_ERROR_PAGE);
+ setErrorPage(error);
+ }
+
+ private void setErrorPage(String path) {
+ if (path == null || path.trim().length() == 0) {
+ } else {
+ if (!path.startsWith("/")) {
+ path = "/" + path;
+ }
+ errorPage = path;
+
+ if (errorPage.indexOf('?') > 0)
+ errorPage = errorPage.substring(0, errorPage.indexOf('?'));
+ }
}
@Override
- public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, Authentication.User validatedUser) throws ServerAuthException
- {
+ public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, Authentication.User validatedUser) throws ServerAuthException {
return true;
}
@@ -167,12 +187,13 @@ public abstract class AbstractKeycloakJettyAuthenticator extends LoginAuthentica
InputStream configInputStream = getConfigInputStream(theServletContext);
if (configInputStream != null) {
deploymentContext = new AdapterDeploymentContext(KeycloakDeploymentBuilder.build(configInputStream));
- }
+ }
}
if (deploymentContext == null) {
deploymentContext = new AdapterDeploymentContext(new KeycloakDeployment());
}
- if (theServletContext != null) theServletContext.setAttribute(AdapterDeploymentContext.class.getName(), deploymentContext);
+ if (theServletContext != null)
+ theServletContext.setAttribute(AdapterDeploymentContext.class.getName(), deploymentContext);
}
private InputStream getConfigInputStream(ServletContext servletContext) {
@@ -198,7 +219,7 @@ public abstract class AbstractKeycloakJettyAuthenticator extends LoginAuthentica
log.trace("*** authenticate");
}
Request request = resolveRequest(req);
- JettyHttpFacade facade = new JettyHttpFacade(request, (HttpServletResponse)res);
+ JettyHttpFacade facade = new JettyHttpFacade(request, (HttpServletResponse) res);
KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
if (deployment == null || !deployment.isConfigured()) {
log.debug("*** deployment isn't configured return false");
@@ -231,17 +252,25 @@ public abstract class AbstractKeycloakJettyAuthenticator extends LoginAuthentica
}
AuthChallenge challenge = authenticator.getChallenge();
if (challenge != null) {
+ if (challenge.errorPage() && errorPage != null) {
+ Response response = (Response)res;
+ try {
+ response.sendRedirect(response.encodeRedirectURL(URIUtil.addPaths(request.getContextPath(), errorPage)));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ }
challenge.challenge(facade);
}
return Authentication.SEND_CONTINUE;
}
-
protected abstract Request resolveRequest(ServletRequest req);
protected JettyRequestAuthenticator createRequestAuthenticator(Request request, JettyHttpFacade facade,
- KeycloakDeployment deployment, AdapterTokenStore tokenStore) {
+ KeycloakDeployment deployment, AdapterTokenStore tokenStore) {
return new JettyRequestAuthenticator(facade, deployment, tokenStore, -1, request);
}
@@ -263,8 +292,7 @@ public abstract class AbstractKeycloakJettyAuthenticator extends LoginAuthentica
protected abstract Authentication createAuthentication(UserIdentity userIdentity);
- public static abstract class KeycloakAuthentication extends UserAuthentication
- {
+ public static abstract class KeycloakAuthentication extends UserAuthentication {
public KeycloakAuthentication(String method, UserIdentity userIdentity) {
super(method, userIdentity);
}
diff --git a/integration/tomcat/tomcat6/src/main/java/org/keycloak/adapters/tomcat/KeycloakAuthenticatorValve.java b/integration/tomcat/tomcat6/src/main/java/org/keycloak/adapters/tomcat/KeycloakAuthenticatorValve.java
index fa6ac80..5dc7701 100755
--- a/integration/tomcat/tomcat6/src/main/java/org/keycloak/adapters/tomcat/KeycloakAuthenticatorValve.java
+++ b/integration/tomcat/tomcat6/src/main/java/org/keycloak/adapters/tomcat/KeycloakAuthenticatorValve.java
@@ -8,6 +8,8 @@ import org.apache.catalina.deploy.LoginConfig;
import org.apache.catalina.realm.GenericPrincipal;
import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
import java.security.Principal;
import java.util.List;
@@ -20,10 +22,20 @@ import java.util.List;
public class KeycloakAuthenticatorValve extends AbstractKeycloakAuthenticatorValve {
@Override
public boolean authenticate(Request request, Response response, LoginConfig config) throws java.io.IOException {
- return authenticateInternal(request, response);
+ return authenticateInternal(request, response, config);
}
@Override
+ protected boolean forwardToErrorPageInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException {
+ if (loginConfig == null) return false;
+ LoginConfig config = (LoginConfig)loginConfig;
+ if (config.getErrorPage() == null) return false;
+ forwardToErrorPage(request, (Response)response, config);
+ return true;
+ }
+
+
+ @Override
public void start() throws LifecycleException {
StandardContext standardContext = (StandardContext) context;
standardContext.addLifecycleListener(this);
diff --git a/integration/tomcat/tomcat7/src/main/java/org/keycloak/adapters/tomcat/KeycloakAuthenticatorValve.java b/integration/tomcat/tomcat7/src/main/java/org/keycloak/adapters/tomcat/KeycloakAuthenticatorValve.java
index 700378e..45402e6 100755
--- a/integration/tomcat/tomcat7/src/main/java/org/keycloak/adapters/tomcat/KeycloakAuthenticatorValve.java
+++ b/integration/tomcat/tomcat7/src/main/java/org/keycloak/adapters/tomcat/KeycloakAuthenticatorValve.java
@@ -1,6 +1,7 @@
package org.keycloak.adapters.tomcat;
import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.deploy.LoginConfig;
import org.apache.catalina.realm.GenericPrincipal;
@@ -19,9 +20,19 @@ import java.util.List;
*/
public class KeycloakAuthenticatorValve extends AbstractKeycloakAuthenticatorValve {
public boolean authenticate(Request request, HttpServletResponse response, LoginConfig config) throws IOException {
- return authenticateInternal(request, response);
+ return authenticateInternal(request, response, config);
}
+ @Override
+ protected boolean forwardToErrorPageInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException {
+ if (loginConfig == null) return false;
+ LoginConfig config = (LoginConfig)loginConfig;
+ if (config.getErrorPage() == null) return false;
+ forwardToErrorPage(request, (Response)response, config);
+ return true;
+ }
+
+
protected void initInternal() {
StandardContext standardContext = (StandardContext) context;
standardContext.addLifecycleListener(this);
integration/tomcat/tomcat8/pom.xml 13(+13 -0)
diff --git a/integration/tomcat/tomcat8/pom.xml b/integration/tomcat/tomcat8/pom.xml
index 8e9eb1b..f503a66 100755
--- a/integration/tomcat/tomcat8/pom.xml
+++ b/integration/tomcat/tomcat8/pom.xml
@@ -33,6 +33,19 @@
<version>${project.version}</version>
</dependency>
<dependency>
+ <groupId>org.apache.tomcat</groupId>
+ <artifactId>tomcat-servlet-api</artifactId>
+ <version>${tomcat.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomcat</groupId>
+ <artifactId>tomcat-catalina</artifactId>
+ <version>${tomcat.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-tomcat-core-adapter</artifactId>
<version>${project.version}</version>
diff --git a/integration/tomcat/tomcat8/src/main/java/org/keycloak/adapters/tomcat/KeycloakAuthenticatorValve.java b/integration/tomcat/tomcat8/src/main/java/org/keycloak/adapters/tomcat/KeycloakAuthenticatorValve.java
index 9812c3d..f390fe7 100755
--- a/integration/tomcat/tomcat8/src/main/java/org/keycloak/adapters/tomcat/KeycloakAuthenticatorValve.java
+++ b/integration/tomcat/tomcat8/src/main/java/org/keycloak/adapters/tomcat/KeycloakAuthenticatorValve.java
@@ -1,12 +1,19 @@
package org.keycloak.adapters.tomcat;
+import org.apache.catalina.authenticator.FormAuthenticator;
import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.realm.GenericPrincipal;
+import org.apache.tomcat.util.ExceptionUtils;
+import org.apache.tomcat.util.descriptor.web.LoginConfig;
+import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.security.Principal;
import java.util.List;
@@ -18,7 +25,32 @@ import java.util.List;
*/
public class KeycloakAuthenticatorValve extends AbstractKeycloakAuthenticatorValve {
public boolean authenticate(Request request, HttpServletResponse response) throws IOException {
- return authenticateInternal(request, response);
+ return authenticateInternal(request, response, request.getContext().getLoginConfig());
+ }
+
+ @Override
+ protected boolean forwardToErrorPageInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException {
+ if (loginConfig == null) return false;
+ LoginConfig config = (LoginConfig)loginConfig;
+ if (config.getErrorPage() == null) return false;
+ // had to do this to get around compiler/IDE issues :(
+ try {
+ Method method = null;
+ /*
+ for (Method m : getClass().getDeclaredMethods()) {
+ if (m.getName().equals("forwardToErrorPage")) {
+ method = m;
+ break;
+ }
+ }
+ */
+ method = FormAuthenticator.class.getDeclaredMethod("forwardToErrorPage", Request.class, HttpServletResponse.class, LoginConfig.class);
+ method.setAccessible(true);
+ method.invoke(this, request, response, config);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ return true;
}
protected void initInternal() {
diff --git a/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/AbstractKeycloakAuthenticatorValve.java b/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/AbstractKeycloakAuthenticatorValve.java
index acf33a4..ffc5941 100755
--- a/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/AbstractKeycloakAuthenticatorValve.java
+++ b/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/AbstractKeycloakAuthenticatorValve.java
@@ -10,6 +10,7 @@ import org.apache.catalina.authenticator.FormAuthenticator;
import org.apache.catalina.authenticator.SavedRequest;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
+import org.apache.catalina.deploy.LoginConfig;
import org.apache.tomcat.util.buf.ByteChunk;
import org.keycloak.KeycloakSecurityContext;
import org.keycloak.constants.AdapterConstants;
@@ -175,8 +176,9 @@ public abstract class AbstractKeycloakAuthenticatorValve extends FormAuthenticat
}
protected abstract GenericPrincipalFactory createPrincipalFactory();
+ protected abstract boolean forwardToErrorPageInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException;
- protected boolean authenticateInternal(Request request, HttpServletResponse response) {
+ protected boolean authenticateInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException {
CatalinaHttpFacade facade = new CatalinaHttpFacade(request, response);
KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
if (deployment == null || !deployment.isConfigured()) {
@@ -196,6 +198,12 @@ public abstract class AbstractKeycloakAuthenticatorValve extends FormAuthenticat
}
AuthChallenge challenge = authenticator.getChallenge();
if (challenge != null) {
+ if (loginConfig == null) {
+ loginConfig = request.getContext().getLoginConfig();
+ }
+ if (challenge.errorPage()) {
+ if (forwardToErrorPageInternal(request, response, loginConfig))return false;
+ }
challenge.challenge(facade);
}
return false;
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/AbstractUndertowKeycloakAuthMech.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/AbstractUndertowKeycloakAuthMech.java
index 9a35896..892343b 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/AbstractUndertowKeycloakAuthMech.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/AbstractUndertowKeycloakAuthMech.java
@@ -23,7 +23,9 @@ import io.undertow.security.api.SecurityNotification;
import io.undertow.server.HttpServerExchange;
import io.undertow.server.session.Session;
import io.undertow.util.AttachmentKey;
+import io.undertow.util.Headers;
import io.undertow.util.Sessions;
+import io.undertow.util.StatusCodes;
import org.keycloak.KeycloakPrincipal;
import org.keycloak.KeycloakSecurityContext;
import org.keycloak.adapters.AdapterDeploymentContext;
@@ -46,16 +48,22 @@ public abstract class AbstractUndertowKeycloakAuthMech implements Authentication
public static final AttachmentKey<AuthChallenge> KEYCLOAK_CHALLENGE_ATTACHMENT_KEY = AttachmentKey.create(AuthChallenge.class);
protected AdapterDeploymentContext deploymentContext;
protected UndertowUserSessionManagement sessionManagement;
+ protected String errorPage;
- public AbstractUndertowKeycloakAuthMech(AdapterDeploymentContext deploymentContext, UndertowUserSessionManagement sessionManagement) {
+ public AbstractUndertowKeycloakAuthMech(AdapterDeploymentContext deploymentContext, UndertowUserSessionManagement sessionManagement, String errorPage) {
this.deploymentContext = deploymentContext;
this.sessionManagement = sessionManagement;
+ this.errorPage = errorPage;
}
@Override
public ChallengeResult sendChallenge(HttpServerExchange exchange, SecurityContext securityContext) {
AuthChallenge challenge = exchange.getAttachment(KEYCLOAK_CHALLENGE_ATTACHMENT_KEY);
if (challenge != null) {
+ if (challenge.errorPage() && errorPage != null) {
+ Integer code = servePage(exchange, errorPage);
+ return new ChallengeResult(true, code);
+ }
UndertowHttpFacade facade = new UndertowHttpFacade(exchange);
if (challenge.challenge(facade)) {
return new ChallengeResult(true, exchange.getResponseCode());
@@ -64,6 +72,19 @@ public abstract class AbstractUndertowKeycloakAuthMech implements Authentication
return new ChallengeResult(false);
}
+ protected Integer servePage(final HttpServerExchange exchange, final String location) {
+ sendRedirect(exchange, location);
+ return StatusCodes.TEMPORARY_REDIRECT;
+ }
+
+ static void sendRedirect(final HttpServerExchange exchange, final String location) {
+ // TODO - String concatenation to construct URLS is extremely error prone - switch to a URI which will better handle this.
+ String loc = exchange.getRequestScheme() + "://" + exchange.getHostAndPort() + location;
+ exchange.getResponseHeaders().put(Headers.LOCATION, loc);
+ }
+
+
+
protected void registerNotifications(final SecurityContext securityContext) {
final NotificationReceiver logoutReceiver = new NotificationReceiver() {
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakServletExtension.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakServletExtension.java
index 4014a92..0258621 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakServletExtension.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakServletExtension.java
@@ -32,11 +32,12 @@ import io.undertow.servlet.api.LoginConfig;
import io.undertow.servlet.api.ServletSessionConfig;
import io.undertow.servlet.util.ImmediateInstanceHandle;
import org.jboss.logging.Logger;
-import org.keycloak.constants.AdapterConstants;
import org.keycloak.adapters.AdapterDeploymentContext;
+import org.keycloak.adapters.KeycloakConfigResolver;
import org.keycloak.adapters.KeycloakDeployment;
import org.keycloak.adapters.KeycloakDeploymentBuilder;
import org.keycloak.adapters.NodesRegistrationManagement;
+import org.keycloak.constants.AdapterConstants;
import javax.servlet.ServletContext;
import java.io.ByteArrayInputStream;
@@ -44,7 +45,6 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Map;
-import org.keycloak.adapters.KeycloakConfigResolver;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -57,9 +57,9 @@ public class KeycloakServletExtension implements ServletExtension {
// todo when this DeploymentInfo method of the same name is fixed.
public boolean isAuthenticationMechanismPresent(DeploymentInfo deploymentInfo, final String mechanismName) {
LoginConfig loginConfig = deploymentInfo.getLoginConfig();
- if(loginConfig != null) {
- for(AuthMethodConfig method : loginConfig.getAuthMethods()) {
- if(method.getName().equalsIgnoreCase(mechanismName)) {
+ if (loginConfig != null) {
+ for (AuthMethodConfig method : loginConfig.getAuthMethods()) {
+ if (method.getName().equalsIgnoreCase(mechanismName)) {
return true;
}
}
@@ -191,7 +191,17 @@ public class KeycloakServletExtension implements ServletExtension {
protected ServletKeycloakAuthMech createAuthenticationMechanism(DeploymentInfo deploymentInfo, AdapterDeploymentContext deploymentContext, UndertowUserSessionManagement userSessionManagement,
NodesRegistrationManagement nodesRegistrationManagement) {
- log.debug("creating ServletKeycloakAuthMech");
- return new ServletKeycloakAuthMech(deploymentContext, userSessionManagement, nodesRegistrationManagement, deploymentInfo.getConfidentialPortManager());
+ log.debug("creating ServletKeycloakAuthMech");
+ String errorPage = getErrorPage(deploymentInfo);
+ return new ServletKeycloakAuthMech(deploymentContext, userSessionManagement, nodesRegistrationManagement, deploymentInfo.getConfidentialPortManager(), errorPage);
+ }
+
+ protected String getErrorPage(DeploymentInfo deploymentInfo) {
+ LoginConfig loginConfig = deploymentInfo.getLoginConfig();
+ String errorPage = null;
+ if (loginConfig != null) {
+ errorPage = loginConfig.getErrorPage();
+ }
+ return errorPage;
}
}
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthMech.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthMech.java
index 0ae5b6e..144210f 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthMech.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthMech.java
@@ -16,18 +16,28 @@
*/
package org.keycloak.adapters.undertow;
+import io.undertow.security.api.AuthenticationMechanism;
import io.undertow.security.api.SecurityContext;
import io.undertow.server.HttpServerExchange;
import io.undertow.servlet.api.ConfidentialPortManager;
+import io.undertow.servlet.handlers.ServletRequestContext;
+import io.undertow.util.Headers;
import org.jboss.logging.Logger;
import org.keycloak.adapters.AdapterDeploymentContext;
import org.keycloak.adapters.AdapterTokenStore;
+import org.keycloak.adapters.AuthChallenge;
import org.keycloak.adapters.HttpFacade;
import org.keycloak.adapters.KeycloakDeployment;
import org.keycloak.adapters.NodesRegistrationManagement;
import org.keycloak.adapters.RequestAuthenticator;
import org.keycloak.enums.TokenStore;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import java.io.IOException;
+
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
@@ -39,13 +49,37 @@ public class ServletKeycloakAuthMech extends AbstractUndertowKeycloakAuthMech {
protected NodesRegistrationManagement nodesRegistrationManagement;
protected ConfidentialPortManager portManager;
- public ServletKeycloakAuthMech(AdapterDeploymentContext deploymentContext, UndertowUserSessionManagement userSessionManagement, NodesRegistrationManagement nodesRegistrationManagement, ConfidentialPortManager portManager) {
- super(deploymentContext, userSessionManagement);
+ public ServletKeycloakAuthMech(AdapterDeploymentContext deploymentContext, UndertowUserSessionManagement userSessionManagement,
+ NodesRegistrationManagement nodesRegistrationManagement, ConfidentialPortManager portManager,
+ String errorPage) {
+ super(deploymentContext, userSessionManagement, errorPage);
this.nodesRegistrationManagement = nodesRegistrationManagement;
this.portManager = portManager;
}
@Override
+ protected Integer servePage(HttpServerExchange exchange, String location) {
+ final ServletRequestContext servletRequestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
+ ServletRequest req = servletRequestContext.getServletRequest();
+ ServletResponse resp = servletRequestContext.getServletResponse();
+ RequestDispatcher disp = req.getRequestDispatcher(location);
+ //make sure the login page is never cached
+ exchange.getResponseHeaders().add(Headers.CACHE_CONTROL, "no-cache, no-store, must-revalidate");
+ exchange.getResponseHeaders().add(Headers.PRAGMA, "no-cache");
+ exchange.getResponseHeaders().add(Headers.EXPIRES, "0");
+
+
+ try {
+ disp.forward(req, resp);
+ } catch (ServletException e) {
+ throw new RuntimeException(e);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return null;
+ }
+
+ @Override
public AuthenticationMechanismOutcome authenticate(HttpServerExchange exchange, SecurityContext securityContext) {
UndertowHttpFacade facade = new UndertowHttpFacade(exchange);
KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowAuthenticationMechanism.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowAuthenticationMechanism.java
index 057fc50..b408255 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowAuthenticationMechanism.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowAuthenticationMechanism.java
@@ -17,8 +17,8 @@ public class UndertowAuthenticationMechanism extends AbstractUndertowKeycloakAut
protected int confidentialPort;
public UndertowAuthenticationMechanism(AdapterDeploymentContext deploymentContext, UndertowUserSessionManagement sessionManagement,
- NodesRegistrationManagement nodesRegistrationManagement, int confidentialPort) {
- super(deploymentContext, sessionManagement);
+ NodesRegistrationManagement nodesRegistrationManagement, int confidentialPort, String errorPage) {
+ super(deploymentContext, sessionManagement, errorPage);
this.nodesRegistrationManagement = nodesRegistrationManagement;
this.confidentialPort = confidentialPort;
}
diff --git a/integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyAuthenticationMechanism.java b/integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyAuthenticationMechanism.java
index 6880d66..85f8bd3 100755
--- a/integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyAuthenticationMechanism.java
+++ b/integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyAuthenticationMechanism.java
@@ -21,8 +21,8 @@ public class WildflyAuthenticationMechanism extends ServletKeycloakAuthMech {
public WildflyAuthenticationMechanism(AdapterDeploymentContext deploymentContext,
UndertowUserSessionManagement userSessionManagement,
NodesRegistrationManagement nodesRegistrationManagement,
- ConfidentialPortManager portManager) {
- super(deploymentContext, userSessionManagement, nodesRegistrationManagement, portManager);
+ ConfidentialPortManager portManager, String errorPage) {
+ super(deploymentContext, userSessionManagement, nodesRegistrationManagement, portManager, errorPage);
}
@Override
diff --git a/integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyKeycloakServletExtension.java b/integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyKeycloakServletExtension.java
index 0cdf2f9..2e43285 100755
--- a/integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyKeycloakServletExtension.java
+++ b/integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyKeycloakServletExtension.java
@@ -19,7 +19,7 @@ public class WildflyKeycloakServletExtension extends KeycloakServletExtension {
protected ServletKeycloakAuthMech createAuthenticationMechanism(DeploymentInfo deploymentInfo, AdapterDeploymentContext deploymentContext,
UndertowUserSessionManagement userSessionManagement, NodesRegistrationManagement nodesRegistrationManagement) {
log.debug("creating WildflyAuthenticationMechanism");
- return new WildflyAuthenticationMechanism(deploymentContext, userSessionManagement, nodesRegistrationManagement, deploymentInfo.getConfidentialPortManager());
+ return new WildflyAuthenticationMechanism(deploymentContext, userSessionManagement, nodesRegistrationManagement, deploymentInfo.getConfidentialPortManager(), getErrorPage(deploymentInfo));
}
}
diff --git a/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyServerBuilder.java b/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyServerBuilder.java
index 8835856..59977e6 100755
--- a/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyServerBuilder.java
+++ b/proxy/proxy-server/src/main/java/org/keycloak/proxy/ProxyServerBuilder.java
@@ -229,7 +229,7 @@ public class ProxyServerBuilder {
handler = new ConstraintMatcherHandler(matches, handler, toWrap, errorPage);
final List<AuthenticationMechanism> mechanisms = new LinkedList<AuthenticationMechanism>();
mechanisms.add(new CachedAuthenticatedSessionMechanism());
- mechanisms.add(new UndertowAuthenticationMechanism(deploymentContext, userSessionManagement, nodesRegistrationManagement, -1));
+ mechanisms.add(new UndertowAuthenticationMechanism(deploymentContext, userSessionManagement, nodesRegistrationManagement, -1, null));
handler = new AuthenticationMechanismsHandler(handler, mechanisms);
IdentityManager identityManager = new IdentityManager() {
@Override
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java
index 49b1a6d..6ff9df2 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java
@@ -224,6 +224,9 @@ public class AdapterTestStrategy extends ExternalResource {
Assert.assertTrue(driver.getCurrentUrl().startsWith(LOGIN_URL));
driver.navigate().to(APP_SERVER_BASE_URL + "/customer-portal");
Assert.assertTrue(driver.getCurrentUrl().startsWith(LOGIN_URL));
+ loginPage.cancel();
+ System.out.println(driver.getPageSource());
+ Assert.assertTrue(driver.getPageSource().contains("Error Page"));
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java
index d618567..0603751 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java
@@ -5,6 +5,7 @@ import io.undertow.servlet.api.DeploymentInfo;
import io.undertow.servlet.api.FilterInfo;
import io.undertow.servlet.api.LoginConfig;
import io.undertow.servlet.api.SecurityConstraint;
+import io.undertow.servlet.api.SecurityInfo;
import io.undertow.servlet.api.ServletInfo;
import io.undertow.servlet.api.WebResourceCollection;
import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer;
@@ -126,6 +127,7 @@ public abstract class AbstractKeycloakRule extends ExternalResource {
server.getServer().deploy(deploymentInfo);
}
+
private DeploymentInfo createDeploymentInfo(String name, String contextPath, Class<? extends Servlet> servletClass) {
DeploymentInfo deploymentInfo = new DeploymentInfo();
deploymentInfo.setClassLoader(getClass().getClassLoader());
@@ -168,11 +170,25 @@ public abstract class AbstractKeycloakRule extends ExternalResource {
constraint.addRoleAllowed(role);
di.addSecurityConstraint(constraint);
}
- LoginConfig loginConfig = new LoginConfig("KEYCLOAK", "demo");
+ LoginConfig loginConfig = new LoginConfig("KEYCLOAK", "demo", null, "/error.html");
di.setLoginConfig(loginConfig);
+ addErrorPage(di);
+
server.getServer().deploy(di);
}
+ public void addErrorPage(DeploymentInfo di) {
+ ServletInfo servlet = new ServletInfo("Error Page", ErrorServlet.class);
+ servlet.addMapping("/error.html");
+ SecurityConstraint constraint = new SecurityConstraint();
+ WebResourceCollection collection = new WebResourceCollection();
+ collection.addUrlPattern("/error.html");
+ constraint.addWebResourceCollection(collection);
+ constraint.setEmptyRoleSemantic(SecurityInfo.EmptyRoleSemantic.PERMIT);
+ di.addSecurityConstraint(constraint);
+ di.addServlet(servlet);
+ }
+
public void deployJaxrsApplication(String name, String contextPath, Class<? extends Application> applicationClass, Map<String,String> initParams) {
ResteasyDeployment deployment = new ResteasyDeployment();
deployment.setApplicationClass(applicationClass.getName());
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/ErrorServlet.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/ErrorServlet.java
new file mode 100755
index 0000000..1f8534d
--- /dev/null
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/ErrorServlet.java
@@ -0,0 +1,28 @@
+package org.keycloak.testsuite.rule;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class ErrorServlet extends HttpServlet {
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+
+
+ resp.setContentType("text/html");
+ PrintWriter pw = resp.getWriter();
+ pw.printf("<html><head><title>%s</title></head><body>", "Error Page");
+ pw.print("<h1>There was an error</h1></body></html>");
+ pw.flush();
+
+
+ }
+}
diff --git a/testsuite/jetty/jetty81/src/test/resources/adapter-test/customer-portal/WEB-INF/web.xml b/testsuite/jetty/jetty81/src/test/resources/adapter-test/customer-portal/WEB-INF/web.xml
index 19acca0..f96add7 100755
--- a/testsuite/jetty/jetty81/src/test/resources/adapter-test/customer-portal/WEB-INF/web.xml
+++ b/testsuite/jetty/jetty81/src/test/resources/adapter-test/customer-portal/WEB-INF/web.xml
@@ -10,12 +10,21 @@
<servlet-name>Servlet</servlet-name>
<servlet-class>org.keycloak.testsuite.adapter.CustomerServlet</servlet-class>
</servlet>
+ <servlet>
+ <servlet-name>Error Servlet</servlet-name>
+ <servlet-class>org.keycloak.testsuite.rule.ErrorServlet</servlet-class>
+ </servlet>
<servlet-mapping>
<servlet-name>Servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>Error Servlet</servlet-name>
+ <url-pattern>/error.html</url-pattern>
+ </servlet-mapping>
+
<security-constraint>
<web-resource-collection>
<web-resource-name>Users</web-resource-name>
@@ -25,12 +34,23 @@
<role-name>user</role-name>
</auth-constraint>
</security-constraint>
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>Errors</web-resource-name>
+ <url-pattern>/error.html</url-pattern>
+ </web-resource-collection>
+ </security-constraint>
<login-config>
- <auth-method>BASIC</auth-method>
+ <auth-method>FORM</auth-method>
<realm-name>demo</realm-name>
+ <form-login-config>
+ <form-login-page>/error.html</form-login-page>
+ <form-error-page>/error.html</form-error-page>
+ </form-login-config>
</login-config>
+♦
<security-role>
<role-name>admin</role-name>
</security-role>
diff --git a/testsuite/jetty/jetty91/src/test/resources/adapter-test/customer-portal/WEB-INF/web.xml b/testsuite/jetty/jetty91/src/test/resources/adapter-test/customer-portal/WEB-INF/web.xml
index 19acca0..cce0616 100755
--- a/testsuite/jetty/jetty91/src/test/resources/adapter-test/customer-portal/WEB-INF/web.xml
+++ b/testsuite/jetty/jetty91/src/test/resources/adapter-test/customer-portal/WEB-INF/web.xml
@@ -10,12 +10,21 @@
<servlet-name>Servlet</servlet-name>
<servlet-class>org.keycloak.testsuite.adapter.CustomerServlet</servlet-class>
</servlet>
+ <servlet>
+ <servlet-name>Error Servlet</servlet-name>
+ <servlet-class>org.keycloak.testsuite.rule.ErrorServlet</servlet-class>
+ </servlet>
<servlet-mapping>
<servlet-name>Servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>Error Servlet</servlet-name>
+ <url-pattern>/error.html</url-pattern>
+ </servlet-mapping>
+
<security-constraint>
<web-resource-collection>
<web-resource-name>Users</web-resource-name>
@@ -25,10 +34,20 @@
<role-name>user</role-name>
</auth-constraint>
</security-constraint>
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>Errors</web-resource-name>
+ <url-pattern>/error.html</url-pattern>
+ </web-resource-collection>
+ </security-constraint>
<login-config>
- <auth-method>BASIC</auth-method>
+ <auth-method>FORM</auth-method>
<realm-name>demo</realm-name>
+ <form-login-config>
+ <form-login-page>/error.html</form-login-page>
+ <form-error-page>/error.html</form-error-page>
+ </form-login-config>
</login-config>
<security-role>
diff --git a/testsuite/jetty/jetty92/src/test/resources/adapter-test/customer-portal/WEB-INF/web.xml b/testsuite/jetty/jetty92/src/test/resources/adapter-test/customer-portal/WEB-INF/web.xml
index 19acca0..cce0616 100755
--- a/testsuite/jetty/jetty92/src/test/resources/adapter-test/customer-portal/WEB-INF/web.xml
+++ b/testsuite/jetty/jetty92/src/test/resources/adapter-test/customer-portal/WEB-INF/web.xml
@@ -10,12 +10,21 @@
<servlet-name>Servlet</servlet-name>
<servlet-class>org.keycloak.testsuite.adapter.CustomerServlet</servlet-class>
</servlet>
+ <servlet>
+ <servlet-name>Error Servlet</servlet-name>
+ <servlet-class>org.keycloak.testsuite.rule.ErrorServlet</servlet-class>
+ </servlet>
<servlet-mapping>
<servlet-name>Servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>Error Servlet</servlet-name>
+ <url-pattern>/error.html</url-pattern>
+ </servlet-mapping>
+
<security-constraint>
<web-resource-collection>
<web-resource-name>Users</web-resource-name>
@@ -25,10 +34,20 @@
<role-name>user</role-name>
</auth-constraint>
</security-constraint>
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>Errors</web-resource-name>
+ <url-pattern>/error.html</url-pattern>
+ </web-resource-collection>
+ </security-constraint>
<login-config>
- <auth-method>BASIC</auth-method>
+ <auth-method>FORM</auth-method>
<realm-name>demo</realm-name>
+ <form-login-config>
+ <form-login-page>/error.html</form-login-page>
+ <form-error-page>/error.html</form-error-page>
+ </form-login-config>
</login-config>
<security-role>
diff --git a/testsuite/tomcat6/src/test/resources/adapter-test/customer-portal/WEB-INF/web.xml b/testsuite/tomcat6/src/test/resources/adapter-test/customer-portal/WEB-INF/web.xml
index 19acca0..9c211cb 100755
--- a/testsuite/tomcat6/src/test/resources/adapter-test/customer-portal/WEB-INF/web.xml
+++ b/testsuite/tomcat6/src/test/resources/adapter-test/customer-portal/WEB-INF/web.xml
@@ -10,12 +10,21 @@
<servlet-name>Servlet</servlet-name>
<servlet-class>org.keycloak.testsuite.adapter.CustomerServlet</servlet-class>
</servlet>
+ <servlet>
+ <servlet-name>Error Servlet</servlet-name>
+ <servlet-class>org.keycloak.testsuite.rule.ErrorServlet</servlet-class>
+ </servlet>
<servlet-mapping>
<servlet-name>Servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>Error Servlet</servlet-name>
+ <url-pattern>/error.html</url-pattern>
+ </servlet-mapping>
+
<security-constraint>
<web-resource-collection>
<web-resource-name>Users</web-resource-name>
@@ -25,10 +34,20 @@
<role-name>user</role-name>
</auth-constraint>
</security-constraint>
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>Errors</web-resource-name>
+ <url-pattern>/error.html</url-pattern>
+ </web-resource-collection>
+ </security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>demo</realm-name>
+ <form-login-config>
+ <form-login-page>/error.html</form-login-page>
+ <form-error-page>/error.html</form-error-page>
+ </form-login-config>
</login-config>
<security-role>
diff --git a/testsuite/tomcat7/src/test/resources/adapter-test/customer-portal/WEB-INF/web.xml b/testsuite/tomcat7/src/test/resources/adapter-test/customer-portal/WEB-INF/web.xml
index 19acca0..9c211cb 100755
--- a/testsuite/tomcat7/src/test/resources/adapter-test/customer-portal/WEB-INF/web.xml
+++ b/testsuite/tomcat7/src/test/resources/adapter-test/customer-portal/WEB-INF/web.xml
@@ -10,12 +10,21 @@
<servlet-name>Servlet</servlet-name>
<servlet-class>org.keycloak.testsuite.adapter.CustomerServlet</servlet-class>
</servlet>
+ <servlet>
+ <servlet-name>Error Servlet</servlet-name>
+ <servlet-class>org.keycloak.testsuite.rule.ErrorServlet</servlet-class>
+ </servlet>
<servlet-mapping>
<servlet-name>Servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>Error Servlet</servlet-name>
+ <url-pattern>/error.html</url-pattern>
+ </servlet-mapping>
+
<security-constraint>
<web-resource-collection>
<web-resource-name>Users</web-resource-name>
@@ -25,10 +34,20 @@
<role-name>user</role-name>
</auth-constraint>
</security-constraint>
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>Errors</web-resource-name>
+ <url-pattern>/error.html</url-pattern>
+ </web-resource-collection>
+ </security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>demo</realm-name>
+ <form-login-config>
+ <form-login-page>/error.html</form-login-page>
+ <form-error-page>/error.html</form-error-page>
+ </form-login-config>
</login-config>
<security-role>
diff --git a/testsuite/tomcat8/src/test/resources/adapter-test/customer-portal/WEB-INF/web.xml b/testsuite/tomcat8/src/test/resources/adapter-test/customer-portal/WEB-INF/web.xml
index 19acca0..9c211cb 100755
--- a/testsuite/tomcat8/src/test/resources/adapter-test/customer-portal/WEB-INF/web.xml
+++ b/testsuite/tomcat8/src/test/resources/adapter-test/customer-portal/WEB-INF/web.xml
@@ -10,12 +10,21 @@
<servlet-name>Servlet</servlet-name>
<servlet-class>org.keycloak.testsuite.adapter.CustomerServlet</servlet-class>
</servlet>
+ <servlet>
+ <servlet-name>Error Servlet</servlet-name>
+ <servlet-class>org.keycloak.testsuite.rule.ErrorServlet</servlet-class>
+ </servlet>
<servlet-mapping>
<servlet-name>Servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>Error Servlet</servlet-name>
+ <url-pattern>/error.html</url-pattern>
+ </servlet-mapping>
+
<security-constraint>
<web-resource-collection>
<web-resource-name>Users</web-resource-name>
@@ -25,10 +34,20 @@
<role-name>user</role-name>
</auth-constraint>
</security-constraint>
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>Errors</web-resource-name>
+ <url-pattern>/error.html</url-pattern>
+ </web-resource-collection>
+ </security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>demo</realm-name>
+ <form-login-config>
+ <form-login-page>/error.html</form-login-page>
+ <form-error-page>/error.html</form-error-page>
+ </form-login-config>
</login-config>
<security-role>