DelegatingAuthenticationEntryPoint.Builder allows just defaultEntryPoint

Previously build threw an Exception when entryPoints was empty and
defaultEntryPoint was specified.

This commit changes build to return the defaultEntryPoint instead.

Closes gh-17955
This commit is contained in:
Rob Winch 2025-09-25 09:45:52 -05:00
parent ad6fe4fdc3
commit 029e31ebe8
No known key found for this signature in database
2 changed files with 55 additions and 1 deletions

View File

@ -211,15 +211,18 @@ public class DelegatingAuthenticationEntryPoint implements AuthenticationEntryPo
* @return the {@link AuthenticationEntryPoint} to use. * @return the {@link AuthenticationEntryPoint} to use.
*/ */
public AuthenticationEntryPoint build() { public AuthenticationEntryPoint build() {
Assert.notEmpty(this.entryPoints, "entryPoints cannot be empty");
AuthenticationEntryPoint defaultEntryPoint = this.defaultEntryPoint; AuthenticationEntryPoint defaultEntryPoint = this.defaultEntryPoint;
if (defaultEntryPoint == null) { if (defaultEntryPoint == null) {
Assert.state(!this.entryPoints.isEmpty(), "entryPoints cannot be empty if defaultEntryPoint is null");
AuthenticationEntryPoint firstAuthenticationEntryPoint = this.entryPoints.get(0).getEntry(); AuthenticationEntryPoint firstAuthenticationEntryPoint = this.entryPoints.get(0).getEntry();
if (this.entryPoints.size() == 1) { if (this.entryPoints.size() == 1) {
return firstAuthenticationEntryPoint; return firstAuthenticationEntryPoint;
} }
defaultEntryPoint = firstAuthenticationEntryPoint; defaultEntryPoint = firstAuthenticationEntryPoint;
} }
else if (this.entryPoints.isEmpty()) {
return defaultEntryPoint;
}
return new DelegatingAuthenticationEntryPoint(defaultEntryPoint, this.entryPoints); return new DelegatingAuthenticationEntryPoint(defaultEntryPoint, this.entryPoints);
} }

View File

@ -16,10 +16,12 @@
package org.springframework.security.web.authentication; package org.springframework.security.web.authentication;
import java.io.IOException;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -29,11 +31,15 @@ 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.security.web.util.matcher.RequestMatcherEntry; import org.springframework.security.web.util.matcher.RequestMatcherEntry;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
/** /**
* Test class for {@link DelegatingAuthenticationEntryPoint} * Test class for {@link DelegatingAuthenticationEntryPoint}
@ -202,4 +208,49 @@ public class DelegatingAuthenticationEntryPointTests {
verify(this.defaultEntryPoint, never()).commence(this.request, null, null); verify(this.defaultEntryPoint, never()).commence(this.request, null, null);
} }
@Test
void builderWhenDefaultNullAndSingleEntryPointThenReturnsSingle() {
AuthenticationEntryPoint entryPoint = mock(AuthenticationEntryPoint.class);
AuthenticationEntryPoint result = DelegatingAuthenticationEntryPoint.builder()
.addEntryPointFor(entryPoint, mock(RequestMatcher.class))
.build();
assertThat(result).isEqualTo(entryPoint);
}
@Test
void builderWhenDefaultNullThenFirstIsDefault() throws ServletException, IOException {
AuthenticationEntryPoint firstEntryPoint = mock(AuthenticationEntryPoint.class);
AuthenticationEntryPoint secondEntryPoint = mock(AuthenticationEntryPoint.class);
RequestMatcher neverMatch = mock(RequestMatcher.class);
given(neverMatch.matches(this.request)).willReturn(false);
AuthenticationEntryPoint result = DelegatingAuthenticationEntryPoint.builder()
.addEntryPointFor(firstEntryPoint, neverMatch)
.addEntryPointFor(secondEntryPoint, neverMatch)
.build();
result.commence(this.request, null, null);
verify(firstEntryPoint).commence(any(), any(), any());
verifyNoInteractions(secondEntryPoint);
}
@Test
void builderWhenDefaultAndEmptyEntryPointsThenReturnsDefault() {
AuthenticationEntryPoint defaultEntryPoint = mock(AuthenticationEntryPoint.class);
AuthenticationEntryPoint result = DelegatingAuthenticationEntryPoint.builder()
.defaultEntryPoint(defaultEntryPoint)
.build();
assertThat(result).isEqualTo(defaultEntryPoint);
}
@Test
void builderWhenNoEntryPointsThenIllegalStateException() {
DelegatingAuthenticationEntryPoint.Builder builder = DelegatingAuthenticationEntryPoint.builder();
assertThatIllegalStateException().isThrownBy(builder::build);
}
} }