From da703aa44983a36287d29eda1c6e8820dbb3815e Mon Sep 17 00:00:00 2001 From: Rob Winch Date: Wed, 29 May 2024 17:24:39 -0500 Subject: [PATCH] Add property to stop filter chain after successful authentication Closes gh-96 Closes gh-97 --- .../SpnegoAuthenticationProcessingFilter.java | 19 ++++++- ...egoAuthenticationProcessingFilterTest.java | 52 +++++++++++++------ 2 files changed, 54 insertions(+), 17 deletions(-) diff --git a/spring-security-kerberos-web/src/main/java/org/springframework/security/kerberos/web/authentication/SpnegoAuthenticationProcessingFilter.java b/spring-security-kerberos-web/src/main/java/org/springframework/security/kerberos/web/authentication/SpnegoAuthenticationProcessingFilter.java index 352a823..c914b43 100644 --- a/spring-security-kerberos-web/src/main/java/org/springframework/security/kerberos/web/authentication/SpnegoAuthenticationProcessingFilter.java +++ b/spring-security-kerberos-web/src/main/java/org/springframework/security/kerberos/web/authentication/SpnegoAuthenticationProcessingFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -100,6 +100,7 @@ * * @author Mike Wiesner * @author Jeremy Stone + * @author Denis Angilella * @since 1.0 * @see KerberosServiceAuthenticationProvider * @see SpnegoEntryPoint @@ -112,6 +113,7 @@ public class SpnegoAuthenticationProcessingFilter extends OncePerRequestFilter { private AuthenticationFailureHandler failureHandler; private SessionAuthenticationStrategy sessionStrategy = new NullAuthenticatedSessionStrategy(); private boolean skipIfAlreadyAuthenticated = true; + private boolean stopFilterChainOnSuccessfulAuthentication = false; /** * Authentication header prefix sent by IE/Windows when the domain controller fails to issue a Kerberos @@ -166,7 +168,9 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse if (successHandler != null) { successHandler.onAuthenticationSuccess(request, response, authentication); } - + if (stopFilterChainOnSuccessfulAuthentication) { + return; + } } chain.doFilter(request, response); @@ -249,4 +253,15 @@ public void setAuthenticationDetailsSource( this.authenticationDetailsSource = authenticationDetailsSource; } + /** + * If set to {@code false} (the default) and authentication is successful, the request will be processed by + * the next filter in the chain. If {@code true} and authentication is successful, the filter chain will stop here. + * + * @since 1.0.2 + * @param shouldStop set to {@code true} to prevent the next filter in the chain from processing the request + * after a successful authentication. + */ + public void setStopFilterChainOnSuccessfulAuthentication(boolean shouldStop) { + this.stopFilterChainOnSuccessfulAuthentication = shouldStop; + } } diff --git a/spring-security-kerberos-web/src/test/java/org/springframework/security/kerberos/web/SpnegoAuthenticationProcessingFilterTest.java b/spring-security-kerberos-web/src/test/java/org/springframework/security/kerberos/web/SpnegoAuthenticationProcessingFilterTest.java index 3088b73..59ba062 100644 --- a/spring-security-kerberos-web/src/test/java/org/springframework/security/kerberos/web/SpnegoAuthenticationProcessingFilterTest.java +++ b/spring-security-kerberos-web/src/test/java/org/springframework/security/kerberos/web/SpnegoAuthenticationProcessingFilterTest.java @@ -133,23 +133,24 @@ public void testEverythingWorksWithHandlers_Kerberos() throws Exception { private void everythingWorksWithHandlers(String tokenPrefix) throws Exception { createHandler(); everythingWorks(tokenPrefix); - verify(successHandler).onAuthenticationSuccess(request, response, AUTHENTICATION); - verify(failureHandler, never()).onAuthenticationFailure(any(HttpServletRequest.class), + everythingWorksVerifyHandlers(); + } + + private void everythingWorksVerifyHandlers() throws Exception { + verify(successHandler).onAuthenticationSuccess(request, response, AUTHENTICATION); + verify(failureHandler, never()).onAuthenticationFailure(any(HttpServletRequest.class), any(HttpServletResponse.class), any(AuthenticationException.class)); } private void everythingWorks(String tokenPrefix) throws IOException, ServletException { // stubbing - when(request.getHeader(HEADER)).thenReturn(tokenPrefix + TEST_TOKEN_BASE64); - KerberosServiceRequestToken requestToken = new KerberosServiceRequestToken(TEST_TOKEN); - requestToken.setDetails(detailsSource.buildDetails(request)); - when(authenticationManager.authenticate(requestToken)).thenReturn(AUTHENTICATION); + everythingWorksStub(tokenPrefix); // testing - filter.doFilter(request, response, chain); - verify(chain).doFilter(request, response); - assertEquals(AUTHENTICATION, SecurityContextHolder.getContext().getAuthentication()); + filter.doFilter(request, response, chain); + verify(chain).doFilter(request, response); + assertEquals(AUTHENTICATION, SecurityContextHolder.getContext().getAuthentication()); } @Test @@ -184,12 +185,12 @@ public void testAuthenticationFails() throws Exception { @Test public void testAuthenticationFailsWithHandlers() throws Exception { - createHandler(); - authenticationFails(); - verify(failureHandler).onAuthenticationFailure(request, response, BCE); - verify(successHandler, never()).onAuthenticationSuccess(any(HttpServletRequest.class), - any(HttpServletResponse.class), any(Authentication.class)); - verify(response, never()).setStatus(anyInt()); + createHandler(); + authenticationFails(); + verify(failureHandler).onAuthenticationFailure(request, response, BCE); + verify(successHandler, never()).onAuthenticationSuccess(any(HttpServletRequest.class), + any(HttpServletResponse.class), any(Authentication.class)); + verify(response, never()).setStatus(anyInt()); } @Test @@ -248,6 +249,27 @@ public void testAlreadyAuthenticatedNotActive() throws Exception { } } + @Test + public void testEverythingWorksWithHandlers_stopFilterChain() throws Exception { + filter.setStopFilterChainOnSuccessfulAuthentication(true); + + createHandler(); + everythingWorksStub(TOKEN_PREFIX_NEG); + + // testing + filter.doFilter(request, response, chain); + verify(chain, never()).doFilter(request, response); + assertEquals(AUTHENTICATION, SecurityContextHolder.getContext().getAuthentication()); + everythingWorksVerifyHandlers(); + } + + private void everythingWorksStub(String tokenPrefix) throws IOException, ServletException { + when(request.getHeader(HEADER)).thenReturn(tokenPrefix + TEST_TOKEN_BASE64); + KerberosServiceRequestToken requestToken = new KerberosServiceRequestToken(TEST_TOKEN); + requestToken.setDetails(detailsSource.buildDetails(request)); + when(authenticationManager.authenticate(requestToken)).thenReturn(AUTHENTICATION); + } + private void authenticationFails() throws IOException, ServletException { // stubbing when(request.getHeader(HEADER)).thenReturn(TOKEN_PREFIX_NEG + TEST_TOKEN_BASE64);