Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 6eb00d0

Browse files
committed
Apply Existing Authorities
Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com>
1 parent 36f1de9 commit 6eb00d0

File tree

37 files changed

+1125
-4
lines changed

37 files changed

+1125
-4
lines changed

‎cas/src/main/java/org/springframework/security/cas/authentication/CasAuthenticationToken.java

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@
2020
import java.util.Collection;
2121

2222
import org.apereo.cas.client.validation.Assertion;
23+
import org.jspecify.annotations.NonNull;
2324

2425
import org.springframework.security.authentication.AbstractAuthenticationToken;
26+
import org.springframework.security.core.Authentication;
2527
import org.springframework.security.core.GrantedAuthority;
2628
import org.springframework.security.core.userdetails.UserDetails;
2729
import org.springframework.util.Assert;
@@ -153,6 +155,11 @@ public UserDetails getUserDetails() {
153155
return this.userDetails;
154156
}
155157

158+
@Override
159+
public Builder toBuilder() {
160+
return new Builder().apply(this);
161+
}
162+
156163
@Override
157164
public String toString() {
158165
StringBuilder sb = new StringBuilder();
@@ -162,4 +169,66 @@ public String toString() {
162169
return (sb.toString());
163170
}
164171

172+
/**
173+
* A builder preserving the concrete {@link Authentication} type
174+
*
175+
* @since 7.0
176+
*/
177+
public static final class Builder extends AbstractAuthenticationBuilder<@NonNull CasAuthenticationToken, Builder> {
178+
179+
private Integer keyHash;
180+
181+
private Object principal;
182+
183+
private Object credentials;
184+
185+
private UserDetails userDetails;
186+
187+
private Assertion assertion;
188+
189+
private Builder() {
190+
191+
}
192+
193+
public Builder apply(CasAuthenticationToken authentication) {
194+
return super.apply(authentication).keyHash(authentication.keyHash)
195+
.principal(authentication.principal)
196+
.credentials(authentication.credentials)
197+
.userDetails(authentication.userDetails)
198+
.assertion(authentication.assertion);
199+
}
200+
201+
public Builder keyHash(Integer keyHash) {
202+
this.keyHash = keyHash;
203+
return this;
204+
}
205+
206+
public Builder principal(Object principal) {
207+
this.principal = principal;
208+
return this;
209+
}
210+
211+
public Builder credentials(Object credentials) {
212+
this.credentials = credentials;
213+
return this;
214+
}
215+
216+
public Builder userDetails(UserDetails userDetails) {
217+
this.userDetails = userDetails;
218+
return this;
219+
}
220+
221+
public Builder assertion(Assertion assertion) {
222+
this.assertion = assertion;
223+
return this;
224+
}
225+
226+
@Override
227+
protected @NonNull CasAuthenticationToken build(Collection<GrantedAuthority> authorities) {
228+
return new CasAuthenticationToken(this.keyHash, this.principal, this.credentials, authorities,
229+
this.userDetails, this.assertion);
230+
}
231+
232+
}
233+
165234
}

‎cas/src/test/java/org/springframework/security/cas/authentication/CasAuthenticationTokenTests.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.util.Collections;
2020
import java.util.List;
21+
import java.util.Set;
2122

2223
import org.apereo.cas.client.validation.Assertion;
2324
import org.apereo.cas.client.validation.AssertionImpl;
@@ -26,6 +27,7 @@
2627
import org.springframework.security.core.GrantedAuthority;
2728
import org.springframework.security.core.authority.AuthorityUtils;
2829
import org.springframework.security.core.authority.SimpleGrantedAuthority;
30+
import org.springframework.security.core.userdetails.PasswordEncodedUser;
2931
import org.springframework.security.core.userdetails.User;
3032
import org.springframework.security.core.userdetails.UserDetails;
3133

