1
0
mirror of synced 2026-05-23 13:53:17 +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
@@ -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);
}
}
}
@@ -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");
}
}