1
0
mirror of synced 2026-05-22 21:33:16 +00:00

Polish Builders

- Added remaining properties
- Removed apply method since Spring Security isn't using
it right now
- Made builders extensible since the authentications are
extensible

Issue gh-17861
This commit is contained in:
Josh Cummings
2025-08-29 13:13:09 -06:00
parent 44fef786aa
commit a0fe6a5fee
37 changed files with 662 additions and 379 deletions
@@ -19,10 +19,11 @@ package org.springframework.security.saml2.provider.service.authentication;
import java.io.Serial;
import java.util.Collection;
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.util.Assert;
/**
* An authentication based off of a SAML 2.0 Assertion
@@ -56,6 +57,12 @@ public class Saml2AssertionAuthentication extends Saml2Authentication {
setAuthenticated(true);
}
protected Saml2AssertionAuthentication(Builder<?> builder) {
super(builder);
this.assertion = builder.assertion;
this.relyingPartyRegistrationId = builder.relyingPartyRegistrationId;
}
@Override
public Saml2ResponseAssertionAccessor getCredentials() {
return this.assertion;
@@ -66,8 +73,8 @@ public class Saml2AssertionAuthentication extends Saml2Authentication {
}
@Override
public Builder toBuilder() {
return new Builder().apply(this);
public Builder<?> toBuilder() {
return new Builder<>(this);
}
/**
@@ -75,44 +82,35 @@ public class Saml2AssertionAuthentication extends Saml2Authentication {
*
* @since 7.0
*/
public static final class Builder
extends AbstractAuthenticationBuilder<@NonNull Saml2AssertionAuthentication, @NonNull Builder> {
private Object principal;
public static class Builder<B extends Builder<B>>
extends Saml2Authentication.Builder<Saml2ResponseAssertionAccessor, B> {
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;
protected Builder(Saml2AssertionAuthentication token) {
super(token);
this.assertion = token.assertion;
this.relyingPartyRegistrationId = token.relyingPartyRegistrationId;
}
@Override
protected Saml2AssertionAuthentication build(Collection<GrantedAuthority> authorities) {
return new Saml2AssertionAuthentication(this.principal, this.assertion, authorities,
this.relyingPartyRegistrationId);
public B credentials(@Nullable Saml2ResponseAssertionAccessor credentials) {
saml2Response(credentials.getResponseValue());
Assert.notNull(credentials, "assertion cannot be null");
this.assertion = credentials;
return (B) this;
}
public B relyingPartyRegistrationId(String relyingPartyRegistrationId) {
this.relyingPartyRegistrationId = relyingPartyRegistrationId;
return (B) this;
}
@Override
public Saml2AssertionAuthentication build() {
return new Saml2AssertionAuthentication(this);
}
}
@@ -19,6 +19,8 @@ package org.springframework.security.saml2.provider.service.authentication;
import java.io.Serial;
import java.util.Collection;
import org.jspecify.annotations.Nullable;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.AuthenticatedPrincipal;
import org.springframework.security.core.Authentication;
@@ -69,6 +71,12 @@ public class Saml2Authentication extends AbstractAuthenticationToken {
setAuthenticated(true);
}
Saml2Authentication(Builder<?, ?> builder) {
super(builder);
this.principal = builder.principal;
this.saml2Response = builder.saml2Response;
}
@Override
public Object getPrincipal() {
return this.principal;
@@ -87,4 +95,29 @@ public class Saml2Authentication extends AbstractAuthenticationToken {
return getSaml2Response();
}
abstract static class Builder<C, B extends Builder<C, B>> extends AbstractAuthenticationBuilder<Object, C, B> {
private Object principal;
String saml2Response;
Builder(Saml2Authentication token) {
super(token);
this.principal = token.principal;
this.saml2Response = token.saml2Response;
}
@Override
public B principal(@Nullable Object principal) {
Assert.notNull(principal, "principal cannot be null");
this.principal = principal;
return (B) this;
}
void saml2Response(String saml2Response) {
this.saml2Response = saml2Response;
}
}
}
@@ -33,7 +33,12 @@ class Saml2AssertionAuthenticationTests {
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();
Saml2AssertionAuthentication result = factorOne.toBuilder()
.authorities((a) -> a.addAll(factorTwo.getAuthorities()))
.principal(factorTwo.getPrincipal())
.credentials(factorTwo.getCredentials())
.relyingPartyRegistrationId(factorTwo.getRelyingPartyRegistrationId())
.build();
Set<String> authorities = AuthorityUtils.authorityListToSet(result.getAuthorities());
assertThat(result.getPrincipal()).isSameAs(factorTwo.getPrincipal());
assertThat(result.getCredentials()).isSameAs(factorTwo.getCredentials());