@@ -155,4 +157,22 @@ public void testToString() {
155157
assertThat(result.lastIndexOf("Credentials (Service/Proxy Ticket):") != -1).isTrue();
156158
}
157159

160+
@Test
161+
public void toBuilderWhenApplyThenCopies() {
162+
Assertion assertionOne = new AssertionImpl("test");
163+
CasAuthenticationToken factorOne = new CasAuthenticationToken("key", "alice", "pass",
164+
AuthorityUtils.createAuthorityList("FACTOR_ONE"), PasswordEncodedUser.user(), assertionOne);
165+
Assertion assertionTwo = new AssertionImpl("test");
166+
CasAuthenticationToken factorTwo = new CasAuthenticationToken("yek", "bob", "ssap",
167+
AuthorityUtils.createAuthorityList("FACTOR_TWO"), PasswordEncodedUser.admin(), assertionTwo);
168+
CasAuthenticationToken authentication = factorOne.toBuilder().apply(factorTwo).build();
169+
Set<String> authorities = AuthorityUtils.authorityListToSet(authentication.getAuthorities());
170+
assertThat(authentication.getKeyHash()).isEqualTo(factorTwo.getKeyHash());
171+
assertThat(authentication.getPrincipal()).isEqualTo(factorTwo.getPrincipal());
172+
assertThat(authentication.getCredentials()).isEqualTo(factorTwo.getCredentials());
173+
assertThat(authentication.getUserDetails()).isEqualTo(factorTwo.getUserDetails());
174+
assertThat(authentication.getAssertion()).isEqualTo(factorTwo.getAssertion());
175+
assertThat(authorities).containsExactlyInAnyOrder("FACTOR_ONE", "FACTOR_TWO");
176+
}
177+
158178
}

‎config/src/main/java/org/springframework/security/config/annotation/authentication/builders/AuthenticationManagerBuilder.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.springframework.security.config.annotation.authentication.configurers.userdetails.DaoAuthenticationConfigurer;
3838
import org.springframework.security.config.annotation.authentication.configurers.userdetails.UserDetailsAwareConfigurer;
3939
import org.springframework.security.core.Authentication;
40+
import org.springframework.security.core.context.SecurityContextHolderStrategy;
4041
import org.springframework.security.core.userdetails.UserDetailsService;
4142
import org.springframework.util.Assert;
4243

@@ -235,6 +236,11 @@ protected ProviderManager performBuild() throws Exception {
235236
if (this.eventPublisher != null) {
236237
providerManager.setAuthenticationEventPublisher(this.eventPublisher);
237238
}
239+
SecurityContextHolderStrategy securityContextHolderStrategy = getSharedObject(
240+
SecurityContextHolderStrategy.class);
241+
if (securityContextHolderStrategy != null) {
242+
providerManager.setSecurityContextHolderStrategy(securityContextHolderStrategy);
243+
}
238244
providerManager = postProcess(providerManager);
239245
return providerManager;
240246
}

