Add Builder#authentication
This commit consolidates logic common to applying one authenticaiton to another. Specifically, it will copy the authorities in one authentication into the builder instance of another. Closes gh-18053
This commit is contained in:
@@ -17,7 +17,6 @@
|
||||
package org.springframework.security.core;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -84,6 +83,30 @@ public interface BuildableAuthentication extends Authentication {
|
||||
*/
|
||||
interface Builder<B extends Builder<B>> {
|
||||
|
||||
/**
|
||||
* Apply this authentication instance
|
||||
* <p>
|
||||
* By default, merges the authorities in the provided {@code authentication} with
|
||||
* the authentication being built. Only those authorities that haven't already
|
||||
* been specified to the builder will be added.
|
||||
* </p>
|
||||
* @param authentication the {@link Authentication} to appluy
|
||||
* @return the {@link Builder} for additional configuration
|
||||
* @see BuildableAuthentication#getAuthorities
|
||||
*/
|
||||
default B authentication(Authentication authentication) {
|
||||
return authorities((a) -> {
|
||||
Set<String> newAuthorities = a.stream()
|
||||
.map(GrantedAuthority::getAuthority)
|
||||
.collect(Collectors.toUnmodifiableSet());
|
||||
for (GrantedAuthority currentAuthority : authentication.getAuthorities()) {
|
||||
if (!newAuthorities.contains(currentAuthority.getAuthority())) {
|
||||
a.add(currentAuthority);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Mutate the authorities with this {@link Consumer}.
|
||||
* <p>
|
||||
@@ -145,8 +168,8 @@ public interface BuildableAuthentication extends Authentication {
|
||||
|
||||
/**
|
||||
* Mark this authentication as authenticated or not
|
||||
* @param authenticated whether this is an authenticated
|
||||
* {@link Authentication} instance
|
||||
* @param authenticated whether this is an authenticated {@link Authentication}
|
||||
* instance
|
||||
* @return the {@link Builder} for additional configuration
|
||||
* @see Authentication#isAuthenticated
|
||||
*/
|
||||
|
||||
+10
@@ -37,6 +37,16 @@ class AbstractAuthenticationBuilderTests {
|
||||
assertThat(authorities).containsExactlyInAnyOrder("FACTOR_ONE", "FACTOR_TWO");
|
||||
}
|
||||
|
||||
@Test
|
||||
void authenticationWhenAuthoritiesThenAdds() {
|
||||
TestingAuthenticationToken factorOne = new TestingAuthenticationToken("user", "pass", "FACTOR_ONE");
|
||||
TestingAuthenticationToken factorTwo = new TestingAuthenticationToken("user", "pass", "FACTOR_TWO");
|
||||
TestAbstractAuthenticationBuilder builder = new TestAbstractAuthenticationBuilder(factorOne);
|
||||
Authentication result = builder.authentication(factorTwo).build();
|
||||
Set<String> authorities = AuthorityUtils.authorityListToSet(result.getAuthorities());
|
||||
assertThat(authorities).containsExactlyInAnyOrder("FACTOR_ONE", "FACTOR_TWO");
|
||||
}
|
||||
|
||||
private static final class TestAbstractAuthenticationBuilder
|
||||
extends TestingAuthenticationToken.Builder<TestAbstractAuthenticationBuilder> {
|
||||
|
||||
|
||||
+1
-3
@@ -184,9 +184,7 @@ public class BearerTokenAuthenticationFilter extends OncePerRequestFilter {
|
||||
Authentication current = this.securityContextHolderStrategy.getContext().getAuthentication();
|
||||
if (current != null && current.isAuthenticated()) {
|
||||
if (authenticationResult instanceof BuildableAuthentication buildable) {
|
||||
authenticationResult = buildable.toBuilder()
|
||||
.authorities((a) -> a.addAll(current.getAuthorities()))
|
||||
.build();
|
||||
authenticationResult = buildable.toBuilder().authentication(current).build();
|
||||
}
|
||||
}
|
||||
SecurityContext context = this.securityContextHolderStrategy.createEmptyContext();
|
||||
|
||||
+1
-17
@@ -17,8 +17,6 @@
|
||||
package org.springframework.security.web.authentication;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
@@ -42,7 +40,6 @@ import org.springframework.security.authentication.event.InteractiveAuthenticati
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.BuildableAuthentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.SpringSecurityMessageSource;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
@@ -255,20 +252,7 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
|
||||
Authentication current = this.securityContextHolderStrategy.getContext().getAuthentication();
|
||||
if (current != null && current.isAuthenticated()) {
|
||||
if (authenticationResult instanceof BuildableAuthentication buildable) {
|
||||
authenticationResult = buildable.toBuilder()
|
||||
// @formatter:off
|
||||
.authorities((a) -> {
|
||||
Set<String> newAuthorities = a.stream()
|
||||
.map(GrantedAuthority::getAuthority)
|
||||
.collect(Collectors.toUnmodifiableSet());
|
||||
for (GrantedAuthority currentAuthority : current.getAuthorities()) {
|
||||
if (!newAuthorities.contains(currentAuthority.getAuthority())) {
|
||||
a.add(currentAuthority);
|
||||
}
|
||||
}
|
||||
})
|
||||
.build();
|
||||
// @formatter:on
|
||||
authenticationResult = buildable.toBuilder().authentication(current).build();
|
||||
}
|
||||
}
|
||||
this.sessionStrategy.onAuthentication(authenticationResult, request, response);
|
||||
|
||||
+1
-17
@@ -17,8 +17,6 @@
|
||||
package org.springframework.security.web.authentication;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jakarta.servlet.Filter;
|
||||
import jakarta.servlet.FilterChain;
|
||||
@@ -34,7 +32,6 @@ import org.springframework.security.authentication.AuthenticationManagerResolver
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.BuildableAuthentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||
@@ -191,20 +188,7 @@ public class AuthenticationFilter extends OncePerRequestFilter {
|
||||
Authentication current = this.securityContextHolderStrategy.getContext().getAuthentication();
|
||||
if (current != null && current.isAuthenticated()) {
|
||||
if (authenticationResult instanceof BuildableAuthentication buildable) {
|
||||
authenticationResult = buildable.toBuilder()
|
||||
// @formatter:off
|
||||
.authorities((a) -> {
|
||||
Set<String> newAuthorities = a.stream()
|
||||
.map(GrantedAuthority::getAuthority)
|
||||
.collect(Collectors.toUnmodifiableSet());
|
||||
for (GrantedAuthority currentAuthority : current.getAuthorities()) {
|
||||
if (!newAuthorities.contains(currentAuthority.getAuthority())) {
|
||||
a.add(currentAuthority);
|
||||
}
|
||||
}
|
||||
})
|
||||
.build();
|
||||
// @formatter:on
|
||||
authenticationResult = buildable.toBuilder().authentication(current).build();
|
||||
}
|
||||
}
|
||||
HttpSession session = request.getSession(false);
|
||||
|
||||
+1
-17
@@ -17,8 +17,6 @@
|
||||
package org.springframework.security.web.authentication.preauth;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
@@ -38,7 +36,6 @@ import org.springframework.security.authentication.event.InteractiveAuthenticati
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.BuildableAuthentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||
@@ -211,20 +208,7 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
|
||||
Authentication current = this.securityContextHolderStrategy.getContext().getAuthentication();
|
||||
if (current != null && current.isAuthenticated()) {
|
||||
if (authenticationResult instanceof BuildableAuthentication buildable) {
|
||||
authenticationResult = buildable.toBuilder()
|
||||
// @formatter:off
|
||||
.authorities((a) -> {
|
||||
Set<String> newAuthorities = a.stream()
|
||||
.map(GrantedAuthority::getAuthority)
|
||||
.collect(Collectors.toUnmodifiableSet());
|
||||
for (GrantedAuthority currentAuthority : current.getAuthorities()) {
|
||||
if (!newAuthorities.contains(currentAuthority.getAuthority())) {
|
||||
a.add(currentAuthority);
|
||||
}
|
||||
}
|
||||
})
|
||||
.build();
|
||||
// @formatter:on
|
||||
authenticationResult = buildable.toBuilder().authentication(current).build();
|
||||
}
|
||||
}
|
||||
successfulAuthentication(request, response, authenticationResult);
|
||||
|
||||
+1
-17
@@ -18,8 +18,6 @@ package org.springframework.security.web.authentication.www;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
@@ -34,7 +32,6 @@ import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.BuildableAuthentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||
@@ -193,20 +190,7 @@ public class BasicAuthenticationFilter extends OncePerRequestFilter {
|
||||
Authentication current = this.securityContextHolderStrategy.getContext().getAuthentication();
|
||||
if (current != null && current.isAuthenticated()) {
|
||||
if (authResult instanceof BuildableAuthentication buildable) {
|
||||
authResult = buildable.toBuilder()
|
||||
// @formatter:off
|
||||
.authorities((a) -> {
|
||||
Set<String> newAuthorities = a.stream()
|
||||
.map(GrantedAuthority::getAuthority)
|
||||
.collect(Collectors.toUnmodifiableSet());
|
||||
for (GrantedAuthority currentAuthority : current.getAuthorities()) {
|
||||
if (!newAuthorities.contains(currentAuthority.getAuthority())) {
|
||||
a.add(currentAuthority);
|
||||
}
|
||||
}
|
||||
})
|
||||
.build();
|
||||
// @formatter:on
|
||||
authResult = buildable.toBuilder().authentication(current).build();
|
||||
}
|
||||
}
|
||||
SecurityContext context = this.securityContextHolderStrategy.createEmptyContext();
|
||||
|
||||
+1
-17
@@ -16,9 +16,7 @@
|
||||
|
||||
package org.springframework.security.web.server.authentication;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -30,7 +28,6 @@ import org.springframework.security.authentication.ReactiveAuthenticationManager
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.BuildableAuthentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
||||
import org.springframework.security.core.context.SecurityContextImpl;
|
||||
import org.springframework.security.web.server.WebFilterExchange;
|
||||
@@ -145,20 +142,7 @@ public class AuthenticationWebFilter implements WebFilter {
|
||||
if (!(result instanceof BuildableAuthentication buildable)) {
|
||||
return result;
|
||||
}
|
||||
return buildable.toBuilder()
|
||||
// @formatter:off
|
||||
.authorities((a) -> {
|
||||
Set<String> newAuthorities = a.stream()
|
||||
.map(GrantedAuthority::getAuthority)
|
||||
.collect(Collectors.toUnmodifiableSet());
|
||||
for (GrantedAuthority currentAuthority : current.getAuthorities()) {
|
||||
if (!newAuthorities.contains(currentAuthority.getAuthority())) {
|
||||
a.add(currentAuthority);
|
||||
}
|
||||
}
|
||||
})
|
||||
.build();
|
||||
// @formatter:on
|
||||
return buildable.toBuilder().authentication(current).build();
|
||||
}).switchIfEmpty(Mono.just(result));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user