Browse Source

Add Internal Authentication Implementations

This commit allows a default implementation of
Authentication.Builder that performs the builder
operations. In this way, authorities and other previous
authentication material can still be effectively be
propagated in the event a custom authentication does
not implement the method.

Issue gh-17861
Josh Cummings 3 weeks ago
parent
commit
4744752a1b

+ 2 - 2
core/src/main/java/org/springframework/security/core/Authentication.java

@@ -65,7 +65,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.Saml2AssertAu
+	 * token has not been authenticated. Never null.
 	 */
 	Collection<? extends GrantedAuthority> getAuthorities();
 
@@ -144,7 +144,7 @@ public interface Authentication extends Principal, Serializable {
 	 * @since 7.0
 	 */
 	default Builder<?, ?, ?> toBuilder() {
-		return new NoopAuthenticationBuilder(this);
+		return new SimpleAuthentication.Builder(this);
 	}
 
 	/**

+ 0 - 69
core/src/main/java/org/springframework/security/core/NoopAuthenticationBuilder.java

@@ -1,69 +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.util.Collection;
-import java.util.function.Consumer;
-
-import org.jspecify.annotations.Nullable;
-
-/**
- * An adapter implementation of {@link Authentication.Builder} that provides a no-op
- * implementation for the principal, credentials, and authorities
- *
- * @author Josh Cummings
- * @since 7.0
- */
-class NoopAuthenticationBuilder implements Authentication.Builder<Object, Object, NoopAuthenticationBuilder> {
-
-	private Authentication original;
-
-	NoopAuthenticationBuilder(Authentication authentication) {
-		this.original = authentication;
-	}
-
-	@Override
-	public NoopAuthenticationBuilder authenticated(boolean authenticated) {
-		return this;
-	}
-
-	@Override
-	public NoopAuthenticationBuilder principal(@Nullable Object principal) {
-		return this;
-	}
-
-	@Override
-	public NoopAuthenticationBuilder details(@Nullable Object details) {
-		return this;
-	}
-
-	@Override
-	public NoopAuthenticationBuilder credentials(@Nullable Object credentials) {
-		return this;
-	}
-
-	@Override
-	public NoopAuthenticationBuilder authorities(Consumer<Collection<GrantedAuthority>> authorities) {
-		return this;
-	}
-
-	@Override
-	public Authentication build() {
-		return this.original;
-	}
-
-}

+ 143 - 0
core/src/main/java/org/springframework/security/core/SimpleAuthentication.java

@@ -0,0 +1,143 @@
+/*
+ * 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.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<Object, Object, Builder> {
+
+		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.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);
+		}
+
+	}
+
+}