Kaynağa Gözat

Create AuthorizationManagerFactories.multiFactor

Closes gh-18032
Rob Winch 3 gün önce
ebeveyn
işleme
702878acae
14 değiştirilmiş dosya ile 138 ekleme ve 140 silme
  1. 4 3
      config/src/main/java/org/springframework/security/config/annotation/authorization/GlobalMultiFactorAuthenticationConfiguration.java
  2. 3 3
      core/src/main/java/org/springframework/security/authorization/AllRequiredFactorsAuthorizationManager.java
  3. 102 0
      core/src/main/java/org/springframework/security/authorization/AuthorizationManagerFactories.java
  4. 0 75
      core/src/main/java/org/springframework/security/authorization/DefaultAuthorizationManagerFactory.java
  5. 2 1
      core/src/test/java/org/springframework/security/authorization/AllRequiredFactorsAuthorizationManagerTests.java
  6. 6 38
      core/src/test/java/org/springframework/security/authorization/AuthorizationManagerFactoryTests.java
  7. 1 1
      docs/modules/ROOT/pages/servlet/authentication/architecture.adoc
  8. 2 1
      docs/modules/ROOT/pages/servlet/authentication/mfa.adoc
  9. 3 3
      docs/src/test/java/org/springframework/security/docs/servlet/authentication/authorizationmanagerfactory/UseAuthorizationManagerFactoryConfiguration.java
  10. 3 3
      docs/src/test/java/org/springframework/security/docs/servlet/authentication/obtainingmoreauthorization/MissingAuthorityConfiguration.java
  11. 3 3
      docs/src/test/java/org/springframework/security/docs/servlet/authentication/selectivemfa/SelectiveMfaConfiguration.java
  12. 3 3
      docs/src/test/kotlin/org/springframework/security/kt/docs/servlet/authentication/authorizationmanagerfactory/UseAuthorizationManagerFactoryConfiguration.kt
  13. 3 3
      docs/src/test/kotlin/org/springframework/security/kt/docs/servlet/authentication/obtainingmoreauthorization/MissingAuthorityConfiguration.kt
  14. 3 3
      docs/src/test/kotlin/org/springframework/security/kt/docs/servlet/authentication/selectivemfa/SelectiveMfaConfiguration.kt

+ 4 - 3
config/src/main/java/org/springframework/security/config/annotation/authorization/GlobalMultiFactorAuthenticationConfiguration.java

@@ -23,6 +23,7 @@ import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.ImportAware;
 import org.springframework.core.type.AnnotationMetadata;
 import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
+import org.springframework.security.authorization.AuthorizationManagerFactories;
 import org.springframework.security.authorization.DefaultAuthorizationManagerFactory;
 
 /**
@@ -39,9 +40,9 @@ class GlobalMultiFactorAuthenticationConfiguration implements ImportAware {
 
 	@Bean
 	DefaultAuthorizationManagerFactory authorizationManagerFactory(ObjectProvider<RoleHierarchy> roleHierarchy) {
-		DefaultAuthorizationManagerFactory.Builder<Object> builder = DefaultAuthorizationManagerFactory.builder()
-			.requireAdditionalAuthorities(this.authorities);
-		roleHierarchy.ifAvailable(builder::roleHierarchy);
+		AuthorizationManagerFactories.AdditionalRequiredFactorsBuilder<Object> builder = AuthorizationManagerFactories
+			.multiFactor()
+			.requireFactors(this.authorities);
 		return builder.build();
 	}
 

+ 3 - 3
core/src/main/java/org/springframework/security/authorization/AllRequiredFactorsAuthorizationManager.java

@@ -146,8 +146,8 @@ public final class AllRequiredFactorsAuthorizationManager<T> implements Authoriz
 	 * Creates a new {@link Builder}
 	 * @return
 	 */
