From 6b59c2f44c7b0a1df53e1077d60558bae8aacc8d Mon Sep 17 00:00:00 2001 From: Frank Schmager Date: Thu, 9 Aug 2018 15:45:01 -0400 Subject: [PATCH] try to register node during authentication attempt in filter * PreAuthActionsFilter registers deployment during authentication attempt to enable, well, node registration if filter is used by itself (if no securityConstraints when using spring boot and spring security) * deregistering node during clean shutdown * added unit test --- .../filter/KeycloakPreAuthActionsFilter.java | 27 +++++- .../KeycloakPreAuthActionsFilterTest.java | 90 +++++++++++++++++++ 2 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 adapters/oidc/spring-security/src/test/java/org/keycloak/adapters/springsecurity/filter/KeycloakPreAuthActionsFilterTest.java diff --git a/adapters/oidc/spring-security/src/main/java/org/keycloak/adapters/springsecurity/filter/KeycloakPreAuthActionsFilter.java b/adapters/oidc/spring-security/src/main/java/org/keycloak/adapters/springsecurity/filter/KeycloakPreAuthActionsFilter.java index fc79dd07a4..b239310c3e 100755 --- a/adapters/oidc/spring-security/src/main/java/org/keycloak/adapters/springsecurity/filter/KeycloakPreAuthActionsFilter.java +++ b/adapters/oidc/spring-security/src/main/java/org/keycloak/adapters/springsecurity/filter/KeycloakPreAuthActionsFilter.java @@ -48,10 +48,11 @@ public class KeycloakPreAuthActionsFilter extends GenericFilterBean implements A private static final Logger log = LoggerFactory.getLogger(KeycloakPreAuthActionsFilter.class); - private final NodesRegistrationManagement management = new NodesRegistrationManagement(); + private NodesRegistrationManagement nodesRegistrationManagement = new NodesRegistrationManagement(); private ApplicationContext applicationContext; private AdapterDeploymentContext deploymentContext; private UserSessionManagement userSessionManagement; + private PreAuthActionsHandlerFactory preAuthActionsHandlerFactory = new PreAuthActionsHandlerFactory(); public KeycloakPreAuthActionsFilter() { super(); @@ -69,7 +70,7 @@ public class KeycloakPreAuthActionsFilter extends GenericFilterBean implements A @Override public void destroy() { log.debug("Unregistering deployment"); - management.stop(); + nodesRegistrationManagement.stop(); } @Override @@ -77,7 +78,8 @@ public class KeycloakPreAuthActionsFilter extends GenericFilterBean implements A throws IOException, ServletException { HttpFacade facade = new SimpleHttpFacade((HttpServletRequest)request, (HttpServletResponse)response); - PreAuthActionsHandler handler = new PreAuthActionsHandler(userSessionManagement, deploymentContext, facade); + nodesRegistrationManagement.tryRegister(deploymentContext.resolveDeployment(facade)); + PreAuthActionsHandler handler = preAuthActionsHandlerFactory.createPreAuthActionsHandler(facade); if (handler.handleRequest()) { log.debug("Pre-auth filter handled request: {}", ((HttpServletRequest) request).getRequestURI()); } else { @@ -93,4 +95,23 @@ public class KeycloakPreAuthActionsFilter extends GenericFilterBean implements A public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } + + void setNodesRegistrationManagement(NodesRegistrationManagement nodesRegistrationManagement) { + this.nodesRegistrationManagement = nodesRegistrationManagement; + } + + void setPreAuthActionsHandlerFactory(PreAuthActionsHandlerFactory preAuthActionsHandlerFactory) { + this.preAuthActionsHandlerFactory = preAuthActionsHandlerFactory; + } + + /** + * Creates {@link PreAuthActionsHandler}s. + * + * Package-private class to enable mocking. + */ + class PreAuthActionsHandlerFactory { + PreAuthActionsHandler createPreAuthActionsHandler(HttpFacade facade) { + return new PreAuthActionsHandler(userSessionManagement, deploymentContext, facade); + } + } } diff --git a/adapters/oidc/spring-security/src/test/java/org/keycloak/adapters/springsecurity/filter/KeycloakPreAuthActionsFilterTest.java b/adapters/oidc/spring-security/src/test/java/org/keycloak/adapters/springsecurity/filter/KeycloakPreAuthActionsFilterTest.java new file mode 100644 index 0000000000..650febe74c --- /dev/null +++ b/adapters/oidc/spring-security/src/test/java/org/keycloak/adapters/springsecurity/filter/KeycloakPreAuthActionsFilterTest.java @@ -0,0 +1,90 @@ +package org.keycloak.adapters.springsecurity.filter; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.initMocks; + +import javax.servlet.FilterChain; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.keycloak.adapters.AdapterDeploymentContext; +import org.keycloak.adapters.KeycloakDeployment; +import org.keycloak.adapters.NodesRegistrationManagement; +import org.keycloak.adapters.PreAuthActionsHandler; +import org.keycloak.adapters.spi.HttpFacade; +import org.keycloak.adapters.spi.UserSessionManagement; +import org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.PreAuthActionsHandlerFactory; +import org.mockito.Mock; +import org.springframework.context.ApplicationContext; + +public class KeycloakPreAuthActionsFilterTest { + + private KeycloakPreAuthActionsFilter filter; + + @Mock + private NodesRegistrationManagement nodesRegistrationManagement; + @Mock + private ApplicationContext applicationContext; + @Mock + private AdapterDeploymentContext deploymentContext; + @Mock + private PreAuthActionsHandlerFactory preAuthActionsHandlerFactory; + @Mock + private UserSessionManagement userSessionManagement; + @Mock + private PreAuthActionsHandler preAuthActionsHandler; + @Mock + private KeycloakDeployment deployment; + + @Mock + private HttpServletRequest request; + @Mock + private HttpServletResponse response; + @Mock + private FilterChain chain; + + @Before + public void setUp() throws Exception { + initMocks(this); + filter = new KeycloakPreAuthActionsFilter(userSessionManagement); + filter.setNodesRegistrationManagement(nodesRegistrationManagement); + filter.setApplicationContext(applicationContext); + filter.setPreAuthActionsHandlerFactory(preAuthActionsHandlerFactory); + when(applicationContext.getBean(AdapterDeploymentContext.class)).thenReturn(deploymentContext); + when(deploymentContext.resolveDeployment(any(HttpFacade.class))).thenReturn(deployment); + when(preAuthActionsHandlerFactory.createPreAuthActionsHandler(any(HttpFacade.class))).thenReturn(preAuthActionsHandler); + filter.initFilterBean(); + } + + @Test + public void shouldIgnoreChainWhenPreAuthActionHandlerHandled() throws Exception { + when(preAuthActionsHandler.handleRequest()).thenReturn(true); + + filter.doFilter(request, response, chain); + + verifyZeroInteractions(chain); + verify(nodesRegistrationManagement).tryRegister(deployment); + } + + @Test + public void shouldContinueChainWhenPreAuthActionHandlerDidNotHandle() throws Exception { + when(preAuthActionsHandler.handleRequest()).thenReturn(false); + + filter.doFilter(request, response, chain); + + verify(chain).doFilter(request, response);; + verify(nodesRegistrationManagement).tryRegister(deployment); + } + + @After + public void tearDown() { + filter.destroy(); + verify(nodesRegistrationManagement).stop(); + } +}