diff --git a/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/filter/KeycloakAuthenticationProcessingFilter.java b/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/filter/KeycloakAuthenticationProcessingFilter.java index cf5f373fcf..67b950bb7b 100644 --- a/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/filter/KeycloakAuthenticationProcessingFilter.java +++ b/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/filter/KeycloakAuthenticationProcessingFilter.java @@ -144,17 +144,29 @@ public class KeycloakAuthenticationProcessingFilter extends AbstractAuthenticati return authValue != null && authValue.startsWith("Bearer"); } + /** + * Returns true if the request was made with a Basic authentication authorization header. + * + * @param request the current HttpServletRequest + * @return true if the request was made with a Basic authentication authorization header; + * false otherwise. + */ + protected boolean isBasicAuthRequest(HttpServletRequest request) { + String authValue = request.getHeader(AUTHORIZATION_HEADER); + return authValue != null && authValue.startsWith("Basic"); + } + @Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { - if (!this.isBearerTokenRequest(request)) { + if (!(this.isBearerTokenRequest(request) || this.isBasicAuthRequest(request))) { super.successfulAuthentication(request, response, chain, authResult); return; } if (log.isDebugEnabled()) { - log.debug("Authentication success using bearer token. Updating SecurityContextHolder to contain: {}", authResult); + log.debug("Authentication success using bearer token/basic authentication. Updating SecurityContextHolder to contain: {}", authResult); } SecurityContextHolder.getContext().setAuthentication(authResult); @@ -181,6 +193,11 @@ public class KeycloakAuthenticationProcessingFilter extends AbstractAuthenticati response.sendError(HttpServletResponse.SC_FORBIDDEN, "Unable to authenticate bearer token"); return; } + else if (this.isBasicAuthRequest(request)) { + SecurityContextHolder.clearContext(); + response.sendError(HttpServletResponse.SC_FORBIDDEN, "Unable to authenticate with basic authentication"); + return; + } super.unsuccessfulAuthentication(request, response, failed); } diff --git a/integration/spring-security/src/test/java/org/keycloak/adapters/springsecurity/filter/KeycloakAuthenticationProcessingFilterTest.java b/integration/spring-security/src/test/java/org/keycloak/adapters/springsecurity/filter/KeycloakAuthenticationProcessingFilterTest.java index 45420339db..034e212001 100644 --- a/integration/spring-security/src/test/java/org/keycloak/adapters/springsecurity/filter/KeycloakAuthenticationProcessingFilterTest.java +++ b/integration/spring-security/src/test/java/org/keycloak/adapters/springsecurity/filter/KeycloakAuthenticationProcessingFilterTest.java @@ -94,10 +94,17 @@ public class KeycloakAuthenticationProcessingFilterTest { @Test public void testIsBearerTokenRequest() throws Exception { assertFalse(filter.isBearerTokenRequest(request)); - this.setAuthHeader(request); + this.setBearerAuthHeader(request); assertTrue(filter.isBearerTokenRequest(request)); } + @Test + public void testIsBasicAuthRequest() throws Exception { + assertFalse(filter.isBasicAuthRequest(request)); + this.setBasicAuthHeader(request); + assertTrue(filter.isBasicAuthRequest(request)); + } + @Test public void testSuccessfulAuthenticationInteractive() throws Exception { Authentication authentication = new KeycloakAuthenticationToken(keycloakAccount, authorities); @@ -110,7 +117,18 @@ public class KeycloakAuthenticationProcessingFilterTest { @Test public void testSuccessfulAuthenticationBearer() throws Exception { Authentication authentication = new KeycloakAuthenticationToken(keycloakAccount, authorities); - this.setAuthHeader(request); + this.setBearerAuthHeader(request); + filter.successfulAuthentication(request, response, chain, authentication); + + verify(chain).doFilter(eq(request), eq(response)); + verify(successHandler, never()).onAuthenticationSuccess(any(HttpServletRequest.class), any(HttpServletResponse.class), + any(Authentication.class)); + } + + @Test + public void testSuccessfulAuthenticationBasicAuth() throws Exception { + Authentication authentication = new KeycloakAuthenticationToken(keycloakAccount, authorities); + this.setBasicAuthHeader(request); filter.successfulAuthentication(request, response, chain, authentication); verify(chain).doFilter(eq(request), eq(response)); @@ -128,7 +146,17 @@ public class KeycloakAuthenticationProcessingFilterTest { @Test public void testUnsuccessfulAuthenticatioBearer() throws Exception { AuthenticationException exception = new BadCredentialsException("OOPS"); - this.setAuthHeader(request); + this.setBearerAuthHeader(request); + filter.unsuccessfulAuthentication(request, response, exception); + verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), anyString()); + verify(failureHandler, never()).onAuthenticationFailure(any(HttpServletRequest.class), any(HttpServletResponse.class), + any(AuthenticationException.class)); + } + + @Test + public void testUnsuccessfulAuthenticatioBasicAuth() throws Exception { + AuthenticationException exception = new BadCredentialsException("OOPS"); + this.setBasicAuthHeader(request); filter.unsuccessfulAuthentication(request, response, exception); verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), anyString()); verify(failureHandler, never()).onAuthenticationFailure(any(HttpServletRequest.class), any(HttpServletResponse.class), @@ -145,8 +173,12 @@ public class KeycloakAuthenticationProcessingFilterTest { filter.setContinueChainBeforeSuccessfulAuthentication(true); } - private void setAuthHeader(MockHttpServletRequest request) { + private void setBearerAuthHeader(MockHttpServletRequest request) { request.addHeader(KeycloakAuthenticationProcessingFilter.AUTHORIZATION_HEADER, "Bearer " + UUID.randomUUID().toString()); } + private void setBasicAuthHeader(MockHttpServletRequest request) { + request.addHeader(KeycloakAuthenticationProcessingFilter.AUTHORIZATION_HEADER, "Basic " + UUID.randomUUID().toString()); + } + }