Browse Source

Fix ProviderManager.copyDetails Changes Authentication Type

Closes gh-18027
pull/17753/merge
Rob Winch 2 months ago
parent
commit
864a9b2fb3
No known key found for this signature in database
  1. 12
      core/src/main/java/org/springframework/security/authentication/ProviderManager.java
  2. 59
      core/src/test/java/org/springframework/security/authentication/ProviderManagerTests.java

12
core/src/main/java/org/springframework/security/authentication/ProviderManager.java

@ -182,7 +182,7 @@ public class ProviderManager implements AuthenticationManager, MessageSourceAwar @@ -182,7 +182,7 @@ public class ProviderManager implements AuthenticationManager, MessageSourceAwar
try {
result = provider.authenticate(authentication);
if (result != null) {
result = copyDetails(authentication, result);
copyDetails(authentication, result);
break;
}
}
@ -277,14 +277,10 @@ public class ProviderManager implements AuthenticationManager, MessageSourceAwar @@ -277,14 +277,10 @@ public class ProviderManager implements AuthenticationManager, MessageSourceAwar
* @param source source authentication
* @param dest the destination authentication object
*/
private Authentication copyDetails(Authentication source, Authentication dest) {
if (source.getDetails() == null) {
return dest;
private void copyDetails(Authentication source, Authentication dest) {
if ((dest instanceof AbstractAuthenticationToken token) && (dest.getDetails() == null)) {
token.setDetails(source.getDetails());
}
if (dest.getDetails() != null) {
return dest;
}
return dest.toBuilder().details(source.getDetails()).build();
}
public List<AuthenticationProvider> getProviders() {

59
core/src/test/java/org/springframework/security/authentication/ProviderManagerTests.java

@ -21,6 +21,7 @@ import java.util.Arrays; @@ -21,6 +21,7 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.springframework.context.MessageSource;
@ -162,6 +163,20 @@ public class ProviderManagerTests { @@ -162,6 +163,20 @@ public class ProviderManagerTests {
assertThat(result.getDetails()).isSameAs(details);
}
// gh-18027
@Test
void authenticationIsSameWhenDetailsSetAndAuthenticationToBuilderIsDefault() {
Authentication customAuthentication = new DefaultToBuilderAuthentication();
AuthenticationProvider provider = mock(AuthenticationProvider.class);
given(provider.supports(any())).willReturn(true);
given(provider.authenticate(any())).willReturn(customAuthentication);
TestingAuthenticationToken request = createAuthenticationToken();
request.setDetails(new Object());
ProviderManager authMgr = new ProviderManager(provider);
Authentication result = authMgr.authenticate(request);
assertThat(result).isSameAs(customAuthentication);
}
@Test
void authenticationExceptionIsIgnoredIfLaterProviderAuthenticates() {
Authentication result = new TestingAuthenticationToken("user", "pass", "FACTOR");
@ -356,4 +371,48 @@ public class ProviderManagerTests { @@ -356,4 +371,48 @@ public class ProviderManagerTests {
}
/**
* Represents a custom {@link Authentication} that does not override
* {@link #toBuilder()}. We should remain passive to previous versions of Spring
* Security and not change the {@link Authentication} type.
*/
private static final class DefaultToBuilderAuthentication implements Authentication {
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return List.of();
}
@Override
public @Nullable Object getCredentials() {
return null;
}
@Override
public @Nullable Object getDetails() {
return null;
}
@Override
public @Nullable Object getPrincipal() {
return null;
}
@Override
public boolean isAuthenticated() {
return false;
}
@Override
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
}
@Override
public String getName() {
return "";
}
}
}

Loading…
Cancel
Save