Skip to content

Commit 4102007

Browse files
committed
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
1 parent e535e61 commit 4102007

File tree

8 files changed

+42
-91
lines changed

8 files changed

+42
-91
lines changed

core/src/main/java/org/springframework/security/core/BuildableAuthentication.java

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package org.springframework.security.core;
1818

1919
import java.util.Collection;
20-
import java.util.HashSet;
2120
import java.util.Set;
2221
import java.util.function.Consumer;
2322
import java.util.stream.Collectors;
@@ -84,6 +83,30 @@ public interface BuildableAuthentication extends Authentication {
8483
*/
8584
interface Builder<B extends Builder<B>> {
8685

86+
/**
87+
* Apply this authentication instance
88+
* <p>
89+
* By default, merges the authorities in the provided {@code authentication} with
90+
* the authentication being built. Only those authorities that haven't already
91+
* been specified to the builder will be added.
92+
* </p>
93+
* @param authentication the {@link Authentication} to appluy
94+
* @return the {@link Builder} for additional configuration
95+
* @see BuildableAuthentication#getAuthorities
96+
*/
97+
default B authentication(Authentication authentication) {
98+
return authorities((a) -> {
99+
Set<String> newAuthorities = a.stream()
100+
.map(GrantedAuthority::getAuthority)
101+
.collect(Collectors.toUnmodifiableSet());
102+
for (GrantedAuthority currentAuthority : authentication.getAuthorities()) {
103+
if (!newAuthorities.contains(currentAuthority.getAuthority())) {
104+
a.add(currentAuthority);
105+
}
106+
}
107+
});
108+
}
109+
87110
/**
88111
* Mutate the authorities with this {@link Consumer}.
89112
* <p>
@@ -145,8 +168,8 @@ default B credentials(@Nullable Object credentials) {
145168

146169
/**
147170
* Mark this authentication as authenticated or not
148-
* @param authenticated whether this is an authenticated
149-
* {@link Authentication} instance
171+
* @param authenticated whether this is an authenticated {@link Authentication}
172+
* instance
150173
* @return the {@link Builder} for additional configuration
151174
* @see Authentication#isAuthenticated
152175
*/

core/src/test/java/org/springframework/security/authentication/AbstractAuthenticationBuilderTests.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,16 @@ void applyWhenAuthoritiesThenAdds() {
3737
assertThat(authorities).containsExactlyInAnyOrder("FACTOR_ONE", "FACTOR_TWO");
3838
}
3939

40+
@Test
41+
void authenticationWhenAuthoritiesThenAdds() {
42+
TestingAuthenticationToken factorOne = new TestingAuthenticationToken("user", "pass", "FACTOR_ONE");
43+
TestingAuthenticationToken factorTwo = new TestingAuthenticationToken("user", "pass", "FACTOR_TWO");
44+
TestAbstractAuthenticationBuilder builder = new TestAbstractAuthenticationBuilder(factorOne);
45+
Authentication result = builder.authentication(factorTwo).build();
46+
Set<String> authorities = AuthorityUtils.authorityListToSet(result.getAuthorities());
47+
assertThat(authorities).containsExactlyInAnyOrder("FACTOR_ONE", "FACTOR_TWO");
48+
}
49+
4050
private static final class TestAbstractAuthenticationBuilder
4151
extends TestingAuthenticationToken.Builder<TestAbstractAuthenticationBuilder> {
4252

oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/web/authentication/BearerTokenAuthenticationFilter.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,9 +184,7 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
184184
Authentication current = this.securityContextHolderStrategy.getContext().getAuthentication();
185185
if (current != null && current.isAuthenticated()) {
186186
if (authenticationResult instanceof BuildableAuthentication buildable) {
187-
authenticationResult = buildable.toBuilder()
188-
.authorities((a) -> a.addAll(current.getAuthorities()))
189-
.build();
187+
authenticationResult = buildable.toBuilder().authentication(current).build();
190188
}
191189
}
192190
SecurityContext context = this.securityContextHolderStrategy.createEmptyContext();

web/src/main/java/org/springframework/security/web/authentication/AbstractAuthenticationProcessingFilter.java

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717
package org.springframework.security.web.authentication;
1818

1919
import java.io.IOException;
20-
import java.util.Set;
21-
import java.util.stream.Collectors;
2220

2321
import jakarta.servlet.FilterChain;
2422
import jakarta.servlet.ServletException;
@@ -42,7 +40,6 @@
4240
import org.springframework.security.core.Authentication;
4341
import org.springframework.security.core.AuthenticationException;
4442
import org.springframework.security.core.BuildableAuthentication;
45-
import org.springframework.security.core.GrantedAuthority;
4643
import org.springframework.security.core.SpringSecurityMessageSource;
4744
import org.springframework.security.core.context.SecurityContext;
4845
import org.springframework.security.core.context.SecurityContextHolder;
@@ -255,20 +252,7 @@ private void doFilter(HttpServletRequest request, HttpServletResponse response,
255252
Authentication current = this.securityContextHolderStrategy.getContext().getAuthentication();
256253
if (current != null && current.isAuthenticated()) {
257254
if (authenticationResult instanceof BuildableAuthentication buildable) {
258-
authenticationResult = buildable.toBuilder()
259-
// @formatter:off
260-
.authorities((a) -> {
261-
Set<String> newAuthorities = a.stream()
262-
.map(GrantedAuthority::getAuthority)
263-
.collect(Collectors.toUnmodifiableSet());
264-
for (GrantedAuthority currentAuthority : current.getAuthorities()) {
265-
if (!newAuthorities.contains(currentAuthority.getAuthority())) {
266-
a.add(currentAuthority);
267-
}
268-
}
269-
})
270-
.build();
271-
// @formatter:on
255+
authenticationResult = buildable.toBuilder().authentication(current).build();
272256
}
273257
}
274258
this.sessionStrategy.onAuthentication(authenticationResult, request, response);

web/src/main/java/org/springframework/security/web/authentication/AuthenticationFilter.java

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717
package org.springframework.security.web.authentication;
1818

1919
import java.io.IOException;
20-
import java.util.Set;
21-
import java.util.stream.Collectors;
2220

2321
import jakarta.servlet.Filter;
2422
import jakarta.servlet.FilterChain;
@@ -34,7 +32,6 @@
3432
import org.springframework.security.core.Authentication;
3533
import org.springframework.security.core.AuthenticationException;
3634
import org.springframework.security.core.BuildableAuthentication;
37-
import org.springframework.security.core.GrantedAuthority;
3835
import org.springframework.security.core.context.SecurityContext;
3936
import org.springframework.security.core.context.SecurityContextHolder;
4037
import org.springframework.security.core.context.SecurityContextHolderStrategy;
@@ -191,20 +188,7 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
191188
Authentication current = this.securityContextHolderStrategy.getContext().getAuthentication();
192189
if (current != null && current.isAuthenticated()) {
193190
if (authenticationResult instanceof BuildableAuthentication buildable) {
194-
authenticationResult = buildable.toBuilder()
195-
// @formatter:off
196-
.authorities((a) -> {
197-
Set<String> newAuthorities = a.stream()
198-
.map(GrantedAuthority::getAuthority)
199-
.collect(Collectors.toUnmodifiableSet());
200-
for (GrantedAuthority currentAuthority : current.getAuthorities()) {
201-
if (!newAuthorities.contains(currentAuthority.getAuthority())) {
202-
a.add(currentAuthority);
203-
}
204-
}
205-
})
206-
.build();
207-
// @formatter:on
191+
authenticationResult = buildable.toBuilder().authentication(current).build();
208192
}
209193
}
210194
HttpSession session = request.getSession(false);

web/src/main/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilter.java

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717
package org.springframework.security.web.authentication.preauth;
1818

1919
import java.io.IOException;
20-
import java.util.Set;
21-
import java.util.stream.Collectors;
2220

2321
import jakarta.servlet.FilterChain;
2422
import jakarta.servlet.ServletException;
@@ -38,7 +36,6 @@
3836
import org.springframework.security.core.Authentication;
3937
import org.springframework.security.core.AuthenticationException;
4038
import org.springframework.security.core.BuildableAuthentication;
41-
import org.springframework.security.core.GrantedAuthority;
4239
import org.springframework.security.core.context.SecurityContext;
4340
import org.springframework.security.core.context.SecurityContextHolder;
4441
import org.springframework.security.core.context.SecurityContextHolderStrategy;
@@ -211,20 +208,7 @@ private void doAuthenticate(HttpServletRequest request, HttpServletResponse resp
211208
Authentication current = this.securityContextHolderStrategy.getContext().getAuthentication();
212209
if (current != null && current.isAuthenticated()) {
213210
if (authenticationResult instanceof BuildableAuthentication buildable) {
214-
authenticationResult = buildable.toBuilder()
215-
// @formatter:off
216-
.authorities((a) -> {
217-
Set<String> newAuthorities = a.stream()
218-
.map(GrantedAuthority::getAuthority)
219-
.collect(Collectors.toUnmodifiableSet());
220-
for (GrantedAuthority currentAuthority : current.getAuthorities()) {
221-
if (!newAuthorities.contains(currentAuthority.getAuthority())) {
222-
a.add(currentAuthority);
223-
}
224-
}
225-
})
226-
.build();
227-
// @formatter:on
211+
authenticationResult = buildable.toBuilder().authentication(current).build();
228212
}
229213
}
230214
successfulAuthentication(request, response, authenticationResult);

web/src/main/java/org/springframework/security/web/authentication/www/BasicAuthenticationFilter.java

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818

1919
import java.io.IOException;
2020
import java.nio.charset.Charset;
21-
import java.util.Set;
22-
import java.util.stream.Collectors;
2321

2422
import jakarta.servlet.FilterChain;
2523
import jakarta.servlet.ServletException;
@@ -34,7 +32,6 @@
3432
import org.springframework.security.core.Authentication;
3533
import org.springframework.security.core.AuthenticationException;
3634
import org.springframework.security.core.BuildableAuthentication;
37-
import org.springframework.security.core.GrantedAuthority;
3835
import org.springframework.security.core.context.SecurityContext;
3936
import org.springframework.security.core.context.SecurityContextHolder;
4037
import org.springframework.security.core.context.SecurityContextHolderStrategy;
@@ -193,20 +190,7 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
193190
Authentication current = this.securityContextHolderStrategy.getContext().getAuthentication();
194191
if (current != null && current.isAuthenticated()) {
195192
if (authResult instanceof BuildableAuthentication buildable) {
196-
authResult = buildable.toBuilder()
197-
// @formatter:off
198-
.authorities((a) -> {
199-
Set<String> newAuthorities = a.stream()
200-
.map(GrantedAuthority::getAuthority)
201-
.collect(Collectors.toUnmodifiableSet());
202-
for (GrantedAuthority currentAuthority : current.getAuthorities()) {
203-
if (!newAuthorities.contains(currentAuthority.getAuthority())) {
204-
a.add(currentAuthority);
205-
}
206-
}
207-
})
208-
.build();
209-
// @formatter:on
193+
authResult = buildable.toBuilder().authentication(current).build();
210194
}
211195
}
212196
SecurityContext context = this.securityContextHolderStrategy.createEmptyContext();

web/src/main/java/org/springframework/security/web/server/authentication/AuthenticationWebFilter.java

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@
1616

1717
package org.springframework.security.web.server.authentication;
1818

19-
import java.util.Set;
2019
import java.util.function.Function;
21-
import java.util.stream.Collectors;
2220

2321
import org.apache.commons.logging.Log;
2422
import org.apache.commons.logging.LogFactory;
@@ -30,7 +28,6 @@
3028
import org.springframework.security.core.Authentication;
3129
import org.springframework.security.core.AuthenticationException;
3230
import org.springframework.security.core.BuildableAuthentication;
33-
import org.springframework.security.core.GrantedAuthority;
3431
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
3532
import org.springframework.security.core.context.SecurityContextImpl;
3633
import org.springframework.security.web.server.WebFilterExchange;
@@ -145,20 +142,7 @@ private Mono<Authentication> applyCurrentAuthenication(Authentication result) {
145142
if (!(result instanceof BuildableAuthentication buildable)) {
146143
return result;
147144
}
148-
return buildable.toBuilder()
149-
// @formatter:off
150-
.authorities((a) -> {
151-
Set<String> newAuthorities = a.stream()
152-
.map(GrantedAuthority::getAuthority)
153-
.collect(Collectors.toUnmodifiableSet());
154-
for (GrantedAuthority currentAuthority : current.getAuthorities()) {
155-
if (!newAuthorities.contains(currentAuthority.getAuthority())) {
156-
a.add(currentAuthority);
157-
}
158-
}
159-
})
160-
.build();
161-
// @formatter:on
145+
return buildable.toBuilder().authentication(current).build();
162146
}).switchIfEmpty(Mono.just(result));
163147
}
164148

0 commit comments

Comments
 (0)