-	public static Builder builder() {
-		return new Builder();
+	public static <T> Builder<T> builder() {
+		return new Builder<>();
 	}
 
 	/**
@@ -156,7 +156,7 @@ public final class AllRequiredFactorsAuthorizationManager<T> implements Authoriz
 	 * @author Rob Winch
 	 * @since 7.0
 	 */
-	public static final class Builder {
+	public static final class Builder<T> {
 
 		private List<RequiredFactor> requiredFactors = new ArrayList<>();
 

+ 102 - 0
core/src/main/java/org/springframework/security/authorization/AuthorizationManagerFactories.java

@@ -0,0 +1,102 @@
+/*
+ * Copyright 2002-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.authorization;
+
+import java.util.function.Consumer;
+
+/**
+ * Creates common {@link AuthorizationManagerFactory} instances.
+ *
+ * @author Rob Winch
+ * @since 7.0
+ * @see DefaultAuthorizationManagerFactory
+ */
+public final class AuthorizationManagerFactories {
+
+	private AuthorizationManagerFactories() {
+	}
+
+	/**
+	 * Creates a {@link AdditionalRequiredFactorsBuilder} that helps build an
+	 * {@link AuthorizationManager} to set on
+	 * {@link DefaultAuthorizationManagerFactory#setAdditionalAuthorization(AuthorizationManager)}
+	 * for multifactor authentication.
+	 * <p>
+	 * Does not affect {@code anonymous}, {@code permitAll}, or {@code denyAll}.
+	 * @param <T> the secured object type
+	 * @return a factory configured with the required authorities
+	 */
+	public static <T> AdditionalRequiredFactorsBuilder<T> multiFactor() {
+		return new AdditionalRequiredFactorsBuilder<>();
+	}
+
+	/**
+	 * A builder that allows creating {@link DefaultAuthorizationManagerFactory} with
+	 * additional requirements for {@link RequiredFactor}s.
+	 *
+	 * @param <T> the type for the {@link DefaultAuthorizationManagerFactory}
+	 * @author Rob Winch
+	 */
+	public static final class AdditionalRequiredFactorsBuilder<T> {
+
+		private final AllRequiredFactorsAuthorizationManager.Builder<T> factors = AllRequiredFactorsAuthorizationManager
+			.builder();
+
+		/**
+		 * Add additional authorities that will be required.
+		 * @param additionalAuthorities the additional authorities.
+		 * @return the {@link AdditionalRequiredFactorsBuilder} to further customize.
+		 */
+		public AdditionalRequiredFactorsBuilder<T> requireFactors(String... additionalAuthorities) {
+			requireFactors((factors) -> {
+				for (String authority : additionalAuthorities) {
+					factors.requireFactor((factor) -> factor.authority(authority));
+				}
+			});
+			return this;
+		}
+
+		public AdditionalRequiredFactorsBuilder<T> requireFactors(
+				Consumer<AllRequiredFactorsAuthorizationManager.Builder<T>> factors) {
+			factors.accept(this.factors);
+			return this;
+		}
+
+		public AdditionalRequiredFactorsBuilder<T> requireFactor(Consumer<RequiredFactor.Builder> factor) {
+			this.factors.requireFactor(factor);
+			return this;
+		}
+
+		/**
+		 * Builds a {@link DefaultAuthorizationManagerFactory} that has the
+		 * {@link DefaultAuthorizationManagerFactory#setAdditionalAuthorization(AuthorizationManager)}
+		 * set.
+		 * @return the {@link DefaultAuthorizationManagerFactory}.
+		 */
+		public DefaultAuthorizationManagerFactory<T> build() {
+			DefaultAuthorizationManagerFactory<T> result = new DefaultAuthorizationManagerFactory<>();
+			AllRequiredFactorsAuthorizationManager<T> additionalChecks = this.factors.build();
+			result.setAdditionalAuthorization(additionalChecks);
+			return result;
+		}
+
+		private AdditionalRequiredFactorsBuilder() {
+		}
+
+	}
+
+}

+ 0 - 75
core/src/main/java/org/springframework/security/authorization/DefaultAuthorizationManagerFactory.java

@@ -16,9 +16,6 @@
 
 package org.springframework.security.authorization;
 
-import java.util.ArrayList;
-import java.util.List;
-
 import org.jspecify.annotations.Nullable;
 
 import org.springframework.security.access.hierarchicalroles.NullRoleHierarchy;
@@ -26,7 +23,6 @@ import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
 import org.springframework.security.authentication.AuthenticationTrustResolver;
 import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
 import org.springframework.util.Assert;
-import org.springframework.util.CollectionUtils;
 
 /**
  * A factory for creating different kinds of {@link AuthorizationManager} instances.
@@ -153,18 +149,6 @@ public final class DefaultAuthorizationManagerFactory<T extends @Nullable Object
 		return createManager(AuthenticatedAuthorizationManager.anonymous());
 	}
 
-	/**
-	 * Creates a {@link Builder} that helps build an {@link AuthorizationManager} to set
-	 * on {@link #setAdditionalAuthorization(AuthorizationManager)} for common scenarios.
-	 * <p>
-	 * Does not affect {@code anonymous}, {@code permitAll}, or {@code denyAll}.
-	 * @param <T> the secured object type
-	 * @return a factory configured with the required authorities
-	 */
-	public static <T> Builder<T> builder() {
-		return new Builder<>();
-	}
-
 	private AuthorizationManager<T> createManager(AuthorityAuthorizationManager<T> authorizationManager) {
 		authorizationManager.setRoleHierarchy(this.roleHierarchy);
 		return withAdditionalAuthorization(authorizationManager);
@@ -187,63 +171,4 @@ public final class DefaultAuthorizationManagerFactory<T extends @Nullable Object
 		return AuthorizationManagers.allOf(new AuthorizationDecision(false), this.additionalAuthorization, manager);
 	}
 
-	/**
-	 * A builder that allows creating {@link DefaultAuthorizationManagerFactory} with
-	 * additional authorization for common scenarios.
-	 *
-	 * @param <T> the type for the {@link DefaultAuthorizationManagerFactory}
-	 * @author Rob Winch
-	 */
-	public static final class Builder<T> {
-
-		private final List<String> additionalAuthorities = new ArrayList<>();
-
-		private RoleHierarchy roleHierarchy = new NullRoleHierarchy();
-
-		/**
-		 * Add additional authorities that will be required.
-		 * @param additionalAuthorities the additional authorities.
-		 * @return the {@link Builder} to further customize.
-		 */
-		public Builder<T> requireAdditionalAuthorities(String... additionalAuthorities) {
-			Assert.notEmpty(additionalAuthorities, "additionalAuthorities cannot be empty");
-			for (String additionalAuthority : additionalAuthorities) {
-				this.additionalAuthorities.add(additionalAuthority);
-			}
-			return this;
-		}
-
-		/**
-		 * The {@link RoleHierarchy} to use.
-		 * @param roleHierarchy the non-null {@link RoleHierarchy} to use. Default is
-		 * {@link NullRoleHierarchy}.
-		 * @return the Builder to further customize.
-		 */
-		public Builder<T> roleHierarchy(RoleHierarchy roleHierarchy) {
-			Assert.notNull(roleHierarchy, "roleHierarchy cannot be null");
-			this.roleHierarchy = roleHierarchy;
-			return this;
-		}
-
-		/**
-		 * Builds a {@link DefaultAuthorizationManagerFactory} that has the
-		 * {@link #setAdditionalAuthorization(AuthorizationManager)} set.
-		 * @return the {@link DefaultAuthorizationManagerFactory}.
-		 */
-		public DefaultAuthorizationManagerFactory<T> build() {
-			Assert.state(!CollectionUtils.isEmpty(this.additionalAuthorities), "additionalAuthorities cannot be empty");
-			DefaultAuthorizationManagerFactory<T> result = new DefaultAuthorizationManagerFactory<>();
-			AllAuthoritiesAuthorizationManager<T> additionalChecks = AllAuthoritiesAuthorizationManager
-				.hasAllAuthorities(this.additionalAuthorities);
-			result.setRoleHierarchy(this.roleHierarchy);
-			additionalChecks.setRoleHierarchy(this.roleHierarchy);
-			result.setAdditionalAuthorization(additionalChecks);
-			return result;
-		}
-
-		private Builder() {
-		}
-
-	}
-
 }

+ 2 - 1
core/src/test/java/org/springframework/security/authorization/AllRequiredFactorsAuthorizationManagerTests.java

@@ -30,6 +30,7 @@ import org.springframework.security.core.authority.FactorGrantedAuthority;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
+import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
 
 /**
  * Test {@link AllRequiredFactorsAuthorizationManager}.
@@ -228,7 +229,7 @@ class AllRequiredFactorsAuthorizationManagerTests {
 
 	@Test
 	void builderBuildWhenEmpty() {
-		assertThatIllegalArgumentException().isThrownBy(() -> AllRequiredFactorsAuthorizationManager.builder().build());
+		assertThatIllegalStateException().isThrownBy(() -> AllRequiredFactorsAuthorizationManager.builder().build());
 	}
 
 	@Test

+ 6 - 38
core/src/test/java/org/springframework/security/authorization/AuthorizationManagerFactoryTests.java

@@ -16,16 +16,11 @@
 
 package org.springframework.security.authorization;
 
-import java.util.Collection;
-
 import org.junit.jupiter.api.Test;
 
-import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
 import org.springframework.security.authentication.TestAuthentication;
-import org.springframework.security.core.authority.AuthorityUtils;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
 import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.BDDMockito.given;
@@ -291,14 +286,15 @@ public class AuthorizationManagerFactoryTests {
 
 	@Test
 	public void builderWhenEmptyAdditionalAuthoritiesThenIllegalStateException() {
-		DefaultAuthorizationManagerFactory.Builder<Object> builder = DefaultAuthorizationManagerFactory.builder();
+		AuthorizationManagerFactories.AdditionalRequiredFactorsBuilder<Object> builder = AuthorizationManagerFactories
+			.multiFactor();
 		assertThatIllegalStateException().isThrownBy(() -> builder.build());
 	}
 
 	@Test
 	public void builderWhenAdditionalAuthorityThenRequired() {
-		AuthorizationManagerFactory<String> factory = DefaultAuthorizationManagerFactory.<String>builder()
-			.requireAdditionalAuthorities("ROLE_ADMIN")
+		AuthorizationManagerFactory<String> factory = AuthorizationManagerFactories.<String>multiFactor()
+			.requireFactors("ROLE_ADMIN")
 			.build();
 		assertUserDenied(factory.hasRole("USER"));
 		assertThat(factory.hasRole("USER").authorize(() -> TestAuthentication.authenticatedAdmin(), "").isGranted())
@@ -307,42 +303,14 @@ public class AuthorizationManagerFactoryTests {
 
 	@Test
 	public void builderWhenAdditionalAuthoritiesThenRequired() {
-		AuthorizationManagerFactory<String> factory = DefaultAuthorizationManagerFactory.<String>builder()
-			.requireAdditionalAuthorities("ROLE_ADMIN", "ROLE_USER")
+		AuthorizationManagerFactory<String> factory = AuthorizationManagerFactories.<String>multiFactor()
+			.requireFactors("ROLE_ADMIN", "ROLE_USER")
 			.build();
 		assertUserDenied(factory.hasRole("USER"));
 		assertThat(factory.hasRole("USER").authorize(() -> TestAuthentication.authenticatedAdmin(), "").isGranted())
 			.isTrue();
 	}
 
-	@Test
-	public void builderWhenNullRoleHierachyThenIllegalArgumentException() {
-		DefaultAuthorizationManagerFactory.Builder<Object> builder = DefaultAuthorizationManagerFactory.builder();
-		assertThatIllegalArgumentException().isThrownBy(() -> builder.roleHierarchy(null));
-	}
-
-	@Test
-	public void builderWhenRoleHierarchyThenUsed() {
-
-		RoleHierarchy roleHierarchy = mock(RoleHierarchy.class);
-		String ROLE_HIERARCHY = "ROLE_HIERARCHY";
-		Collection authorityHierarchy = AuthorityUtils.createAuthorityList(ROLE_HIERARCHY, "ROLE_USER");
-		given(roleHierarchy.getReachableGrantedAuthorities(any())).willReturn(authorityHierarchy);
-		DefaultAuthorizationManagerFactory<String> factory = DefaultAuthorizationManagerFactory.<String>builder()
-			.requireAdditionalAuthorities(ROLE_HIERARCHY)
-			.roleHierarchy(roleHierarchy)
-			.build();
-
-		// ROLE_USER is replaced with the RoleHierarchy (ROLE_USER, ROLE_HIERARCHY)
-		assertUserGranted(factory.hasAuthority("ROLE_USER"));
-		// ROLE_ADMIN is replaced with the RoleHierarchy (ROLE_USER, ROLE_HIERARCHY)
-		assertThat(factory.hasAuthority("ROLE_ADMIN")
-			.authorize(() -> TestAuthentication.authenticatedAdmin(), "")
-			.isGranted()).isFalse();
-
-		verify(roleHierarchy, times(4)).getReachableGrantedAuthorities(any());
-	}
-
 	private void assertUserGranted(AuthorizationManager<String> manager) {
 		assertThat(manager.authorize(() -> TestAuthentication.authenticatedUser(), "").isGranted()).isTrue();
 	}

+ 1 - 1
docs/modules/ROOT/pages/servlet/authentication/architecture.adoc

@@ -140,7 +140,7 @@ In many cases, this is cleared after the user is authenticated, to ensure that i
 * `authorities`: The <<servlet-authentication-granted-authority,`GrantedAuthority`>> instances are high-level permissions the user is granted.
 Two examples are roles and scopes.
 
-It is also equipped with a `Builder` that allows you to mutate an existing `Authentication` instance and potentially merge it with another.
+It is also equipped with a `AdditionalRequiredFactorsBuilder` that allows you to mutate an existing `Authentication` instance and potentially merge it with another.
 This is useful in scenarios like taking the authorities from one authentication step, like form login, and applying them to another, like one-time-token login, like so:
 
 include-code::./CopyAuthoritiesTests[tag=springSecurity,indent=0]

+ 2 - 1
docs/modules/ROOT/pages/servlet/authentication/mfa.adoc

@@ -91,9 +91,10 @@ This instructs `DefaultAuthorizationManagerFactory` that any authorization rule
 <2> Publish `DefaultAuthorizationManagerFactory` as a Bean, so it is used globally
 
 This should feel very similar to our previous example in xref:./mfa.adoc#authorization-manager-factory[].
-The difference is that in the previous example, the `Builder` is setting `DefaultAuthorization.additionalAuthorization` with a built in `AuthorizationManager` that always requires the same authorities.
+The difference is that in the previous example, the `AuthorizationManagerFactories` is setting `DefaultAuthorization.additionalAuthorization` with a built in `AuthorizationManager` that always requires the same authorities.
 
 We can now define our authorization rules which are combined with `AdminMfaAuthorizationManager`.
+
 include-code::./AdminMfaAuthorizationManagerConfiguration[tag=httpSecurity,indent=0]
 <1> URLs that begin with `/admin/**` require `ROLE_ADMIN`.
 If the username is `admin`, then `FACTOR_OTT` and `FACTOR_PASSWORD` are also required.

+ 3 - 3
docs/src/test/java/org/springframework/security/docs/servlet/authentication/authorizationmanagerfactory/UseAuthorizationManagerFactoryConfiguration.java

@@ -2,8 +2,8 @@ package org.springframework.security.docs.servlet.authentication.authorizationma
 
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.security.authorization.AuthorizationManagerFactories;
 import org.springframework.security.authorization.AuthorizationManagerFactory;
-import org.springframework.security.authorization.DefaultAuthorizationManagerFactory;
 import org.springframework.security.config.Customizer;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@@ -38,8 +38,8 @@ class UseAuthorizationManagerFactoryConfiguration {
 	// tag::authorizationManagerFactoryBean[]
 	@Bean
 	AuthorizationManagerFactory<Object> authz() {
-		return DefaultAuthorizationManagerFactory.builder()
-			.requireAdditionalAuthorities(
+		return AuthorizationManagerFactories.multiFactor()
+			.requireFactors(
 				FactorGrantedAuthority.PASSWORD_AUTHORITY,
 				FactorGrantedAuthority.OTT_AUTHORITY
 			)

+ 3 - 3
docs/src/test/java/org/springframework/security/docs/servlet/authentication/obtainingmoreauthorization/MissingAuthorityConfiguration.java

@@ -8,8 +8,8 @@ import jakarta.servlet.http.HttpServletResponse;
 
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.security.authorization.AuthorizationManagerFactories;
 import org.springframework.security.authorization.AuthorizationManagerFactory;
-import org.springframework.security.authorization.DefaultAuthorizationManagerFactory;
 import org.springframework.security.config.Customizer;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@@ -48,8 +48,8 @@ class MissingAuthorityConfiguration {
 	// tag::authorizationManagerFactoryBean[]
 	@Bean
 	AuthorizationManagerFactory<Object> authz() {
-		return DefaultAuthorizationManagerFactory.builder()
-				.requireAdditionalAuthorities(FactorGrantedAuthority.X509_AUTHORITY, FactorGrantedAuthority.AUTHORIZATION_CODE_AUTHORITY)
+		return AuthorizationManagerFactories.multiFactor()
+				.requireFactors(FactorGrantedAuthority.X509_AUTHORITY, FactorGrantedAuthority.AUTHORIZATION_CODE_AUTHORITY)
 				.build();
 	}
 	// end::authorizationManagerFactoryBean[]

+ 3 - 3
docs/src/test/java/org/springframework/security/docs/servlet/authentication/selectivemfa/SelectiveMfaConfiguration.java

@@ -2,8 +2,8 @@ package org.springframework.security.docs.servlet.authentication.selectivemfa;
 
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.security.authorization.AuthorizationManagerFactories;
 import org.springframework.security.authorization.AuthorizationManagerFactory;
-import org.springframework.security.authorization.DefaultAuthorizationManagerFactory;
 import org.springframework.security.config.Customizer;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@@ -25,8 +25,8 @@ class SelectiveMfaConfiguration {
 		// @formatter:off
 		// <1>
 		AuthorizationManagerFactory<Object> mfa =
-			DefaultAuthorizationManagerFactory.<Object>builder()
-				.requireAdditionalAuthorities(
+			AuthorizationManagerFactories.<Object>multiFactor()
+				.requireFactors(
 					FactorGrantedAuthority.PASSWORD_AUTHORITY,
 					FactorGrantedAuthority.OTT_AUTHORITY
 				)

+ 3 - 3
docs/src/test/kotlin/org/springframework/security/kt/docs/servlet/authentication/authorizationmanagerfactory/UseAuthorizationManagerFactoryConfiguration.kt

@@ -2,8 +2,8 @@ package org.springframework.security.kt.docs.servlet.authentication.authorizatio
 
 import org.springframework.context.annotation.Bean
 import org.springframework.context.annotation.Configuration
+import org.springframework.security.authorization.AuthorizationManagerFactories
 import org.springframework.security.authorization.AuthorizationManagerFactory
-import org.springframework.security.authorization.DefaultAuthorizationManagerFactory
 import org.springframework.security.config.annotation.web.builders.HttpSecurity
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
 import org.springframework.security.config.annotation.web.invoke
@@ -38,8 +38,8 @@ internal class UseAuthorizationManagerFactoryConfiguration {
     // tag::authorizationManagerFactoryBean[]
     @Bean
     fun authz(): AuthorizationManagerFactory<Object> {
-        return DefaultAuthorizationManagerFactory.builder<Object>()
-            .requireAdditionalAuthorities(
+        return AuthorizationManagerFactories.multiFactor<Object>()
+            .requireFactors(
                 FactorGrantedAuthority.PASSWORD_AUTHORITY,
                 FactorGrantedAuthority.OTT_AUTHORITY
             )

+ 3 - 3
docs/src/test/kotlin/org/springframework/security/kt/docs/servlet/authentication/obtainingmoreauthorization/MissingAuthorityConfiguration.kt

@@ -4,8 +4,8 @@ import jakarta.servlet.http.HttpServletRequest
 import jakarta.servlet.http.HttpServletResponse
 import org.springframework.context.annotation.Bean
 import org.springframework.context.annotation.Configuration
+import org.springframework.security.authorization.AuthorizationManagerFactories
 import org.springframework.security.authorization.AuthorizationManagerFactory
-import org.springframework.security.authorization.DefaultAuthorizationManagerFactory
 import org.springframework.security.config.annotation.web.builders.HttpSecurity
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
 import org.springframework.security.config.annotation.web.configurers.ExceptionHandlingConfigurer
@@ -54,8 +54,8 @@ internal class MissingAuthorityConfiguration {
     // tag::authorizationManagerFactoryBean[]
     @Bean
     fun authz(): AuthorizationManagerFactory<Object> {
-        return DefaultAuthorizationManagerFactory.builder<Object>()
-                .requireAdditionalAuthorities(
+        return AuthorizationManagerFactories.multiFactor<Object>()
+                .requireFactors(
                     FactorGrantedAuthority.X509_AUTHORITY,
                     FactorGrantedAuthority.AUTHORIZATION_CODE_AUTHORITY
                 )

+ 3 - 3
docs/src/test/kotlin/org/springframework/security/kt/docs/servlet/authentication/selectivemfa/SelectiveMfaConfiguration.kt

@@ -2,8 +2,8 @@ package org.springframework.security.kt.docs.servlet.authentication.selectivemfa
 
 import org.springframework.context.annotation.Bean
 import org.springframework.context.annotation.Configuration
+import org.springframework.security.authorization.AuthorizationManagerFactories
 import org.springframework.security.authorization.AuthorizationManagerFactory
-import org.springframework.security.authorization.DefaultAuthorizationManagerFactory
 import org.springframework.security.config.annotation.web.builders.HttpSecurity
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
 import org.springframework.security.config.annotation.web.invoke
@@ -25,8 +25,8 @@ internal class SelectiveMfaConfiguration {
         // @formatter:off
         // <1>
         val mfa: AuthorizationManagerFactory<Any> =
-            DefaultAuthorizationManagerFactory.builder<Any>()
-                .requireAdditionalAuthorities(
+            AuthorizationManagerFactories.multiFactor<Any>()
+                .requireFactors(
                     FactorGrantedAuthority.PASSWORD_AUTHORITY,
                     FactorGrantedAuthority.OTT_AUTHORITY
                 )