‎config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfiguration.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@
4747
import org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration;
4848
import org.springframework.security.core.Authentication;
4949
import org.springframework.security.core.AuthenticationException;
50+
import org.springframework.security.core.context.SecurityContextHolder;
51+
import org.springframework.security.core.context.SecurityContextHolderStrategy;
5052
import org.springframework.security.core.userdetails.UserDetailsService;
5153
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
5254
import org.springframework.security.crypto.password.PasswordEncoder;
@@ -83,6 +85,9 @@ public AuthenticationManagerBuilder authenticationManagerBuilder(ObjectPostProce
8385
AuthenticationEventPublisher authenticationEventPublisher = getAuthenticationEventPublisher(context);
8486
DefaultPasswordEncoderAuthenticationManagerBuilder result = new DefaultPasswordEncoderAuthenticationManagerBuilder(
8587
objectPostProcessor, defaultPasswordEncoder);
88+
result.setSharedObject(SecurityContextHolderStrategy.class,
89+
this.applicationContext.getBeanProvider(SecurityContextHolderStrategy.class)
90+
.getIfUnique(SecurityContextHolder::getContextHolderStrategy));
8691
if (authenticationEventPublisher != null) {
8792
result.authenticationEventPublisher(authenticationEventPublisher);
8893
}

‎config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,12 @@ protected AuthenticationManager authenticationManager() throws Exception {
316316
if (this.authenticationManager == null) {
317317
DefaultAuthenticationEventPublisher eventPublisher = this.objectPostProcessor
318318
.postProcess(new DefaultAuthenticationEventPublisher());
319+
SecurityContextHolderStrategy securityContextHolderStrategy = this.context
320+
.getBeanProvider(SecurityContextHolderStrategy.class)
321+
.getIfUnique(SecurityContextHolder::getContextHolderStrategy);
319322
this.auth = new AuthenticationManagerBuilder(this.objectPostProcessor);
320323
this.auth.authenticationEventPublisher(eventPublisher);
324+
this.auth.setSharedObject(SecurityContextHolderStrategy.class, securityContextHolderStrategy);
321325
configure(this.auth);
322326
this.authenticationManager = (this.disableAuthenticationRegistry)
323327
? getAuthenticationConfiguration().getAuthenticationManager() : this.auth.build();

‎config/src/main/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@ HttpSecurity httpSecurity() throws Exception {
116116
LazyPasswordEncoder passwordEncoder = new LazyPasswordEncoder(this.context);
117117
AuthenticationManagerBuilder authenticationBuilder = new DefaultPasswordEncoderAuthenticationManagerBuilder(
118118
this.objectPostProcessor, passwordEncoder);
119+
authenticationBuilder.setSharedObject(SecurityContextHolderStrategy.class,
120+
this.context.getBeanProvider(SecurityContextHolderStrategy.class)
121+
.getIfUnique(SecurityContextHolder::getContextHolderStrategy));
119122
authenticationBuilder.parentAuthenticationManager(authenticationManager());
120123
authenticationBuilder.authenticationEventPublisher(getAuthenticationEventPublisher());
121124
HttpSecurity http = new HttpSecurity(this.objectPostProcessor, authenticationBuilder, createSharedObjects());

‎config/src/main/java/org/springframework/security/config/annotation/web/configurers/WebAuthnConfigurer.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,10 @@ public void configure(H http) throws Exception {
162162
WebAuthnRelyingPartyOperations rpOperations = webAuthnRelyingPartyOperations(userEntities, userCredentials);
163163
PublicKeyCredentialCreationOptionsRepository creationOptionsRepository = creationOptionsRepository();
164164
WebAuthnAuthenticationFilter webAuthnAuthnFilter = new WebAuthnAuthenticationFilter();
165-
webAuthnAuthnFilter.setAuthenticationManager(
166-
new ProviderManager(new WebAuthnAuthenticationProvider(rpOperations, userDetailsService)));
165+
ProviderManager manager = new ProviderManager(
166+
new WebAuthnAuthenticationProvider(rpOperations, userDetailsService));
167+
manager.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
168+
webAuthnAuthnFilter.setAuthenticationManager(manager);
167169
WebAuthnRegistrationFilter webAuthnRegistrationFilter = new WebAuthnRegistrationFilter(userCredentials,
168170
rpOperations);
169171
PublicKeyCredentialCreationOptionsFilter creationOptionsFilter = new PublicKeyCredentialCreationOptionsFilter(

‎config/src/main/java/org/springframework/security/config/authentication/AuthenticationManagerFactoryBean.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
import org.springframework.security.authentication.ProviderManager;
3131
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
3232
import org.springframework.security.config.BeanIds;
33+
import org.springframework.security.core.context.SecurityContextHolder;
34+
import org.springframework.security.core.context.SecurityContextHolderStrategy;
3335
import org.springframework.security.core.userdetails.UserDetailsService;
3436
import org.springframework.security.crypto.password.PasswordEncoder;
3537

@@ -72,6 +74,10 @@ public AuthenticationManager getObject() throws Exception {
7274
}
7375
provider.afterPropertiesSet();
7476
ProviderManager manager = new ProviderManager(Arrays.asList(provider));
77+
SecurityContextHolderStrategy securityContextHolderStrategy = this.bf
78+
.getBeanProvider(SecurityContextHolderStrategy.class)
79+
.getIfUnique(SecurityContextHolder::getContextHolderStrategy);
80+
manager.setSecurityContextHolderStrategy(securityContextHolderStrategy);
7581
if (this.observationRegistry.isNoop()) {
7682
return manager;
7783
}

‎core/src/main/java/org/springframework/security/authentication/AbstractAuthenticationToken.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import java.util.ArrayList;
2121
import java.util.Collection;
2222
import java.util.Collections;
23+
import java.util.HashSet;
24+
import java.util.function.Consumer;
2325

2426
import org.jspecify.annotations.Nullable;
2527

@@ -185,4 +187,36 @@ public String toString() {
185187
return sb.toString();
186188
}
187189

190+
protected abstract static class AbstractAuthenticationBuilder<A extends Authentication, B extends AbstractAuthenticationBuilder<A, B>>
191+
implements Builder<A, B> {
192+
193+
private final Collection<GrantedAuthority> authorities = new HashSet<>();
194+
195+
protected AbstractAuthenticationBuilder() {
196+
197+
}
198+
199+
@Override
200+
public B authorities(Consumer<Collection<GrantedAuthority>> authorities) {
201+
authorities.accept(this.authorities);
202+
return (B) this;
203+
}
204+
205+
@Override
206+
public A build() {
207+
return build(this.authorities);
208+
}
209+
210+
@Override
211+
public B apply(Authentication token) {
212+
Assert.isTrue(token.isAuthenticated(), "cannot mutate an unauthenticated token");
213+
Assert.notNull(token.getPrincipal(), "principal cannot be null");
214+
this.authorities.addAll(token.getAuthorities());
215+
return (B) this;
216+
}
217+
218+
protected abstract A build(Collection<GrantedAuthority> authorities);
219+
220+
}
221+
188222
}

‎core/src/main/java/org/springframework/security/authentication/DelegatingReactiveAuthenticationManager.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import org.springframework.security.core.Authentication;
2929
import org.springframework.security.core.AuthenticationException;
30+
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
3031
import org.springframework.util.Assert;
3132

3233
/**
@@ -57,11 +58,24 @@ public DelegatingReactiveAuthenticationManager(List<ReactiveAuthenticationManage
5758

5859
@Override
5960
public Mono<Authentication> authenticate(Authentication authentication) {
61+
return ReactiveSecurityContextHolder.getContext().flatMap((context) -> {
62+
Mono<Authentication> result = doAuthenticate(authentication);
63+
Authentication current = context.getAuthentication();
64+
if (current == null) {
65+
return result;
66+
}
67+
if (!current.isAuthenticated()) {
68+
return result;
69+
}
70+
return doAuthenticate(current).map((r) -> r.toBuilder().apply(current).build());
71+
}).switchIfEmpty(doAuthenticate(authentication));
72+
}
73+
74+
private Mono<Authentication> doAuthenticate(Authentication authentication) {
6075
Flux<ReactiveAuthenticationManager> result = Flux.fromIterable(this.delegates);
6176
Function<ReactiveAuthenticationManager, Mono<Authentication>> logging = (m) -> m.authenticate(authentication)
6277
.doOnError(AuthenticationException.class, (ex) -> ex.setAuthenticationRequest(authentication))
6378
.doOnError(this.logger::debug);
64-
6579
return ((this.continueOnError) ? result.concatMapDelayError(logging) : result.concatMap(logging)).next();
6680
}
6781

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /