1
0
mirror of synced 2026-05-22 21:33:16 +00:00

Check If toBuilder Is Implemented

Since RC1 is right around the corner, let's change the API
footprint as little as possible by using reflection to check
if a class has declared toBuilder themselves. If they have, we
can assume that that class's builder will produce that class.

Issue gh-18052
This commit is contained in:
Josh Cummings
2025-10-16 13:22:18 -06:00
parent 4281f6b00b
commit b1a50a25b6
13 changed files with 214 additions and 6 deletions
@@ -17,6 +17,7 @@
package org.springframework.security.oauth2.server.resource.web.authentication;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
@@ -56,7 +57,6 @@ import org.springframework.security.web.context.RequestAttributeSecurityContextR
import org.springframework.security.web.context.SecurityContextRepository;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
@@ -214,7 +214,12 @@ public class BearerTokenAuthenticationFilter extends OncePerRequestFilter {
}
private static boolean declaresToBuilder(Authentication authentication) {
return ReflectionUtils.findMethod(authentication.getClass(), "toBuilder") != null;
for (Method method : authentication.getClass().getDeclaredMethods()) {
if (method.getName().equals("toBuilder") && method.getParameterTypes().length == 0) {
return true;
}
}
return false;
}
/**
@@ -38,6 +38,7 @@ import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationManagerResolver;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.NonBuildableAuthenticationToken;
import org.springframework.security.authentication.SecurityAssertions;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.Authentication;
@@ -316,6 +317,24 @@ public class BearerTokenAuthenticationFilterTests {
// @formatter:on
}
@Test
void doFilterWhenNonBuildableAuthenticationSubclassThenSkipsToBuilder() throws Exception {
TestingAuthenticationToken existingAuthn = new TestingAuthenticationToken("username", "password", "FACTORONE");
SecurityContextHolder.setContext(new SecurityContextImpl(existingAuthn));
given(this.authenticationManager.authenticate(any()))
.willReturn(new NonBuildableAuthenticationToken("username", "password", "FACTORTWO"));
given(this.bearerTokenResolver.resolve(any())).willReturn("token");
BearerTokenAuthenticationFilter filter = addMocks(
new BearerTokenAuthenticationFilter(this.authenticationManager));
filter.doFilter(this.request, this.response, this.filterChain);
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
// @formatter:off
SecurityAssertions.assertThat(authentication).authorities()
.extracting(GrantedAuthority::getAuthority)
.containsExactly("FACTORTWO");
// @formatter:on
}
@Test
public void setAuthenticationEntryPointWhenNullThenThrowsException() {
BearerTokenAuthenticationFilter filter = new BearerTokenAuthenticationFilter(this.authenticationManager);