Add Authentication.Builder
This commit adds a new default method to Authentication for the purposes of creating a Builder based on the current authentication, allowing other authentications to be applied to it as a composite. It also adds Builders for each one of the authentication result classes. Issue gh-17861
This commit is contained in:
+69
@@ -20,8 +20,10 @@ import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.apereo.cas.client.validation.Assertion;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -153,6 +155,11 @@ public class CasAuthenticationToken extends AbstractAuthenticationToken implemen
|
||||
return this.userDetails;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder toBuilder() {
|
||||
return new Builder().apply(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
@@ -162,4 +169,66 @@ public class CasAuthenticationToken extends AbstractAuthenticationToken implemen
|
||||
return (sb.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder preserving the concrete {@link Authentication} type
|
||||
*
|
||||
* @since 7.0
|
||||
*/
|
||||
public static final class Builder extends AbstractAuthenticationBuilder<@NonNull CasAuthenticationToken, Builder> {
|
||||
|
||||
private Integer keyHash;
|
||||
|
||||
private Object principal;
|
||||
|
||||
private Object credentials;
|
||||
|
||||
private UserDetails userDetails;
|
||||
|
||||
private Assertion assertion;
|
||||
|
||||
private Builder() {
|
||||
|
||||
}
|
||||
|
||||
public Builder apply(CasAuthenticationToken authentication) {
|
||||
return super.apply(authentication).keyHash(authentication.keyHash)
|
||||
.principal(authentication.principal)
|
||||
.credentials(authentication.credentials)
|
||||
.userDetails(authentication.userDetails)
|
||||
.assertion(authentication.assertion);
|
||||
}
|
||||
|
||||
public Builder keyHash(Integer keyHash) {
|
||||
this.keyHash = keyHash;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder principal(Object principal) {
|
||||
this.principal = principal;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder credentials(Object credentials) {
|
||||
this.credentials = credentials;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder userDetails(UserDetails userDetails) {
|
||||
this.userDetails = userDetails;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder assertion(Assertion assertion) {
|
||||
this.assertion = assertion;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NonNull CasAuthenticationToken build(Collection<GrantedAuthority> authorities) {
|
||||
return new CasAuthenticationToken(this.keyHash, this.principal, this.credentials, authorities,
|
||||
this.userDetails, this.assertion);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+20
@@ -18,6 +18,7 @@ package org.springframework.security.cas.authentication;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apereo.cas.client.validation.Assertion;
|
||||
import org.apereo.cas.client.validation.AssertionImpl;
|
||||
@@ -26,6 +27,7 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.PasswordEncodedUser;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
@@ -155,4 +157,22 @@ public class CasAuthenticationTokenTests {
|
||||
assertThat(result.lastIndexOf("Credentials (Service/Proxy Ticket):") != -1).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toBuilderWhenApplyThenCopies() {
|
||||
Assertion assertionOne = new AssertionImpl("test");
|
||||
CasAuthenticationToken factorOne = new CasAuthenticationToken("key", "alice", "pass",
|
||||
AuthorityUtils.createAuthorityList("FACTOR_ONE"), PasswordEncodedUser.user(), assertionOne);
|
||||
Assertion assertionTwo = new AssertionImpl("test");
|
||||
CasAuthenticationToken factorTwo = new CasAuthenticationToken("yek", "bob", "ssap",
|
||||
AuthorityUtils.createAuthorityList("FACTOR_TWO"), PasswordEncodedUser.admin(), assertionTwo);
|
||||
CasAuthenticationToken authentication = factorOne.toBuilder().apply(factorTwo).build();
|
||||
Set<String> authorities = AuthorityUtils.authorityListToSet(authentication.getAuthorities());
|
||||
assertThat(authentication.getKeyHash()).isEqualTo(factorTwo.getKeyHash());
|
||||
assertThat(authentication.getPrincipal()).isEqualTo(factorTwo.getPrincipal());
|
||||
assertThat(authentication.getCredentials()).isEqualTo(factorTwo.getCredentials());
|
||||
assertThat(authentication.getUserDetails()).isEqualTo(factorTwo.getUserDetails());
|
||||
assertThat(authentication.getAssertion()).isEqualTo(factorTwo.getAssertion());
|
||||
assertThat(authorities).containsExactlyInAnyOrder("FACTOR_ONE", "FACTOR_TWO");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+34
@@ -20,6 +20,8 @@ import java.security.Principal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@@ -185,4 +187,36 @@ public abstract class AbstractAuthenticationToken implements Authentication, Cre
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
protected abstract static class AbstractAuthenticationBuilder<A extends Authentication, B extends AbstractAuthenticationBuilder<A, B>>
|
||||
implements Builder<A, B> {
|
||||
|
||||
private final Collection<GrantedAuthority> authorities = new HashSet<>();
|
||||
|
||||
protected AbstractAuthenticationBuilder() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public B authorities(Consumer<Collection<GrantedAuthority>> authorities) {
|
||||
authorities.accept(this.authorities);
|
||||
return (B) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public A build() {
|
||||
return build(this.authorities);
|
||||
}
|
||||
|
||||
@Override
|
||||
public B apply(Authentication token) {
|
||||
Assert.isTrue(token.isAuthenticated(), "cannot mutate an unauthenticated token");
|
||||
Assert.notNull(token.getPrincipal(), "principal cannot be null");
|
||||
this.authorities.addAll(token.getAuthorities());
|
||||
return (B) this;
|
||||
}
|
||||
|
||||
protected abstract A build(Collection<GrantedAuthority> authorities);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+47
@@ -18,7 +18,11 @@ package org.springframework.security.authentication;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Represents a remembered <code>Authentication</code>.
|
||||
@@ -88,6 +92,11 @@ public class RememberMeAuthenticationToken extends AbstractAuthenticationToken {
|
||||
return this.principal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder toBuilder() {
|
||||
return new Builder().apply(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!super.equals(obj)) {
|
||||
@@ -106,4 +115,42 @@ public class RememberMeAuthenticationToken extends AbstractAuthenticationToken {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder preserving the concrete {@link Authentication} type
|
||||
*
|
||||
* @since 7.0
|
||||
*/
|
||||
public static final class Builder extends AbstractAuthenticationBuilder<RememberMeAuthenticationToken, Builder> {
|
||||
|
||||
private @Nullable Integer keyHash;
|
||||
|
||||
private @Nullable Object principal;
|
||||
|
||||
private Builder() {
|
||||
|
||||
}
|
||||
|
||||
public Builder apply(RememberMeAuthenticationToken token) {
|
||||
return super.apply(token).keyHash(token.getKeyHash()).principal(token.getPrincipal());
|
||||
}
|
||||
|
||||
public Builder principal(Object principal) {
|
||||
this.principal = principal;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder keyHash(int keyHash) {
|
||||
this.keyHash = keyHash;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RememberMeAuthenticationToken build(Collection<GrantedAuthority> authorities) {
|
||||
Assert.notNull(this.keyHash, "keyHash cannot be null");
|
||||
Assert.notNull(this.principal, "principal cannot be null");
|
||||
return new RememberMeAuthenticationToken(this.keyHash, this.principal, authorities);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+48
@@ -19,8 +19,12 @@ package org.springframework.security.authentication;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* An {@link org.springframework.security.core.Authentication} implementation that is
|
||||
@@ -71,4 +75,48 @@ public class TestingAuthenticationToken extends AbstractAuthenticationToken {
|
||||
return this.principal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder toBuilder() {
|
||||
return new Builder().apply(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder preserving the concrete {@link Authentication} type
|
||||
*
|
||||
* @since 7.0
|
||||
*/
|
||||
public static final class Builder extends AbstractAuthenticationBuilder<TestingAuthenticationToken, Builder> {
|
||||
|
||||
private @Nullable Object principal;
|
||||
|
||||
private @Nullable Object credentials;
|
||||
|
||||
private Builder() {
|
||||
|
||||
}
|
||||
|
||||
public Builder apply(TestingAuthenticationToken authentication) {
|
||||
return super.apply(authentication).principal(authentication.getPrincipal())
|
||||
.credentials(authentication.getCredentials());
|
||||
}
|
||||
|
||||
public Builder principal(Object principal) {
|
||||
this.principal = principal;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder credentials(Object credentials) {
|
||||
this.credentials = credentials;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TestingAuthenticationToken build(Collection<GrantedAuthority> authorities) {
|
||||
Assert.notNull(this.principal, "principal cannot be null");
|
||||
Assert.notNull(this.credentials, "credentials cannot be null");
|
||||
return new TestingAuthenticationToken(this.principal, this.credentials, authorities);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+44
@@ -20,6 +20,7 @@ import java.util.Collection;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -124,4 +125,47 @@ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationT
|
||||
this.credentials = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<?, ?> toBuilder() {
|
||||
return new Builder<>().apply(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder preserving the concrete {@link Authentication} type
|
||||
*
|
||||
* @since 7.0
|
||||
*/
|
||||
public static class Builder<A extends UsernamePasswordAuthenticationToken, B extends Builder<A, B>>
|
||||
extends AbstractAuthenticationBuilder<A, B> {
|
||||
|
||||
private @Nullable Object principal;
|
||||
|
||||
private @Nullable Object credentials;
|
||||
|
||||
protected Builder() {
|
||||
}
|
||||
|
||||
public B apply(UsernamePasswordAuthenticationToken authentication) {
|
||||
return super.apply(authentication).principal(authentication.getPrincipal())
|
||||
.credentials(authentication.getCredentials());
|
||||
}
|
||||
|
||||
public B principal(Object principal) {
|
||||
this.principal = principal;
|
||||
return (B) this;
|
||||
}
|
||||
|
||||
public B credentials(@Nullable Object credentials) {
|
||||
this.credentials = credentials;
|
||||
return (B) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected A build(Collection<GrantedAuthority> authorities) {
|
||||
Assert.notNull(this.principal, "principal cannot be null");
|
||||
return (A) new UsernamePasswordAuthenticationToken(this.principal, this.credentials, authorities);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+46
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.security.authentication.jaas;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import javax.security.auth.login.LoginContext;
|
||||
@@ -23,7 +24,9 @@ import javax.security.auth.login.LoginContext;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* UsernamePasswordAuthenticationToken extension to carry the Jaas LoginContext that the
|
||||
@@ -52,4 +55,47 @@ public class JaasAuthenticationToken extends UsernamePasswordAuthenticationToken
|
||||
return this.loginContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder toBuilder() {
|
||||
return new Builder().apply(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder preserving the concrete {@link Authentication} type
|
||||
*
|
||||
* @since 7.0
|
||||
*/
|
||||
public static final class Builder
|
||||
extends UsernamePasswordAuthenticationToken.Builder<JaasAuthenticationToken, Builder> {
|
||||
|
||||
private @Nullable LoginContext loginContext;
|
||||
|
||||
private Builder() {
|
||||
|
||||
}
|
||||
|
||||
public Builder apply(JaasAuthenticationToken authentication) {
|
||||
return super.apply(authentication).loginContext(authentication.getLoginContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this {@link LoginContext}
|
||||
* @param loginContext the {@link LoginContext} to use
|
||||
* @return the {@link Builder} for further configuration
|
||||
*/
|
||||
public Builder loginContext(LoginContext loginContext) {
|
||||
this.loginContext = loginContext;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JaasAuthenticationToken build(Collection<GrantedAuthority> authorities) {
|
||||
UsernamePasswordAuthenticationToken token = super.build(authorities);
|
||||
Assert.notNull(this.loginContext, "loginContext cannot be null");
|
||||
return new JaasAuthenticationToken(token.getPrincipal(), token.getCredentials(),
|
||||
(List<GrantedAuthority>) token.getAuthorities(), this.loginContext);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+42
@@ -23,6 +23,7 @@ import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* The result of a successful one-time-token authentication
|
||||
@@ -53,4 +54,45 @@ public class OneTimeTokenAuthentication extends AbstractAuthenticationToken {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder toBuilder() {
|
||||
return new Builder().apply(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder for constructing a {@link OneTimeTokenAuthentication} instance
|
||||
*/
|
||||
public static final class Builder extends AbstractAuthenticationBuilder<OneTimeTokenAuthentication, Builder> {
|
||||
|
||||
private @Nullable Object principal;
|
||||
|
||||
private Builder() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply this {@link OneTimeTokenAuthentication}
|
||||
* @return the {@link Builder} for further configuration
|
||||
*/
|
||||
public Builder apply(OneTimeTokenAuthentication authentication) {
|
||||
return super.apply(authentication).principal(authentication.principal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this principal
|
||||
* @return the {@link Builder} for further configuration
|
||||
*/
|
||||
public Builder principal(Object principal) {
|
||||
this.principal = principal;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OneTimeTokenAuthentication build(Collection<GrantedAuthority> authorities) {
|
||||
Assert.notNull(this.principal, "principal cannot be null");
|
||||
return new OneTimeTokenAuthentication(this.principal, authorities);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,14 +16,17 @@
|
||||
|
||||
package org.springframework.security.core;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.security.Principal;
|
||||
import java.util.Collection;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Represents the token for an authentication request or for an authenticated principal
|
||||
@@ -54,6 +57,9 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
||||
*/
|
||||
public interface Authentication extends Principal, Serializable {
|
||||
|
||||
@Serial
|
||||
long serialVersionUID = -3884394378624019849L;
|
||||
|
||||
/**
|
||||
* Set by an <code>AuthenticationManager</code> to indicate the authorities that the
|
||||
* principal has been granted. Note that classes should not rely on this value as
|
||||
@@ -64,7 +70,7 @@ public interface Authentication extends Principal, Serializable {
|
||||
* instance.
|
||||
* </p>
|
||||
* @return the authorities granted to the principal, or an empty collection if the
|
||||
* token has not been authenticated. Never null.
|
||||
* token has not been authenticated. Never null.Saml2AssertAu
|
||||
*/
|
||||
Collection<? extends GrantedAuthority> getAuthorities();
|
||||
|
||||
@@ -136,4 +142,50 @@ public interface Authentication extends Principal, Serializable {
|
||||
*/
|
||||
void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Return an {@link Builder} based on this instance
|
||||
* @return an {@link Builder} for building a new {@link Authentication} based on this
|
||||
* instance
|
||||
* @since 7.0
|
||||
*/
|
||||
default Builder<?, ?> toBuilder() {
|
||||
return new NoopAuthenticationBuilder<>(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder based on a given {@link Authentication} instance
|
||||
*
|
||||
* @param <A> the type of {@link Authentication}
|
||||
* @author Josh Cummings
|
||||
* @since 7.0
|
||||
*/
|
||||
interface Builder<A extends Authentication, B extends Builder<A, B>> {
|
||||
|
||||
/**
|
||||
* Apply this {@link Authentication} to the builder.
|
||||
* <p>
|
||||
* By default, this method adds the authorities from {@code authentication} to
|
||||
* this builder
|
||||
* @return the {@link Builder} for further configuration
|
||||
*/
|
||||
default B apply(Authentication authentication) {
|
||||
Assert.isTrue(authentication.isAuthenticated(), "cannot apply an unauthenticated token");
|
||||
return authorities((a) -> a.addAll(authentication.getAuthorities()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply these authorities to the builder.
|
||||
* @param authorities the authorities to apply
|
||||
* @return the {@link Builder} for further configuration
|
||||
*/
|
||||
B authorities(Consumer<Collection<GrantedAuthority>> authorities);
|
||||
|
||||
/**
|
||||
* Build an {@link Authentication} instance
|
||||
* @return the {@link Authentication} instance
|
||||
*/
|
||||
A build();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.util.Collection;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* An adapter implementation of {@link Authentication.Builder} that provides a no-op
|
||||
* implementation for the principal, credentials, and authorities
|
||||
*
|
||||
* @param <A> the type of {@link Authentication}
|
||||
* @author Josh Cummings
|
||||
* @since 7.0
|
||||
*/
|
||||
class NoopAuthenticationBuilder<A extends Authentication>
|
||||
implements Authentication.Builder<A, NoopAuthenticationBuilder<A>> {
|
||||
|
||||
private A original;
|
||||
|
||||
NoopAuthenticationBuilder(A authentication) {
|
||||
Assert.isTrue(authentication.isAuthenticated(), "cannot mutate an unauthenticated token");
|
||||
Assert.notNull(authentication.getPrincipal(), "principal cannot be null");
|
||||
this.original = authentication;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NoopAuthenticationBuilder<A> authorities(Consumer<Collection<GrantedAuthority>> authorities) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public A build() {
|
||||
return this.original;
|
||||
}
|
||||
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.authentication;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken.AbstractAuthenticationBuilder;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
|
||||
class AbstractAuthenticationBuilderTests {
|
||||
|
||||
@Test
|
||||
void applyWhenUnauthenticatedThenErrors() {
|
||||
TestAbstractAuthenticationBuilder builder = new TestAbstractAuthenticationBuilder();
|
||||
TestingAuthenticationToken unauthenticated = new TestingAuthenticationToken("user", "password");
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> builder.apply(unauthenticated));
|
||||
}
|
||||
|
||||
@Test
|
||||
void applyWhenAuthoritiesThenAdds() {
|
||||
TestAbstractAuthenticationBuilder builder = new TestAbstractAuthenticationBuilder();
|
||||
TestingAuthenticationToken factorOne = new TestingAuthenticationToken("user", "pass", "FACTOR_ONE");
|
||||
TestingAuthenticationToken factorTwo = new TestingAuthenticationToken("user", "pass", "FACTOR_TWO");
|
||||
Authentication result = builder.apply(factorOne).apply(factorTwo).build();
|
||||
Set<String> authorities = AuthorityUtils.authorityListToSet(result.getAuthorities());
|
||||
assertThat(authorities).containsExactlyInAnyOrder("FACTOR_ONE", "FACTOR_TWO");
|
||||
}
|
||||
|
||||
private static final class TestAbstractAuthenticationBuilder
|
||||
extends AbstractAuthenticationBuilder<Authentication, TestAbstractAuthenticationBuilder> {
|
||||
|
||||
@Override
|
||||
protected Authentication build(Collection<GrantedAuthority> authorities) {
|
||||
return new TestingAuthenticationToken("user", "password", authorities);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+15
@@ -17,9 +17,11 @@
|
||||
package org.springframework.security.authentication;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -49,4 +51,17 @@ public class TestingAuthenticationTokenTests {
|
||||
assertThat(authenticated.isAuthenticated()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toBuilderWhenApplyThenCopies() {
|
||||
TestingAuthenticationToken factorOne = new TestingAuthenticationToken("alice", "pass",
|
||||
AuthorityUtils.createAuthorityList("FACTOR_ONE"));
|
||||
TestingAuthenticationToken factorTwo = new TestingAuthenticationToken("bob", "ssap",
|
||||
AuthorityUtils.createAuthorityList("FACTOR_TWO"));
|
||||
TestingAuthenticationToken result = factorOne.toBuilder().apply(factorTwo).build();
|
||||
Set<String> authorities = AuthorityUtils.authorityListToSet(result.getAuthorities());
|
||||
assertThat(result.getPrincipal()).isSameAs(factorTwo.getPrincipal());
|
||||
assertThat(result.getCredentials()).isSameAs(factorTwo.getCredentials());
|
||||
assertThat(authorities).containsExactlyInAnyOrder("FACTOR_ONE", "FACTOR_TWO");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+16
@@ -16,8 +16,11 @@
|
||||
|
||||
package org.springframework.security.authentication;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -85,4 +88,17 @@ public class UsernamePasswordAuthenticationTokenTests {
|
||||
assertThat(grantedToken.isAuthenticated()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toBuilderWhenApplyThenCopies() {
|
||||
UsernamePasswordAuthenticationToken factorOne = new UsernamePasswordAuthenticationToken("alice", "pass",
|
||||
AuthorityUtils.createAuthorityList("FACTOR_ONE"));
|
||||
UsernamePasswordAuthenticationToken factorTwo = new UsernamePasswordAuthenticationToken("bob", "ssap",
|
||||
AuthorityUtils.createAuthorityList("FACTOR_TWO"));
|
||||
Authentication authentication = factorOne.toBuilder().apply(factorTwo).build();
|
||||
Set<String> authorities = AuthorityUtils.authorityListToSet(authentication.getAuthorities());
|
||||
assertThat(authentication.getPrincipal()).isEqualTo("bob");
|
||||
assertThat(authentication.getCredentials()).isEqualTo("ssap");
|
||||
assertThat(authorities).containsExactlyInAnyOrder("FACTOR_ONE", "FACTOR_TWO");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.authentication.jaas;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.security.auth.login.LoginContext;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
class JaasAuthenticationTokenTests {
|
||||
|
||||
@Test
|
||||
void toBuilderWhenApplyThenCopies() {
|
||||
JaasAuthenticationToken factorOne = new JaasAuthenticationToken("alice", "pass",
|
||||
AuthorityUtils.createAuthorityList("FACTOR_ONE"), mock(LoginContext.class));
|
||||
JaasAuthenticationToken factorTwo = new JaasAuthenticationToken("bob", "ssap",
|
||||
AuthorityUtils.createAuthorityList("FACTOR_TWO"), mock(LoginContext.class));
|
||||
JaasAuthenticationToken result = factorOne.toBuilder().apply(factorTwo).build();
|
||||
Set<String> authorities = AuthorityUtils.authorityListToSet(result.getAuthorities());
|
||||
assertThat(result.getPrincipal()).isSameAs(factorTwo.getPrincipal());
|
||||
assertThat(result.getCredentials()).isSameAs(factorTwo.getCredentials());
|
||||
assertThat(result.getLoginContext()).isSameAs(factorTwo.getLoginContext());
|
||||
assertThat(authorities).containsExactlyInAnyOrder("FACTOR_ONE", "FACTOR_TWO");
|
||||
}
|
||||
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.authentication.ott;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class OneTimeTokenAuthenticationTests {
|
||||
|
||||
@Test
|
||||
void toBuilderWhenApplyThenCopies() {
|
||||
OneTimeTokenAuthentication factorOne = new OneTimeTokenAuthentication("alice",
|
||||
AuthorityUtils.createAuthorityList("FACTOR_ONE"));
|
||||
OneTimeTokenAuthentication factorTwo = new OneTimeTokenAuthentication("bob",
|
||||
AuthorityUtils.createAuthorityList("FACTOR_TWO"));
|
||||
OneTimeTokenAuthentication result = factorOne.toBuilder().apply(factorTwo).build();
|
||||
Set<String> authorities = AuthorityUtils.authorityListToSet(result.getAuthorities());
|
||||
assertThat(result.getPrincipal()).isSameAs(factorTwo.getPrincipal());
|
||||
assertThat(authorities).containsExactlyInAnyOrder("FACTOR_ONE", "FACTOR_TWO");
|
||||
}
|
||||
|
||||
}
|
||||
+42
@@ -85,4 +85,46 @@ public class OAuth2AuthenticationToken extends AbstractAuthenticationToken {
|
||||
return this.authorizedClientRegistrationId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder toBuilder() {
|
||||
return new Builder().apply(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder preserving the concrete {@link Authentication} type
|
||||
*
|
||||
* @since 7.0
|
||||
*/
|
||||
public static final class Builder extends AbstractAuthenticationBuilder<OAuth2AuthenticationToken, Builder> {
|
||||
|
||||
private OAuth2User principal;
|
||||
|
||||
private String authorizedClientRegistrationId;
|
||||
|
||||
private Builder() {
|
||||
|
||||
}
|
||||
|
||||
public Builder apply(OAuth2AuthenticationToken authentication) {
|
||||
return super.apply(authentication).principal(authentication.getPrincipal())
|
||||
.authorizedClientRegistrationId(authentication.authorizedClientRegistrationId);
|
||||
}
|
||||
|
||||
public Builder principal(OAuth2User principal) {
|
||||
this.principal = principal;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder authorizedClientRegistrationId(String authorizedClientRegistrationId) {
|
||||
this.authorizedClientRegistrationId = authorizedClientRegistrationId;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OAuth2AuthenticationToken build(Collection<GrantedAuthority> authorities) {
|
||||
return new OAuth2AuthenticationToken(this.principal, authorities, this.authorizedClientRegistrationId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+16
@@ -18,12 +18,15 @@ package org.springframework.security.oauth2.client.authentication;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||
import org.springframework.security.oauth2.core.user.TestOAuth2Users;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
@@ -82,4 +85,17 @@ public class OAuth2AuthenticationTokenTests {
|
||||
assertThat(authentication.isAuthenticated()).isEqualTo(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toBuilderWhenApplyThenCopies() {
|
||||
OAuth2AuthenticationToken factorOne = new OAuth2AuthenticationToken(TestOAuth2Users.create(),
|
||||
AuthorityUtils.createAuthorityList("FACTOR_ONE"), "alice");
|
||||
OAuth2AuthenticationToken factorTwo = new OAuth2AuthenticationToken(TestOAuth2Users.create(),
|
||||
AuthorityUtils.createAuthorityList("FACTOR_TWO"), "bob");
|
||||
OAuth2AuthenticationToken result = factorOne.toBuilder().apply(factorTwo).build();
|
||||
Set<String> authorities = AuthorityUtils.authorityListToSet(result.getAuthorities());
|
||||
assertThat(result.getPrincipal()).isSameAs(factorTwo.getPrincipal());
|
||||
assertThat(result.getAuthorizedClientRegistrationId()).isSameAs(factorTwo.getAuthorizedClientRegistrationId());
|
||||
assertThat(authorities).containsExactlyInAnyOrder("FACTOR_ONE", "FACTOR_TWO");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+43
@@ -21,6 +21,7 @@ import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.Transient;
|
||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||
@@ -61,4 +62,46 @@ public class BearerTokenAuthentication extends AbstractOAuth2TokenAuthentication
|
||||
return this.attributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder toBuilder() {
|
||||
return new Builder().apply(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder preserving the concrete {@link Authentication} type
|
||||
*
|
||||
* @since 7.0
|
||||
*/
|
||||
public static final class Builder extends AbstractAuthenticationBuilder<BearerTokenAuthentication, Builder> {
|
||||
|
||||
private OAuth2AuthenticatedPrincipal principal;
|
||||
|
||||
private OAuth2AccessToken token;
|
||||
|
||||
private Builder() {
|
||||
|
||||
}
|
||||
|
||||
public Builder apply(BearerTokenAuthentication authentication) {
|
||||
return super.apply(authentication).principal((OAuth2AuthenticatedPrincipal) authentication.getPrincipal())
|
||||
.credentials(authentication.getToken());
|
||||
}
|
||||
|
||||
public Builder principal(OAuth2AuthenticatedPrincipal principal) {
|
||||
this.principal = principal;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder credentials(OAuth2AccessToken credentials) {
|
||||
this.token = credentials;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BearerTokenAuthentication build(Collection<GrantedAuthority> authorities) {
|
||||
return new BearerTokenAuthentication(this.principal, this.token, authorities);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+42
@@ -19,6 +19,7 @@ package org.springframework.security.oauth2.server.resource.authentication;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.Transient;
|
||||
import org.springframework.security.oauth2.jwt.Jwt;
|
||||
@@ -84,4 +85,45 @@ public class JwtAuthenticationToken extends AbstractOAuth2TokenAuthenticationTok
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder toBuilder() {
|
||||
return new Builder().apply(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder preserving the concrete {@link Authentication} type
|
||||
*
|
||||
* @since 7.0
|
||||
*/
|
||||
public static final class Builder extends AbstractAuthenticationBuilder<JwtAuthenticationToken, Builder> {
|
||||
|
||||
private Jwt jwt;
|
||||
|
||||
private String name;
|
||||
|
||||
private Builder() {
|
||||
|
||||
}
|
||||
|
||||
public Builder apply(JwtAuthenticationToken token) {
|
||||
return super.apply(token).jwt(token.getToken()).name(token.getName());
|
||||
}
|
||||
|
||||
public Builder jwt(Jwt jwt) {
|
||||
this.jwt = jwt;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JwtAuthenticationToken build(Collection<GrantedAuthority> authorities) {
|
||||
return new JwtAuthenticationToken(this.jwt, authorities, this.name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+18
@@ -23,6 +23,7 @@ import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import net.minidev.json.JSONObject;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@@ -34,6 +35,7 @@ import org.springframework.security.oauth2.core.DefaultOAuth2AuthenticatedPrinci
|
||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenIntrospectionClaimNames;
|
||||
import org.springframework.security.oauth2.core.TestOAuth2AuthenticatedPrincipals;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
@@ -151,4 +153,20 @@ public class BearerTokenAuthenticationTests {
|
||||
token.toString();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toBuilderWhenApplyThenCopies() {
|
||||
BearerTokenAuthentication factorOne = new BearerTokenAuthentication(TestOAuth2AuthenticatedPrincipals.active(),
|
||||
this.token, AuthorityUtils.createAuthorityList("FACTOR_ONE"));
|
||||
BearerTokenAuthentication factorTwo = new BearerTokenAuthentication(
|
||||
TestOAuth2AuthenticatedPrincipals.active((m) -> m.put("k", "v")),
|
||||
new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "nekot", Instant.now(),
|
||||
Instant.now().plusSeconds(3600)),
|
||||
AuthorityUtils.createAuthorityList("FACTOR_TWO"));
|
||||
BearerTokenAuthentication authentication = factorOne.toBuilder().apply(factorTwo).build();
|
||||
Set<String> authorities = AuthorityUtils.authorityListToSet(authentication.getAuthorities());
|
||||
assertThat(authentication.getPrincipal()).isSameAs(factorTwo.getPrincipal());
|
||||
assertThat(authentication.getToken()).isSameAs(factorTwo.getToken());
|
||||
assertThat(authorities).containsExactlyInAnyOrder("FACTOR_ONE", "FACTOR_TWO");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+14
@@ -17,6 +17,7 @@
|
||||
package org.springframework.security.oauth2.server.resource.authentication;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
@@ -115,6 +116,19 @@ public class JwtAuthenticationTokenTests {
|
||||
assertThat(new JwtAuthenticationToken(jwt).getName()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toBuilderWhenApplyThenCopies() {
|
||||
JwtAuthenticationToken factorOne = new JwtAuthenticationToken(builder().claim("c", "v").build(),
|
||||
AuthorityUtils.createAuthorityList("FACTOR_ONE"), "alice");
|
||||
JwtAuthenticationToken factorTwo = new JwtAuthenticationToken(builder().claim("d", "w").build(),
|
||||
AuthorityUtils.createAuthorityList("FACTOR_TWO"), "bob");
|
||||
JwtAuthenticationToken result = factorOne.toBuilder().apply(factorTwo).build();
|
||||
Set<String> authorities = AuthorityUtils.authorityListToSet(result.getAuthorities());
|
||||
assertThat(result.getPrincipal()).isSameAs(factorTwo.getPrincipal());
|
||||
assertThat(result.getName()).isSameAs(factorTwo.getName());
|
||||
assertThat(authorities).containsExactlyInAnyOrder("FACTOR_ONE", "FACTOR_TWO");
|
||||
}
|
||||
|
||||
private Jwt.Builder builder() {
|
||||
return Jwt.withTokenValue("token").header("alg", JwsAlgorithms.RS256);
|
||||
}
|
||||
|
||||
+55
@@ -19,6 +19,9 @@ package org.springframework.security.saml2.provider.service.authentication;
|
||||
import java.io.Serial;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.jspecify.annotations.NonNull;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
/**
|
||||
@@ -62,4 +65,56 @@ public class Saml2AssertionAuthentication extends Saml2Authentication {
|
||||
return this.relyingPartyRegistrationId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder toBuilder() {
|
||||
return new Builder().apply(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder preserving the concrete {@link Authentication} type
|
||||
*
|
||||
* @since 7.0
|
||||
*/
|
||||
public static final class Builder
|
||||
extends AbstractAuthenticationBuilder<@NonNull Saml2AssertionAuthentication, @NonNull Builder> {
|
||||
|
||||
private Object principal;
|
||||
|
||||
private Saml2ResponseAssertionAccessor assertion;
|
||||
|
||||
private String relyingPartyRegistrationId;
|
||||
|
||||
private Builder() {
|
||||
|
||||
}
|
||||
|
||||
public Builder apply(Saml2AssertionAuthentication authentication) {
|
||||
return super.apply(authentication).principal(authentication.getPrincipal())
|
||||
.assertion(authentication.assertion)
|
||||
.relyingPartyRegistrationId(authentication.relyingPartyRegistrationId);
|
||||
}
|
||||
|
||||
public Builder principal(Object principal) {
|
||||
this.principal = principal;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder assertion(Saml2ResponseAssertionAccessor assertion) {
|
||||
this.assertion = assertion;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder relyingPartyRegistrationId(String relyingPartyRegistrationId) {
|
||||
this.relyingPartyRegistrationId = relyingPartyRegistrationId;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Saml2AssertionAuthentication build(Collection<GrantedAuthority> authorities) {
|
||||
return new Saml2AssertionAuthentication(this.principal, this.assertion, authorities,
|
||||
this.relyingPartyRegistrationId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.saml2.provider.service.authentication;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class Saml2AssertionAuthenticationTests {
|
||||
|
||||
@Test
|
||||
void toBuilderWhenApplyThenCopies() {
|
||||
Saml2ResponseAssertion.Builder prototype = Saml2ResponseAssertion.withResponseValue("response");
|
||||
Saml2AssertionAuthentication factorOne = new Saml2AssertionAuthentication("alice",
|
||||
prototype.nameId("alice").build(), AuthorityUtils.createAuthorityList("FACTOR_ONE"), "alice");
|
||||
Saml2AssertionAuthentication factorTwo = new Saml2AssertionAuthentication("bob",
|
||||
prototype.nameId("alice").build(), AuthorityUtils.createAuthorityList("FACTOR_TWO"), "bob");
|
||||
Saml2AssertionAuthentication result = factorOne.toBuilder().apply(factorTwo).build();
|
||||
Set<String> authorities = AuthorityUtils.authorityListToSet(result.getAuthorities());
|
||||
assertThat(result.getPrincipal()).isSameAs(factorTwo.getPrincipal());
|
||||
assertThat(result.getCredentials()).isSameAs(factorTwo.getCredentials());
|
||||
assertThat(result.getRelyingPartyRegistrationId()).isSameAs(factorTwo.getRelyingPartyRegistrationId());
|
||||
assertThat(authorities).containsExactlyInAnyOrder("FACTOR_ONE", "FACTOR_TWO");
|
||||
}
|
||||
|
||||
}
|
||||
+43
@@ -21,6 +21,7 @@ import java.util.Collection;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
/**
|
||||
@@ -82,4 +83,46 @@ public class PreAuthenticatedAuthenticationToken extends AbstractAuthenticationT
|
||||
return this.principal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder toBuilder() {
|
||||
return new Builder().apply(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder preserving the concrete {@link Authentication} type
|
||||
*
|
||||
* @since 7.0
|
||||
*/
|
||||
public static final class Builder
|
||||
extends AbstractAuthenticationBuilder<PreAuthenticatedAuthenticationToken, Builder> {
|
||||
|
||||
private Object principal;
|
||||
|
||||
private Object credentials;
|
||||
|
||||
private Builder() {
|
||||
|
||||
}
|
||||
|
||||
public Builder apply(PreAuthenticatedAuthenticationToken token) {
|
||||
return super.apply(token).principal(token.getPrincipal()).credentials(token.getCredentials());
|
||||
}
|
||||
|
||||
public Builder principal(Object principal) {
|
||||
this.principal = principal;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder credentials(Object credentials) {
|
||||
this.credentials = credentials;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PreAuthenticatedAuthenticationToken build(Collection<GrantedAuthority> authorities) {
|
||||
return new PreAuthenticatedAuthenticationToken(this.principal, this.credentials, authorities);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+14
@@ -18,6 +18,7 @@ package org.springframework.security.web.authentication.preauth;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -73,4 +74,17 @@ public class PreAuthenticatedAuthenticationTokenTests {
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toBuilderWhenApplyThenCopies() {
|
||||
PreAuthenticatedAuthenticationToken factorOne = new PreAuthenticatedAuthenticationToken("alice", "pass",
|
||||
AuthorityUtils.createAuthorityList("FACTOR_ONE"));
|
||||
PreAuthenticatedAuthenticationToken factorTwo = new PreAuthenticatedAuthenticationToken("bob", "ssap",
|
||||
AuthorityUtils.createAuthorityList("FACTOR_TWO"));
|
||||
PreAuthenticatedAuthenticationToken result = factorOne.toBuilder().apply(factorTwo).build();
|
||||
Set<String> authorities = AuthorityUtils.authorityListToSet(result.getAuthorities());
|
||||
assertThat(result.getPrincipal()).isSameAs(factorTwo.getPrincipal());
|
||||
assertThat(result.getCredentials()).isSameAs(factorTwo.getCredentials());
|
||||
assertThat(authorities).containsExactlyInAnyOrder("FACTOR_ONE", "FACTOR_TWO");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+35
@@ -22,6 +22,7 @@ import java.util.Collection;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.web.webauthn.api.PublicKeyCredentialUserEntity;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -69,4 +70,38 @@ public class WebAuthnAuthentication extends AbstractAuthenticationToken {
|
||||
return this.principal.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder toBuilder() {
|
||||
return new Builder().apply(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder preserving the concrete {@link Authentication} type
|
||||
*
|
||||
* @since 7.0
|
||||
*/
|
||||
public static final class Builder extends AbstractAuthenticationBuilder<WebAuthnAuthentication, Builder> {
|
||||
|
||||
private PublicKeyCredentialUserEntity principal;
|
||||
|
||||
private Builder() {
|
||||
|
||||
}
|
||||
|
||||
public Builder apply(WebAuthnAuthentication authentication) {
|
||||
return super.apply(authentication).principal(authentication.getPrincipal());
|
||||
}
|
||||
|
||||
public Builder principal(PublicKeyCredentialUserEntity principal) {
|
||||
this.principal = principal;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected WebAuthnAuthentication build(Collection<GrantedAuthority> authorities) {
|
||||
return new WebAuthnAuthentication(this.principal, authorities);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+15
@@ -17,6 +17,7 @@
|
||||
package org.springframework.security.web.webauthn.authentication;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -55,4 +56,18 @@ class WebAuthnAuthenticationTests {
|
||||
assertThat(authentication.isAuthenticated()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void toBuilderWhenApplyThenCopies() {
|
||||
PublicKeyCredentialUserEntity alice = TestPublicKeyCredentialUserEntities.userEntity().build();
|
||||
WebAuthnAuthentication factorOne = new WebAuthnAuthentication(alice,
|
||||
AuthorityUtils.createAuthorityList("FACTOR_ONE"));
|
||||
PublicKeyCredentialUserEntity bob = TestPublicKeyCredentialUserEntities.userEntity().build();
|
||||
WebAuthnAuthentication factorTwo = new WebAuthnAuthentication(bob,
|
||||
AuthorityUtils.createAuthorityList("FACTOR_TWO"));
|
||||
WebAuthnAuthentication result = factorOne.toBuilder().apply(factorTwo).build();
|
||||
Set<String> authorities = AuthorityUtils.authorityListToSet(result.getAuthorities());
|
||||
assertThat(result.getPrincipal()).isSameAs(factorTwo.getPrincipal());
|
||||
assertThat(authorities).containsExactlyInAnyOrder("FACTOR_ONE", "FACTOR_TWO");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user