KEYCLOAK-5753 fixed NPE thrown when using custom RequestMatcher

This commit is contained in:
Thomas Kuestermann 2017-10-26 12:38:22 +02:00 committed by Stian Thorgersen
parent e4a6ee19d1
commit bb900f9db8
2 changed files with 39 additions and 28 deletions

View file

@ -17,7 +17,16 @@
package org.keycloak.adapters.springsecurity.authentication; package org.keycloak.adapters.springsecurity.authentication;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.http.HttpHeaders; import org.apache.http.HttpHeaders;
import org.keycloak.adapters.AdapterDeploymentContext;
import org.keycloak.adapters.spi.HttpFacade;
import org.keycloak.adapters.springsecurity.facade.SimpleHttpFacade;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
@ -26,17 +35,6 @@ import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import org.keycloak.adapters.AdapterDeploymentContext;
import org.keycloak.adapters.spi.HttpFacade;
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
import org.keycloak.adapters.springsecurity.facade.SimpleHttpFacade;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/** /**
* Provides a Keycloak {@link AuthenticationEntryPoint authentication entry point}. Uses a * Provides a Keycloak {@link AuthenticationEntryPoint authentication entry point}. Uses a
* {@link RequestMatcher} to determine if the request is an interactive login request or a * {@link RequestMatcher} to determine if the request is an interactive login request or a
@ -62,15 +60,14 @@ public class KeycloakAuthenticationEntryPoint implements AuthenticationEntryPoin
private final RequestMatcher apiRequestMatcher; private final RequestMatcher apiRequestMatcher;
private String loginUri = DEFAULT_LOGIN_URI; private String loginUri = DEFAULT_LOGIN_URI;
private String realm = DEFAULT_REALM; private String realm = DEFAULT_REALM;
private AdapterDeploymentContext adapterDeploymentContext; private AdapterDeploymentContext adapterDeploymentContext;
/** /**
* Creates a new Keycloak authentication entry point. * Creates a new Keycloak authentication entry point.
*/ */
public KeycloakAuthenticationEntryPoint(AdapterDeploymentContext adapterDeploymentContext) { public KeycloakAuthenticationEntryPoint(AdapterDeploymentContext adapterDeploymentContext) {
this(DEFAULT_API_REQUEST_MATCHER); this(adapterDeploymentContext, DEFAULT_API_REQUEST_MATCHER);
this.adapterDeploymentContext = adapterDeploymentContext;
} }
/** /**
@ -80,14 +77,15 @@ public class KeycloakAuthenticationEntryPoint implements AuthenticationEntryPoin
* @param apiRequestMatcher the <code>RequestMatcher</code> to use to determine * @param apiRequestMatcher the <code>RequestMatcher</code> to use to determine
* if the current request is an API request or a browser request (required) * if the current request is an API request or a browser request (required)
*/ */
public KeycloakAuthenticationEntryPoint(RequestMatcher apiRequestMatcher) { public KeycloakAuthenticationEntryPoint(AdapterDeploymentContext adapterDeploymentContext, RequestMatcher apiRequestMatcher) {
Assert.notNull(apiRequestMatcher, "apiRequestMatcher required"); Assert.notNull(apiRequestMatcher, "apiRequestMatcher required");
Assert.notNull(adapterDeploymentContext, "adapterDeploymentContext required");
this.adapterDeploymentContext = adapterDeploymentContext;
this.apiRequestMatcher = apiRequestMatcher; this.apiRequestMatcher = apiRequestMatcher;
} }
@Override @Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
{
HttpFacade facade = new SimpleHttpFacade(request, response); HttpFacade facade = new SimpleHttpFacade(request, response);
if (apiRequestMatcher.matches(request) || adapterDeploymentContext.resolveDeployment(facade).isBearerOnly()) { if (apiRequestMatcher.matches(request) || adapterDeploymentContext.resolveDeployment(facade).isBearerOnly()) {
commenceUnauthorizedResponse(request, response); commenceUnauthorizedResponse(request, response);

View file

@ -17,25 +17,27 @@
package org.keycloak.adapters.springsecurity.authentication; package org.keycloak.adapters.springsecurity.authentication;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.apache.http.HttpHeaders; import org.apache.http.HttpHeaders;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.springframework.http.HttpStatus;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import static junit.framework.TestCase.assertNull;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import org.keycloak.adapters.AdapterDeploymentContext; import org.keycloak.adapters.AdapterDeploymentContext;
import org.keycloak.adapters.KeycloakDeployment; import org.keycloak.adapters.KeycloakDeployment;
import org.keycloak.adapters.spi.HttpFacade; import org.keycloak.adapters.spi.HttpFacade;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import org.mockito.Mock; import org.mockito.Mock;
import static org.mockito.Mockito.when;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.web.util.matcher.RequestMatcher;
/** /**
* Keycloak authentication entry point tests. * Keycloak authentication entry point tests.
@ -47,13 +49,16 @@ public class KeycloakAuthenticationEntryPointTest {
private MockHttpServletResponse response; private MockHttpServletResponse response;
@Mock @Mock
private ApplicationContext applicationContext; private ApplicationContext applicationContext;
@Mock @Mock
private AdapterDeploymentContext adapterDeploymentContext; private AdapterDeploymentContext adapterDeploymentContext;
@Mock @Mock
private KeycloakDeployment keycloakDeployment; private KeycloakDeployment keycloakDeployment;
@Mock
private RequestMatcher requestMatcher;
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
@ -101,6 +106,14 @@ public class KeycloakAuthenticationEntryPointTest {
assertEquals(logoutUri, response.getHeader("Location")); assertEquals(logoutUri, response.getHeader("Location"));
} }
@Test
public void testCommenceWithCustomRequestMatcher() throws Exception {
new KeycloakAuthenticationEntryPoint(adapterDeploymentContext, requestMatcher)
.commence(request, response, null);
verify(requestMatcher).matches(request);
}
private void configureBrowserRequest() { private void configureBrowserRequest() {
request.addHeader(HttpHeaders.ACCEPT, "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); request.addHeader(HttpHeaders.ACCEPT, "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
} }