mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-10-21 09:48:46 +00:00
Merge branch 'builder-enhancements'
Issue gh-18052 Issue gh-18053
This commit is contained in:
commit
95644fb73c
@ -23,6 +23,7 @@ import org.apereo.cas.client.validation.Assertion;
|
|||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||||
|
import org.springframework.security.core.BuildableAuthentication;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
@ -34,7 +35,8 @@ import org.springframework.util.ObjectUtils;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
* @author Scott Battaglia
|
* @author Scott Battaglia
|
||||||
*/
|
*/
|
||||||
public class CasAuthenticationToken extends AbstractAuthenticationToken implements Serializable {
|
public class CasAuthenticationToken extends AbstractAuthenticationToken
|
||||||
|
implements BuildableAuthentication, Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = 620L;
|
private static final long serialVersionUID = 620L;
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ import java.util.Collection;
|
|||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||||
|
import org.springframework.security.core.BuildableAuthentication;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
@ -32,7 +33,8 @@ import org.springframework.util.Assert;
|
|||||||
* @author Hal Deadman
|
* @author Hal Deadman
|
||||||
* @since 6.1
|
* @since 6.1
|
||||||
*/
|
*/
|
||||||
public class CasServiceTicketAuthenticationToken extends AbstractAuthenticationToken {
|
public class CasServiceTicketAuthenticationToken extends AbstractAuthenticationToken
|
||||||
|
implements BuildableAuthentication {
|
||||||
|
|
||||||
static final String CAS_STATELESS_IDENTIFIER = "_cas_stateless_";
|
static final String CAS_STATELESS_IDENTIFIER = "_cas_stateless_";
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ import java.util.Collection;
|
|||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
|
import org.springframework.security.core.BuildableAuthentication;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
@ -32,7 +33,7 @@ import org.springframework.util.Assert;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
* @author Luke Taylor
|
* @author Luke Taylor
|
||||||
*/
|
*/
|
||||||
public class RememberMeAuthenticationToken extends AbstractAuthenticationToken {
|
public class RememberMeAuthenticationToken extends AbstractAuthenticationToken implements BuildableAuthentication {
|
||||||
|
|
||||||
private static final long serialVersionUID = 620L;
|
private static final long serialVersionUID = 620L;
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
|
import org.springframework.security.core.BuildableAuthentication;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.security.core.authority.AuthorityUtils;
|
import org.springframework.security.core.authority.AuthorityUtils;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
@ -34,7 +35,7 @@ import org.springframework.util.Assert;
|
|||||||
*
|
*
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public class TestingAuthenticationToken extends AbstractAuthenticationToken {
|
public class TestingAuthenticationToken extends AbstractAuthenticationToken implements BuildableAuthentication {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ import java.util.Collection;
|
|||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
|
import org.springframework.security.core.BuildableAuthentication;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
@ -35,7 +36,8 @@ import org.springframework.util.Assert;
|
|||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
* @author Norbert Nowak
|
* @author Norbert Nowak
|
||||||
*/
|
*/
|
||||||
public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationToken {
|
public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationToken
|
||||||
|
implements BuildableAuthentication {
|
||||||
|
|
||||||
private static final long serialVersionUID = 620L;
|
private static final long serialVersionUID = 620L;
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ import java.util.Collection;
|
|||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||||
|
import org.springframework.security.core.BuildableAuthentication;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
@ -31,7 +32,7 @@ import org.springframework.util.Assert;
|
|||||||
* @author Josh Cummings
|
* @author Josh Cummings
|
||||||
* @since 7.0
|
* @since 7.0
|
||||||
*/
|
*/
|
||||||
public class OneTimeTokenAuthentication extends AbstractAuthenticationToken {
|
public class OneTimeTokenAuthentication extends AbstractAuthenticationToken implements BuildableAuthentication {
|
||||||
|
|
||||||
@Serial
|
@Serial
|
||||||
private static final long serialVersionUID = 1195893764725073959L;
|
private static final long serialVersionUID = 1195893764725073959L;
|
||||||
|
@ -19,7 +19,9 @@ package org.springframework.security.core;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
@ -138,35 +140,37 @@ public interface Authentication extends Principal, Serializable {
|
|||||||
void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;
|
void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an {@link Builder} based on this instance. By default, returns a builder
|
* A builder based on a given {@link BuildableAuthentication} instance
|
||||||
* that builds a {@link SimpleAuthentication}.
|
|
||||||
* <p>
|
|
||||||
* Although a {@code default} method, all {@link Authentication} implementations
|
|
||||||
* should implement this. The reason is to ensure that the {@link Authentication} type
|
|
||||||
* is preserved when {@link Builder#build} is invoked. This is especially important in
|
|
||||||
* the event that your authentication implementation contains custom fields.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* This isn't strictly necessary since it is recommended that applications code to the
|
|
||||||
* {@link Authentication} interface and that custom information is often contained in
|
|
||||||
* the {@link Authentication#getPrincipal} value.
|
|
||||||
* </p>
|
|
||||||
* @return an {@link Builder} for building a new {@link Authentication} based on this
|
|
||||||
* instance
|
|
||||||
* @since 7.0
|
|
||||||
*/
|
|
||||||
default Builder<?> toBuilder() {
|
|
||||||
return new SimpleAuthentication.Builder(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A builder based on a given {@link Authentication} instance
|
|
||||||
*
|
*
|
||||||
* @author Josh Cummings
|
* @author Josh Cummings
|
||||||
* @since 7.0
|
* @since 7.0
|
||||||
*/
|
*/
|
||||||
interface Builder<B extends Builder<B>> {
|
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}.
|
* Mutate the authorities with this {@link Consumer}.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.security.core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An {@link Authentication} that is also buildable.
|
||||||
|
*
|
||||||
|
* @author Josh Cummings
|
||||||
|
* @since 7.0
|
||||||
|
*/
|
||||||
|
public interface BuildableAuthentication extends Authentication {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an {@link Builder} based on this instance.
|
||||||
|
* <p>
|
||||||
|
* Although a {@code default} method, all {@link BuildableAuthentication}
|
||||||
|
* implementations should implement this. The reason is to ensure that the
|
||||||
|
* {@link BuildableAuthentication} type is preserved when {@link Builder#build} is
|
||||||
|
* invoked. This is especially important in the event that your authentication
|
||||||
|
* implementation contains custom fields.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* This isn't strictly necessary since it is recommended that applications code to the
|
||||||
|
* {@link Authentication} interface and that custom information is often contained in
|
||||||
|
* the {@link Authentication#getPrincipal} value.
|
||||||
|
* </p>
|
||||||
|
* @return an {@link Builder} for building a new {@link Authentication} based on this
|
||||||
|
* instance
|
||||||
|
*/
|
||||||
|
Builder<?> toBuilder();
|
||||||
|
|
||||||
|
}
|
@ -1,151 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2004-present the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.security.core;
|
|
||||||
|
|
||||||
import java.io.Serial;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
|
|
||||||
@Transient
|
|
||||||
final class SimpleAuthentication implements Authentication {
|
|
||||||
|
|
||||||
@Serial
|
|
||||||
private static final long serialVersionUID = 3194696462184782814L;
|
|
||||||
|
|
||||||
private final @Nullable Object principal;
|
|
||||||
|
|
||||||
private final @Nullable Object credentials;
|
|
||||||
|
|
||||||
private final Collection<GrantedAuthority> authorities;
|
|
||||||
|
|
||||||
private final @Nullable Object details;
|
|
||||||
|
|
||||||
private final boolean authenticated;
|
|
||||||
|
|
||||||
private SimpleAuthentication(Builder builder) {
|
|
||||||
this.principal = builder.principal;
|
|
||||||
this.credentials = builder.credentials;
|
|
||||||
this.authorities = builder.authorities;
|
|
||||||
this.details = builder.details;
|
|
||||||
this.authenticated = builder.authenticated;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
|
||||||
return this.authorities;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable Object getCredentials() {
|
|
||||||
return this.credentials;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable Object getDetails() {
|
|
||||||
return this.details;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable Object getPrincipal() {
|
|
||||||
return this.principal;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAuthenticated() {
|
|
||||||
return this.authenticated;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Instead of calling this setter, please call toBuilder to create a new instance");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return (this.principal == null) ? "" : this.principal.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
static final class Builder implements Authentication.Builder<Builder> {
|
|
||||||
|
|
||||||
private final Log logger = LogFactory.getLog(getClass());
|
|
||||||
|
|
||||||
private final Collection<GrantedAuthority> authorities = new LinkedHashSet<>();
|
|
||||||
|
|
||||||
private @Nullable Object principal;
|
|
||||||
|
|
||||||
private @Nullable Object credentials;
|
|
||||||
|
|
||||||
private @Nullable Object details;
|
|
||||||
|
|
||||||
private boolean authenticated;
|
|
||||||
|
|
||||||
Builder(Authentication authentication) {
|
|
||||||
this.logger.debug("Creating a builder which will result in exchanging an authentication of type "
|
|
||||||
+ authentication.getClass() + " for " + SimpleAuthentication.class.getSimpleName() + ";"
|
|
||||||
+ " consider implementing " + authentication.getClass().getSimpleName() + "#toBuilder");
|
|
||||||
this.authorities.addAll(authentication.getAuthorities());
|
|
||||||
this.principal = authentication.getPrincipal();
|
|
||||||
this.credentials = authentication.getCredentials();
|
|
||||||
this.details = authentication.getDetails();
|
|
||||||
this.authenticated = authentication.isAuthenticated();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Builder authorities(Consumer<Collection<GrantedAuthority>> authorities) {
|
|
||||||
authorities.accept(this.authorities);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Builder details(@Nullable Object details) {
|
|
||||||
this.details = details;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Builder principal(@Nullable Object principal) {
|
|
||||||
this.principal = principal;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Builder credentials(@Nullable Object credentials) {
|
|
||||||
this.credentials = credentials;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Builder authenticated(boolean authenticated) {
|
|
||||||
this.authenticated = authenticated;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Authentication build() {
|
|
||||||
return new SimpleAuthentication(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -37,6 +37,16 @@ class AbstractAuthenticationBuilderTests {
|
|||||||
assertThat(authorities).containsExactlyInAnyOrder("FACTOR_ONE", "FACTOR_TWO");
|
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
|
private static final class TestAbstractAuthenticationBuilder
|
||||||
extends TestingAuthenticationToken.Builder<TestAbstractAuthenticationBuilder> {
|
extends TestingAuthenticationToken.Builder<TestAbstractAuthenticationBuilder> {
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import org.springframework.security.authentication.TestingAuthenticationToken;
|
|||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.security.authentication.ott.OneTimeTokenAuthentication;
|
import org.springframework.security.authentication.ott.OneTimeTokenAuthentication;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.BuildableAuthentication;
|
||||||
import org.springframework.security.core.authority.AuthorityUtils;
|
import org.springframework.security.core.authority.AuthorityUtils;
|
||||||
import org.springframework.security.core.authority.FactorGrantedAuthority;
|
import org.springframework.security.core.authority.FactorGrantedAuthority;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
@ -30,8 +31,9 @@ public class CopyAuthoritiesTests {
|
|||||||
// tag::springSecurity[]
|
// tag::springSecurity[]
|
||||||
Authentication lastestResult = authenticationManager.authenticate(authenticationRequest);
|
Authentication lastestResult = authenticationManager.authenticate(authenticationRequest);
|
||||||
Authentication previousResult = SecurityContextHolder.getContext().getAuthentication();
|
Authentication previousResult = SecurityContextHolder.getContext().getAuthentication();
|
||||||
if (previousResult != null && previousResult.isAuthenticated()) {
|
if (previousResult != null && previousResult.isAuthenticated() &&
|
||||||
lastestResult = lastestResult.toBuilder()
|
lastestResult instanceof BuildableAuthentication buildable) {
|
||||||
|
lastestResult = buildable.toBuilder()
|
||||||
.authorities((a) -> a.addAll(previous.getAuthorities()))
|
.authorities((a) -> a.addAll(previous.getAuthorities()))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import org.springframework.security.authentication.TestingAuthenticationToken
|
|||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
|
||||||
import org.springframework.security.authentication.ott.OneTimeTokenAuthentication
|
import org.springframework.security.authentication.ott.OneTimeTokenAuthentication
|
||||||
import org.springframework.security.core.Authentication
|
import org.springframework.security.core.Authentication
|
||||||
|
import org.springframework.security.core.BuildableAuthentication
|
||||||
import org.springframework.security.core.authority.AuthorityUtils
|
import org.springframework.security.core.authority.AuthorityUtils
|
||||||
import org.springframework.security.core.authority.FactorGrantedAuthority
|
import org.springframework.security.core.authority.FactorGrantedAuthority
|
||||||
import org.springframework.security.core.context.SecurityContextHolder
|
import org.springframework.security.core.context.SecurityContextHolder
|
||||||
@ -28,7 +29,7 @@ class CopyAuthoritiesTests {
|
|||||||
// tag::springSecurity[]
|
// tag::springSecurity[]
|
||||||
var latestResult: Authentication = authenticationManager.authenticate(authenticationRequest)
|
var latestResult: Authentication = authenticationManager.authenticate(authenticationRequest)
|
||||||
val previousResult = SecurityContextHolder.getContext().authentication;
|
val previousResult = SecurityContextHolder.getContext().authentication;
|
||||||
if (previousResult?.isAuthenticated == true) {
|
if (previousResult?.isAuthenticated == true && latestResult is BuildableAuthentication) {
|
||||||
latestResult = latestResult.toBuilder().authorities { a ->
|
latestResult = latestResult.toBuilder().authorities { a ->
|
||||||
a.addAll(previousResult.authorities)
|
a.addAll(previousResult.authorities)
|
||||||
}.build()
|
}.build()
|
||||||
|
@ -22,6 +22,7 @@ import org.jspecify.annotations.Nullable;
|
|||||||
|
|
||||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.BuildableAuthentication;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
|
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
|
||||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||||
@ -42,7 +43,7 @@ import org.springframework.util.Assert;
|
|||||||
* @see OAuth2User
|
* @see OAuth2User
|
||||||
* @see OAuth2AuthorizedClient
|
* @see OAuth2AuthorizedClient
|
||||||
*/
|
*/
|
||||||
public class OAuth2AuthenticationToken extends AbstractAuthenticationToken {
|
public class OAuth2AuthenticationToken extends AbstractAuthenticationToken implements BuildableAuthentication {
|
||||||
|
|
||||||
private static final long serialVersionUID = 620L;
|
private static final long serialVersionUID = 620L;
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ import java.util.Map;
|
|||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.BuildableAuthentication;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.security.core.Transient;
|
import org.springframework.security.core.Transient;
|
||||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||||
@ -38,7 +39,8 @@ import org.springframework.util.Assert;
|
|||||||
* @since 5.2
|
* @since 5.2
|
||||||
*/
|
*/
|
||||||
@Transient
|
@Transient
|
||||||
public class BearerTokenAuthentication extends AbstractOAuth2TokenAuthenticationToken<OAuth2AccessToken> {
|
public class BearerTokenAuthentication extends AbstractOAuth2TokenAuthenticationToken<OAuth2AccessToken>
|
||||||
|
implements BuildableAuthentication {
|
||||||
|
|
||||||
private static final long serialVersionUID = 620L;
|
private static final long serialVersionUID = 620L;
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ import java.util.Map;
|
|||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.BuildableAuthentication;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.security.core.Transient;
|
import org.springframework.security.core.Transient;
|
||||||
import org.springframework.security.oauth2.jwt.Jwt;
|
import org.springframework.security.oauth2.jwt.Jwt;
|
||||||
@ -37,7 +38,8 @@ import org.springframework.util.Assert;
|
|||||||
* @see Jwt
|
* @see Jwt
|
||||||
*/
|
*/
|
||||||
@Transient
|
@Transient
|
||||||
public class JwtAuthenticationToken extends AbstractOAuth2TokenAuthenticationToken<Jwt> {
|
public class JwtAuthenticationToken extends AbstractOAuth2TokenAuthenticationToken<Jwt>
|
||||||
|
implements BuildableAuthentication {
|
||||||
|
|
||||||
private static final long serialVersionUID = 620L;
|
private static final long serialVersionUID = 620L;
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ import org.springframework.security.authentication.AuthenticationManager;
|
|||||||
import org.springframework.security.authentication.AuthenticationManagerResolver;
|
import org.springframework.security.authentication.AuthenticationManagerResolver;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.AuthenticationException;
|
||||||
|
import org.springframework.security.core.BuildableAuthentication;
|
||||||
import org.springframework.security.core.context.SecurityContext;
|
import org.springframework.security.core.context.SecurityContext;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||||
@ -182,9 +183,9 @@ public class BearerTokenAuthenticationFilter extends OncePerRequestFilter {
|
|||||||
}
|
}
|
||||||
Authentication current = this.securityContextHolderStrategy.getContext().getAuthentication();
|
Authentication current = this.securityContextHolderStrategy.getContext().getAuthentication();
|
||||||
if (current != null && current.isAuthenticated()) {
|
if (current != null && current.isAuthenticated()) {
|
||||||
authenticationResult = authenticationResult.toBuilder()
|
if (authenticationResult instanceof BuildableAuthentication buildable) {
|
||||||
.authorities((a) -> a.addAll(current.getAuthorities()))
|
authenticationResult = buildable.toBuilder().authentication(current).build();
|
||||||
.build();
|
}
|
||||||
}
|
}
|
||||||
SecurityContext context = this.securityContextHolderStrategy.createEmptyContext();
|
SecurityContext context = this.securityContextHolderStrategy.createEmptyContext();
|
||||||
context.setAuthentication(authenticationResult);
|
context.setAuthentication(authenticationResult);
|
||||||
|
@ -21,6 +21,7 @@ import java.util.Collection;
|
|||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
|
import org.springframework.security.core.BuildableAuthentication;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
|
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
@ -33,7 +34,7 @@ import org.springframework.util.Assert;
|
|||||||
* @see Saml2ResponseAssertionAccessor
|
* @see Saml2ResponseAssertionAccessor
|
||||||
* @see Saml2ResponseAssertion
|
* @see Saml2ResponseAssertion
|
||||||
*/
|
*/
|
||||||
public class Saml2AssertionAuthentication extends Saml2Authentication {
|
public class Saml2AssertionAuthentication extends Saml2Authentication implements BuildableAuthentication {
|
||||||
|
|
||||||
@Serial
|
@Serial
|
||||||
private static final long serialVersionUID = -4194323643788693205L;
|
private static final long serialVersionUID = -4194323643788693205L;
|
||||||
|
@ -17,8 +17,6 @@
|
|||||||
package org.springframework.security.web.authentication;
|
package org.springframework.security.web.authentication;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import jakarta.servlet.FilterChain;
|
import jakarta.servlet.FilterChain;
|
||||||
import jakarta.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
@ -41,7 +39,7 @@ import org.springframework.security.authentication.InternalAuthenticationService
|
|||||||
import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent;
|
import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.AuthenticationException;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.BuildableAuthentication;
|
||||||
import org.springframework.security.core.SpringSecurityMessageSource;
|
import org.springframework.security.core.SpringSecurityMessageSource;
|
||||||
import org.springframework.security.core.context.SecurityContext;
|
import org.springframework.security.core.context.SecurityContext;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
@ -253,20 +251,9 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
|
|||||||
}
|
}
|
||||||
Authentication current = this.securityContextHolderStrategy.getContext().getAuthentication();
|
Authentication current = this.securityContextHolderStrategy.getContext().getAuthentication();
|
||||||
if (current != null && current.isAuthenticated()) {
|
if (current != null && current.isAuthenticated()) {
|
||||||
authenticationResult = authenticationResult.toBuilder()
|
if (authenticationResult instanceof BuildableAuthentication buildable) {
|
||||||
// @formatter:off
|
authenticationResult = buildable.toBuilder().authentication(current).build();
|
||||||
.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
|
|
||||||
}
|
}
|
||||||
this.sessionStrategy.onAuthentication(authenticationResult, request, response);
|
this.sessionStrategy.onAuthentication(authenticationResult, request, response);
|
||||||
// Authentication success
|
// Authentication success
|
||||||
|
@ -17,8 +17,6 @@
|
|||||||
package org.springframework.security.web.authentication;
|
package org.springframework.security.web.authentication;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import jakarta.servlet.Filter;
|
import jakarta.servlet.Filter;
|
||||||
import jakarta.servlet.FilterChain;
|
import jakarta.servlet.FilterChain;
|
||||||
@ -33,7 +31,7 @@ import org.springframework.security.authentication.AuthenticationManager;
|
|||||||
import org.springframework.security.authentication.AuthenticationManagerResolver;
|
import org.springframework.security.authentication.AuthenticationManagerResolver;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.AuthenticationException;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.BuildableAuthentication;
|
||||||
import org.springframework.security.core.context.SecurityContext;
|
import org.springframework.security.core.context.SecurityContext;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||||
@ -189,20 +187,9 @@ public class AuthenticationFilter extends OncePerRequestFilter {
|
|||||||
}
|
}
|
||||||
Authentication current = this.securityContextHolderStrategy.getContext().getAuthentication();
|
Authentication current = this.securityContextHolderStrategy.getContext().getAuthentication();
|
||||||
if (current != null && current.isAuthenticated()) {
|
if (current != null && current.isAuthenticated()) {
|
||||||
authenticationResult = authenticationResult.toBuilder()
|
if (authenticationResult instanceof BuildableAuthentication buildable) {
|
||||||
// @formatter:off
|
authenticationResult = buildable.toBuilder().authentication(current).build();
|
||||||
.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
|
|
||||||
}
|
}
|
||||||
HttpSession session = request.getSession(false);
|
HttpSession session = request.getSession(false);
|
||||||
if (session != null) {
|
if (session != null) {
|
||||||
|
@ -17,8 +17,6 @@
|
|||||||
package org.springframework.security.web.authentication.preauth;
|
package org.springframework.security.web.authentication.preauth;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import jakarta.servlet.FilterChain;
|
import jakarta.servlet.FilterChain;
|
||||||
import jakarta.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
@ -37,7 +35,7 @@ import org.springframework.security.authentication.AuthenticationManager;
|
|||||||
import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent;
|
import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.AuthenticationException;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.BuildableAuthentication;
|
||||||
import org.springframework.security.core.context.SecurityContext;
|
import org.springframework.security.core.context.SecurityContext;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||||
@ -209,20 +207,9 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
|
|||||||
Authentication authenticationResult = this.authenticationManager.authenticate(authenticationRequest);
|
Authentication authenticationResult = this.authenticationManager.authenticate(authenticationRequest);
|
||||||
Authentication current = this.securityContextHolderStrategy.getContext().getAuthentication();
|
Authentication current = this.securityContextHolderStrategy.getContext().getAuthentication();
|
||||||
if (current != null && current.isAuthenticated()) {
|
if (current != null && current.isAuthenticated()) {
|
||||||
authenticationResult = authenticationResult.toBuilder()
|
if (authenticationResult instanceof BuildableAuthentication buildable) {
|
||||||
// @formatter:off
|
authenticationResult = buildable.toBuilder().authentication(current).build();
|
||||||
.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
|
|
||||||
}
|
}
|
||||||
successfulAuthentication(request, response, authenticationResult);
|
successfulAuthentication(request, response, authenticationResult);
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import java.util.Collection;
|
|||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||||
|
import org.springframework.security.core.BuildableAuthentication;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
@ -31,7 +32,8 @@ import org.springframework.util.Assert;
|
|||||||
* @author Ruud Senden
|
* @author Ruud Senden
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
*/
|
*/
|
||||||
public class PreAuthenticatedAuthenticationToken extends AbstractAuthenticationToken {
|
public class PreAuthenticatedAuthenticationToken extends AbstractAuthenticationToken
|
||||||
|
implements BuildableAuthentication {
|
||||||
|
|
||||||
private static final long serialVersionUID = 620L;
|
private static final long serialVersionUID = 620L;
|
||||||
|
|
||||||
|
@ -18,8 +18,6 @@ package org.springframework.security.web.authentication.www;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import jakarta.servlet.FilterChain;
|
import jakarta.servlet.FilterChain;
|
||||||
import jakarta.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
@ -33,7 +31,7 @@ import org.springframework.security.authentication.AuthenticationDetailsSource;
|
|||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.AuthenticationException;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.BuildableAuthentication;
|
||||||
import org.springframework.security.core.context.SecurityContext;
|
import org.springframework.security.core.context.SecurityContext;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||||
@ -191,20 +189,9 @@ public class BasicAuthenticationFilter extends OncePerRequestFilter {
|
|||||||
Authentication authResult = this.authenticationManager.authenticate(authRequest);
|
Authentication authResult = this.authenticationManager.authenticate(authRequest);
|
||||||
Authentication current = this.securityContextHolderStrategy.getContext().getAuthentication();
|
Authentication current = this.securityContextHolderStrategy.getContext().getAuthentication();
|
||||||
if (current != null && current.isAuthenticated()) {
|
if (current != null && current.isAuthenticated()) {
|
||||||
authResult = authResult.toBuilder()
|
if (authResult instanceof BuildableAuthentication buildable) {
|
||||||
// @formatter:off
|
authResult = buildable.toBuilder().authentication(current).build();
|
||||||
.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
|
|
||||||
}
|
}
|
||||||
SecurityContext context = this.securityContextHolderStrategy.createEmptyContext();
|
SecurityContext context = this.securityContextHolderStrategy.createEmptyContext();
|
||||||
context.setAuthentication(authResult);
|
context.setAuthentication(authResult);
|
||||||
|
@ -16,9 +16,7 @@
|
|||||||
|
|
||||||
package org.springframework.security.web.server.authentication;
|
package org.springframework.security.web.server.authentication;
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
@ -29,7 +27,7 @@ import org.springframework.security.authentication.ReactiveAuthenticationManager
|
|||||||
import org.springframework.security.authentication.ReactiveAuthenticationManagerResolver;
|
import org.springframework.security.authentication.ReactiveAuthenticationManagerResolver;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.AuthenticationException;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.BuildableAuthentication;
|
||||||
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
||||||
import org.springframework.security.core.context.SecurityContextImpl;
|
import org.springframework.security.core.context.SecurityContextImpl;
|
||||||
import org.springframework.security.web.server.WebFilterExchange;
|
import org.springframework.security.web.server.WebFilterExchange;
|
||||||
@ -141,20 +139,10 @@ public class AuthenticationWebFilter implements WebFilter {
|
|||||||
if (!current.isAuthenticated()) {
|
if (!current.isAuthenticated()) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return result.toBuilder()
|
if (!(result instanceof BuildableAuthentication buildable)) {
|
||||||
// @formatter:off
|
return result;
|
||||||
.authorities((a) -> {
|
}
|
||||||
Set<String> newAuthorities = a.stream()
|
return buildable.toBuilder().authentication(current).build();
|
||||||
.map(GrantedAuthority::getAuthority)
|
|
||||||
.collect(Collectors.toUnmodifiableSet());
|
|
||||||
for (GrantedAuthority currentAuthority : current.getAuthorities()) {
|
|
||||||
if (!newAuthorities.contains(currentAuthority.getAuthority())) {
|
|
||||||
a.add(currentAuthority);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.build();
|
|
||||||
// @formatter:on
|
|
||||||
}).switchIfEmpty(Mono.just(result));
|
}).switchIfEmpty(Mono.just(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ import java.util.Collection;
|
|||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||||
|
import org.springframework.security.core.BuildableAuthentication;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.security.web.webauthn.api.PublicKeyCredentialUserEntity;
|
import org.springframework.security.web.webauthn.api.PublicKeyCredentialUserEntity;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
@ -34,7 +35,7 @@ import org.springframework.util.Assert;
|
|||||||
* @since 6.4
|
* @since 6.4
|
||||||
* @see WebAuthnAuthenticationRequestToken
|
* @see WebAuthnAuthenticationRequestToken
|
||||||
*/
|
*/
|
||||||
public class WebAuthnAuthentication extends AbstractAuthenticationToken {
|
public class WebAuthnAuthentication extends AbstractAuthenticationToken implements BuildableAuthentication {
|
||||||
|
|
||||||
@Serial
|
@Serial
|
||||||
private static final long serialVersionUID = -4879907158750659197L;
|
private static final long serialVersionUID = -4879907158750659197L;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user