Skip to content

Commit

Permalink
Add property to stop filter chain after successful authentication
Browse files Browse the repository at this point in the history
Closes gh-96
Closes gh-97
  • Loading branch information
rwinch committed May 29, 2024
1 parent 50a77ae commit da703aa
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 17 deletions.
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -100,6 +100,7 @@
*
* @author Mike Wiesner
* @author Jeremy Stone
* @author Denis Angilella
* @since 1.0
* @see KerberosServiceAuthenticationProvider
* @see SpnegoEntryPoint
Expand All @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit da703aa

Please sign in to comment.