AuthorizationManagerFactories.when
Closes gh-18920
This commit is contained in:
+45
-1
@@ -17,6 +17,13 @@
|
|||||||
package org.springframework.security.authorization;
|
package org.springframework.security.authorization;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates common {@link AuthorizationManagerFactory} instances.
|
* Creates common {@link AuthorizationManagerFactory} instances.
|
||||||
@@ -56,6 +63,38 @@ public final class AuthorizationManagerFactories {
|
|||||||
private final AllRequiredFactorsAuthorizationManager.Builder<T> factors = AllRequiredFactorsAuthorizationManager
|
private final AllRequiredFactorsAuthorizationManager.Builder<T> factors = AllRequiredFactorsAuthorizationManager
|
||||||
.builder();
|
.builder();
|
||||||
|
|
||||||
|
private @Nullable Predicate<Authentication> whenCondition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply the required factors only when the given condition is true for the
|
||||||
|
* current {@link Authentication}. When the condition is false, no additional
|
||||||
|
* factors are required (equivalent to permit-all for the additional
|
||||||
|
* authorization). Implemented using
|
||||||
|
* {@link ConditionalAuthorizationManager#when(java.util.function.Predicate)}.
|
||||||
|
* @param condition the condition to evaluate (must not be null)
|
||||||
|
* @return the {@link AdditionalRequiredFactorsBuilder} to further customize
|
||||||
|
* @since 7.1
|
||||||
|
*/
|
||||||
|
public AdditionalRequiredFactorsBuilder<T> when(Predicate<Authentication> condition) {
|
||||||
|
Assert.notNull(condition, "condition cannot be null");
|
||||||
|
this.whenCondition = condition;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Customize the condition that determines if the required factors are evaluated.
|
||||||
|
* @param condition a function that takes the current condition and returns the
|
||||||
|
* new condition
|
||||||
|
* @return the {@link AdditionalRequiredFactorsBuilder} to further customize
|
||||||
|
* @since 7.1
|
||||||
|
*/
|
||||||
|
public AdditionalRequiredFactorsBuilder<T> withWhen(
|
||||||
|
Function<@Nullable Predicate<Authentication>, @Nullable Predicate<Authentication>> condition) {
|
||||||
|
Assert.notNull(condition, "condition cannot be null");
|
||||||
|
this.whenCondition = condition.apply(this.whenCondition);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add additional authorities that will be required.
|
* Add additional authorities that will be required.
|
||||||
* @param additionalAuthorities the additional authorities.
|
* @param additionalAuthorities the additional authorities.
|
||||||
@@ -89,7 +128,12 @@ public final class AuthorizationManagerFactories {
|
|||||||
*/
|
*/
|
||||||
public DefaultAuthorizationManagerFactory<T> build() {
|
public DefaultAuthorizationManagerFactory<T> build() {
|
||||||
DefaultAuthorizationManagerFactory<T> result = new DefaultAuthorizationManagerFactory<>();
|
DefaultAuthorizationManagerFactory<T> result = new DefaultAuthorizationManagerFactory<>();
|
||||||
AllRequiredFactorsAuthorizationManager<T> additionalChecks = this.factors.build();
|
AuthorizationManager<T> additionalChecks = this.factors.build();
|
||||||
|
if (this.whenCondition != null) {
|
||||||
|
additionalChecks = ConditionalAuthorizationManager.<T>when(this.whenCondition)
|
||||||
|
.whenTrue(additionalChecks)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
result.setAdditionalAuthorization(additionalChecks);
|
result.setAdditionalAuthorization(additionalChecks);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
+55
@@ -19,8 +19,10 @@ package org.springframework.security.authorization;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.security.authentication.TestAuthentication;
|
import org.springframework.security.authentication.TestAuthentication;
|
||||||
|
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
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.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.BDDMockito.given;
|
import static org.mockito.BDDMockito.given;
|
||||||
@@ -311,6 +313,59 @@ public class AuthorizationManagerFactoryTests {
|
|||||||
.isTrue();
|
.isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void builderWhenWhenConditionThenAdditionalFactorsRequiredOnlyWhenConditionTrue() {
|
||||||
|
AuthorizationManagerFactory<String> factory = AuthorizationManagerFactories.<String>multiFactor()
|
||||||
|
.requireFactors("ROLE_ADMIN")
|
||||||
|
.when((auth) -> "admin".equals(auth.getName()))
|
||||||
|
.build();
|
||||||
|
// When condition is true (admin user), ROLE_ADMIN is required in addition to
|
||||||
|
// hasRole("USER")
|
||||||
|
assertThat(factory.hasRole("USER").authorize(() -> TestAuthentication.authenticatedAdmin(), "").isGranted())
|
||||||
|
.isTrue();
|
||||||
|
// When condition is false (non-admin user), additional factors are not required
|
||||||
|
assertUserGranted(factory.hasRole("USER"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void builderWhenWhenConditionFalseThenUserWithoutRequiredFactorGranted() {
|
||||||
|
AuthorizationManagerFactory<String> factory = AuthorizationManagerFactories.<String>multiFactor()
|
||||||
|
.requireFactors("ROLE_ADMIN")
|
||||||
|
.when((auth) -> "admin".equals(auth.getName()))
|
||||||
|
.build();
|
||||||
|
// Non-admin user does not need ROLE_ADMIN for hasRole("USER")
|
||||||
|
assertThat(factory.hasRole("USER").authorize(() -> TestAuthentication.authenticatedUser(), "").isGranted())
|
||||||
|
.isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void builderWhenWithWhenConditionThenConditionIsCustomized() {
|
||||||
|
AuthorizationManagerFactory<String> factory = AuthorizationManagerFactories.<String>multiFactor()
|
||||||
|
.requireFactors("ROLE_ADMIN")
|
||||||
|
.when((auth) -> "admin".equals(auth.getName()))
|
||||||
|
.withWhen((current) -> (auth) -> current != null && current.test(auth) && auth.isAuthenticated())
|
||||||
|
.build();
|
||||||
|
// When condition is true (admin user and authenticated), ROLE_ADMIN is required
|
||||||
|
assertThat(factory.hasRole("USER").authorize(() -> TestAuthentication.authenticatedAdmin(), "").isGranted())
|
||||||
|
.isTrue();
|
||||||
|
// When condition is false (admin user but not authenticated), additional factors
|
||||||
|
// are not required
|
||||||
|
TestingAuthenticationToken unauthenticatedAdmin = new TestingAuthenticationToken("admin", "password",
|
||||||
|
"ROLE_USER");
|
||||||
|
unauthenticatedAdmin.setAuthenticated(false);
|
||||||
|
assertThat(factory.hasRole("USER").authorize(() -> unauthenticatedAdmin, "").isGranted()).isTrue();
|
||||||
|
// When condition is false (non-admin user), additional factors are not required
|
||||||
|
assertUserGranted(factory.hasRole("USER"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void builderWhenWithWhenNullThenIllegalArgumentException() {
|
||||||
|
AuthorizationManagerFactories.AdditionalRequiredFactorsBuilder<Object> builder = AuthorizationManagerFactories
|
||||||
|
.multiFactor();
|
||||||
|
assertThatIllegalArgumentException().isThrownBy(() -> builder.withWhen(null))
|
||||||
|
.withMessage("condition cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
private void assertUserGranted(AuthorizationManager<String> manager) {
|
private void assertUserGranted(AuthorizationManager<String> manager) {
|
||||||
assertThat(manager.authorize(() -> TestAuthentication.authenticatedUser(), "").isGranted()).isTrue();
|
assertThat(manager.authorize(() -> TestAuthentication.authenticatedUser(), "").isGranted()).isTrue();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,23 +108,20 @@ include-code::./ValidDurationConfiguration[tag=httpSecurity,indent=0]
|
|||||||
|
|
||||||
In our previous examples, MFA is a static decision per request.
|
In our previous examples, MFA is a static decision per request.
|
||||||
There are times when we might want to require MFA for some users, but not others.
|
There are times when we might want to require MFA for some users, but not others.
|
||||||
Determining if MFA is enabled per user can be achieved by creating a custom `AuthorizationManager` that conditionally requires factors based upon the `Authentication`.
|
Determining if MFA is enabled per user can be achieved by using `AuthorizationManagerFactories.multiFactor().when` to conditionally require factors based upon the `Authentication`.
|
||||||
|
This is implemented using xref:servlet/authorization/architecture.adoc#authz-conditional-authorization-manager[`ConditionalAuthorizationManager`].
|
||||||
|
|
||||||
include-code::./AdminMfaAuthorizationManagerConfiguration[tag=authorizationManager,indent=0]
|
To enable the conditional MFA rules globally, we can publish an `AuthorizationManagerFactory` Bean.
|
||||||
<1> MFA is required for the user with the username `admin`
|
|
||||||
<2> Otherwise, MFA is not required
|
|
||||||
|
|
||||||
To enable the MFA rules globally, we can publish an `AuthorizationManagerFactory` Bean.
|
|
||||||
|
|
||||||
include-code::./AdminMfaAuthorizationManagerConfiguration[tag=authorizationManagerFactory,indent=0]
|
include-code::./AdminMfaAuthorizationManagerConfiguration[tag=authorizationManagerFactory,indent=0]
|
||||||
<1> Inject the custom `AuthorizationManager` as the javadoc:org.springframework.security.authorization.DefaultAuthorizationManagerFactory#setAdditionalAuthorization(org.springframework.security.authorization.AuthorizationManager)[DefaultAuthorization.additionalAuthorization].
|
<1> Require `FACTOR_OTT` and `FACTOR_PASSWORD`
|
||||||
This instructs `DefaultAuthorizationManagerFactory` that any authorization rule should apply our custom `AuthorizationManager` along with any authorization requirements defined by the application (e.g. `hasRole("ADMIN")`).
|
<2> Only apply the requirement if the username is `admin`. Otherwise, MFA is not required.
|
||||||
<2> Publish `DefaultAuthorizationManagerFactory` as a Bean, so it is used globally
|
<3> Return the `AuthorizationManagerFactory` using `.build()`. Since it is published as a Bean, it is used globally.
|
||||||
|
|
||||||
This should feel very similar to our previous example in xref:./mfa.adoc#authorization-manager-factory[].
|
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 `AuthorizationManagerFactories` 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` creates an `AuthorizationManager` that always requires the same authorities.
|
||||||
|
|
||||||
We can now define our authorization rules which are combined with `AdminMfaAuthorizationManager`.
|
We can now define our authorization rules which are combined with `AuthorizationManagerFactory`.
|
||||||
|
|
||||||
include-code::./AdminMfaAuthorizationManagerConfiguration[tag=httpSecurity,indent=0]
|
include-code::./AdminMfaAuthorizationManagerConfiguration[tag=httpSecurity,indent=0]
|
||||||
<1> URLs that begin with `/admin/**` require `ROLE_ADMIN`.
|
<1> URLs that begin with `/admin/**` require `ROLE_ADMIN`.
|
||||||
@@ -138,7 +135,7 @@ If we preferred, we could change our logic to enable MFA based upon the roles ra
|
|||||||
[[raam-mfa]]
|
[[raam-mfa]]
|
||||||
== RequiredAuthoritiesAuthorizationManager
|
== RequiredAuthoritiesAuthorizationManager
|
||||||
|
|
||||||
We've demonstrated how we can dynamically determine the authorities for a particular user in xref:./mfa.adoc#programmatic-mfa[] using a custom `AuthorizationManager`.
|
We've demonstrated how we can dynamically determine the authorities for a particular user in xref:./mfa.adoc#programmatic-mfa[] using `AuthorizationManagerFactories.multiFactor().when`.
|
||||||
However, this is such a common scenario that Spring Security provides built in support using javadoc:org.springframework.security.authorization.RequiredAuthoritiesAuthorizationManager[] and javadoc:org.springframework.security.authorization.RequiredAuthoritiesRepository[].
|
However, this is such a common scenario that Spring Security provides built in support using javadoc:org.springframework.security.authorization.RequiredAuthoritiesAuthorizationManager[] and javadoc:org.springframework.security.authorization.RequiredAuthoritiesRepository[].
|
||||||
|
|
||||||
Let's implement the same requirement that we did in xref:./mfa.adoc#programmatic-mfa[] using the built-in support.
|
Let's implement the same requirement that we did in xref:./mfa.adoc#programmatic-mfa[] using the built-in support.
|
||||||
@@ -168,7 +165,7 @@ Our example uses an in memory mapping of usernames to the additional required au
|
|||||||
For more dynamic use cases that can be determined by the username, a custom implementation of javadoc:org.springframework.security.authorization.RequiredAuthoritiesRepository[] can be created.
|
For more dynamic use cases that can be determined by the username, a custom implementation of javadoc:org.springframework.security.authorization.RequiredAuthoritiesRepository[] can be created.
|
||||||
Possible examples would be looking up if a user has enabled MFA in an explicit setting, determining if a user has registered a passkey, etc.
|
Possible examples would be looking up if a user has enabled MFA in an explicit setting, determining if a user has registered a passkey, etc.
|
||||||
|
|
||||||
For cases that need to determine MFA based upon the `Authentication`, a custom `AuthorizationManger` can be used as demonstrated in xref:./mfa.adoc#programmatic-mfa[].
|
For cases that need to determine MFA based upon the `Authentication`, `AuthorizationManagerFactories.multiFactor().when` can be used as demonstrated in xref:./mfa.adoc#programmatic-mfa[].
|
||||||
|
|
||||||
|
|
||||||
[[hasallauthorities]]
|
[[hasallauthorities]]
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
* https://github.com/spring-projects/spring-security/pull/18634[gh-18634] - Added javadoc:org.springframework.security.web.util.matcher.InetAddressMatcher[]
|
* https://github.com/spring-projects/spring-security/pull/18634[gh-18634] - Added javadoc:org.springframework.security.web.util.matcher.InetAddressMatcher[]
|
||||||
* https://github.com/spring-projects/spring-security/issues/18755[gh-18755] - Include `charset` in `WWW-Authenticate` header
|
* https://github.com/spring-projects/spring-security/issues/18755[gh-18755] - Include `charset` in `WWW-Authenticate` header
|
||||||
* Added xref:servlet/authorization/architecture.adoc#authz-conditional-authorization-manager[ConditionalAuthorizationManager]
|
* Added xref:servlet/authorization/architecture.adoc#authz-conditional-authorization-manager[ConditionalAuthorizationManager]
|
||||||
|
* Added `when` and `withWhen` conditions to `AuthorizationManagerFactories.multiFactor()` for xref:servlet/authentication/mfa.adoc#programmatic-mfa[Programmatic MFA]
|
||||||
|
|
||||||
== OAuth 2.0
|
== OAuth 2.0
|
||||||
|
|
||||||
|
|||||||
+9
-38
@@ -1,17 +1,9 @@
|
|||||||
package org.springframework.security.docs.servlet.authentication.programmaticmfa;
|
package org.springframework.security.docs.servlet.authentication.programmaticmfa;
|
||||||
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
import org.jspecify.annotations.Nullable;
|
|
||||||
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.security.authorization.AllAuthoritiesAuthorizationManager;
|
import org.springframework.security.authorization.AuthorizationManagerFactories;
|
||||||
import org.springframework.security.authorization.AuthorizationDecision;
|
|
||||||
import org.springframework.security.authorization.AuthorizationManager;
|
|
||||||
import org.springframework.security.authorization.AuthorizationManagerFactory;
|
import org.springframework.security.authorization.AuthorizationManagerFactory;
|
||||||
import org.springframework.security.authorization.AuthorizationResult;
|
|
||||||
import org.springframework.security.authorization.DefaultAuthorizationManagerFactory;
|
|
||||||
import org.springframework.security.config.Customizer;
|
import org.springframework.security.config.Customizer;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
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.configuration.EnableWebSecurity;
|
||||||
@@ -23,7 +15,6 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
|||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.authentication.ott.OneTimeTokenGenerationSuccessHandler;
|
import org.springframework.security.web.authentication.ott.OneTimeTokenGenerationSuccessHandler;
|
||||||
import org.springframework.security.web.authentication.ott.RedirectOneTimeTokenGenerationSuccessHandler;
|
import org.springframework.security.web.authentication.ott.RedirectOneTimeTokenGenerationSuccessHandler;
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
@@ -46,36 +37,16 @@ class AdminMfaAuthorizationManagerConfiguration {
|
|||||||
}
|
}
|
||||||
// end::httpSecurity[]
|
// end::httpSecurity[]
|
||||||
|
|
||||||
// tag::authorizationManager[]
|
|
||||||
@Component
|
|
||||||
class AdminMfaAuthorizationManager implements AuthorizationManager<Object> {
|
|
||||||
@Override
|
|
||||||
public AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication, Object context) {
|
|
||||||
if ("admin".equals(authentication.get().getName())) {
|
|
||||||
AuthorizationManager<Object> admins =
|
|
||||||
AllAuthoritiesAuthorizationManager.hasAllAuthorities(
|
|
||||||
FactorGrantedAuthority.OTT_AUTHORITY,
|
|
||||||
FactorGrantedAuthority.PASSWORD_AUTHORITY
|
|
||||||
);
|
|
||||||
// <1>
|
|
||||||
return admins.authorize(authentication, context);
|
|
||||||
} else {
|
|
||||||
// <2>
|
|
||||||
return new AuthorizationDecision(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// end::authorizationManager[]
|
|
||||||
|
|
||||||
// tag::authorizationManagerFactory[]
|
// tag::authorizationManagerFactory[]
|
||||||
@Bean
|
@Bean
|
||||||
AuthorizationManagerFactory<Object> authorizationManagerFactory(
|
AuthorizationManagerFactory<Object> authorizationManagerFactory() {
|
||||||
AdminMfaAuthorizationManager admins) {
|
// <3>
|
||||||
DefaultAuthorizationManagerFactory<Object> defaults = new DefaultAuthorizationManagerFactory<>();
|
return AuthorizationManagerFactories.multiFactor()
|
||||||
// <1>
|
// <1>
|
||||||
defaults.setAdditionalAuthorization(admins);
|
.requireFactors(FactorGrantedAuthority.OTT_AUTHORITY, FactorGrantedAuthority.PASSWORD_AUTHORITY)
|
||||||
// <2>
|
// <2>
|
||||||
return defaults;
|
.when((auth) -> "admin".equals(auth.getName()))
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
// end::authorizationManagerFactory[]
|
// end::authorizationManagerFactory[]
|
||||||
|
|
||||||
|
|||||||
+8
-28
@@ -14,8 +14,6 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager
|
|||||||
import org.springframework.security.web.SecurityFilterChain
|
import org.springframework.security.web.SecurityFilterChain
|
||||||
import org.springframework.security.web.authentication.ott.OneTimeTokenGenerationSuccessHandler
|
import org.springframework.security.web.authentication.ott.OneTimeTokenGenerationSuccessHandler
|
||||||
import org.springframework.security.web.authentication.ott.RedirectOneTimeTokenGenerationSuccessHandler
|
import org.springframework.security.web.authentication.ott.RedirectOneTimeTokenGenerationSuccessHandler
|
||||||
import org.springframework.stereotype.Component
|
|
||||||
import java.util.function.Supplier
|
|
||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
@@ -40,34 +38,16 @@ internal class AdminMfaAuthorizationManagerConfiguration {
|
|||||||
}
|
}
|
||||||
// end::httpSecurity[]
|
// end::httpSecurity[]
|
||||||
|
|
||||||
// tag::authorizationManager[]
|
|
||||||
@Component
|
|
||||||
internal open class AdminMfaAuthorizationManager : AuthorizationManager<Any> {
|
|
||||||
override fun authorize(
|
|
||||||
authentication: Supplier<out Authentication?>, context: Any): AuthorizationResult {
|
|
||||||
return if ("admin" == authentication.get().name) {
|
|
||||||
var admins =
|
|
||||||
AllAuthoritiesAuthorizationManager.hasAllAuthorities<Any>(
|
|
||||||
FactorGrantedAuthority.OTT_AUTHORITY,
|
|
||||||
FactorGrantedAuthority.PASSWORD_AUTHORITY)
|
|
||||||
// <1>
|
|
||||||
admins.authorize(authentication, context)
|
|
||||||
} else {
|
|
||||||
// <2>
|
|
||||||
AuthorizationDecision(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// end::authorizationManager[]
|
|
||||||
|
|
||||||
// tag::authorizationManagerFactory[]
|
// tag::authorizationManagerFactory[]
|
||||||
@Bean
|
@Bean
|
||||||
fun authorizationManagerFactory(admins: AdminMfaAuthorizationManager): AuthorizationManagerFactory<Any> {
|
fun authorizationManagerFactory(): AuthorizationManagerFactory<Any> {
|
||||||
val defaults = DefaultAuthorizationManagerFactory<Any>()
|
// <3>
|
||||||
// <1>
|
return AuthorizationManagerFactories.multiFactor<Any>()
|
||||||
defaults.setAdditionalAuthorization(admins)
|
// <1>
|
||||||
// <2>
|
.requireFactors(FactorGrantedAuthority.OTT_AUTHORITY, FactorGrantedAuthority.PASSWORD_AUTHORITY)
|
||||||
return defaults
|
// <2>
|
||||||
|
.`when` { auth -> "admin" == auth.name }
|
||||||
|
.build()
|
||||||
}
|
}
|
||||||
// end::authorizationManagerFactory[]
|
// end::authorizationManagerFactory[]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user