1
0
mirror of synced 2026-08-06 02:08:01 +00:00

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:
Josh Cummings
2025-08-22 16:21:26 -06:00
parent eeb4574bb3
commit a201a2b862
27 changed files with 1016 additions and 1 deletions
@@ -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);
}
}
}
@@ -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");
}
}