Fix ProviderManager.copyDetails Changes Authentication Type
Closes gh-18027
This commit is contained in:
@@ -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
|
||||
* @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
@@ -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 {
|
||||
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 {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 "";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user