EnableGlobalMultiFactorAuthentication->EnableMultiFactorAuthentication
Closes gh-18127
This commit is contained in:
+3
-3
@@ -27,12 +27,12 @@ import org.springframework.security.authorization.AuthorizationManagerFactories;
|
|||||||
import org.springframework.security.authorization.DefaultAuthorizationManagerFactory;
|
import org.springframework.security.authorization.DefaultAuthorizationManagerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses {@link EnableGlobalMultiFactorAuthentication} to configure a
|
* Uses {@link EnableMultiFactorAuthentication} to configure a
|
||||||
* {@link DefaultAuthorizationManagerFactory}.
|
* {@link DefaultAuthorizationManagerFactory}.
|
||||||
*
|
*
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
* @since 7.0
|
* @since 7.0
|
||||||
* @see EnableGlobalMultiFactorAuthentication
|
* @see EnableMultiFactorAuthentication
|
||||||
*/
|
*/
|
||||||
class AuthorizationManagerFactoryConfiguration implements ImportAware {
|
class AuthorizationManagerFactoryConfiguration implements ImportAware {
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ class AuthorizationManagerFactoryConfiguration implements ImportAware {
|
|||||||
@Override
|
@Override
|
||||||
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
||||||
Map<String, Object> multiFactorAuthenticationAttrs = importMetadata
|
Map<String, Object> multiFactorAuthenticationAttrs = importMetadata
|
||||||
.getAnnotationAttributes(EnableGlobalMultiFactorAuthentication.class.getName());
|
.getAnnotationAttributes(EnableMultiFactorAuthentication.class.getName());
|
||||||
|
|
||||||
this.authorities = (String[]) multiFactorAuthenticationAttrs.getOrDefault("authorities", new String[0]);
|
this.authorities = (String[]) multiFactorAuthenticationAttrs.getOrDefault("authorities", new String[0]);
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-6
@@ -26,9 +26,12 @@ import org.springframework.context.annotation.Import;
|
|||||||
import org.springframework.security.authorization.DefaultAuthorizationManagerFactory;
|
import org.springframework.security.authorization.DefaultAuthorizationManagerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exposes a {@link DefaultAuthorizationManagerFactory} as a Bean with the
|
* Enables Multi-Factor Authentication (MFA) support within Spring Security.
|
||||||
* {@link #authorities()} specified as additional required authorities. The configuration
|
*
|
||||||
* will be picked up by both
|
* When {@link #authorities()} is specified creates a
|
||||||
|
* {@link DefaultAuthorizationManagerFactory} as a Bean with the {@link #authorities()}
|
||||||
|
* specified as additional required authorities. The configuration will be picked up by
|
||||||
|
* both
|
||||||
* {@link org.springframework.security.config.annotation.web.configuration.EnableWebSecurity}
|
* {@link org.springframework.security.config.annotation.web.configuration.EnableWebSecurity}
|
||||||
* and
|
* and
|
||||||
* {@link org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity}.
|
* {@link org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity}.
|
||||||
@@ -36,7 +39,7 @@ import org.springframework.security.authorization.DefaultAuthorizationManagerFac
|
|||||||
* <pre>
|
* <pre>
|
||||||
|
|
||||||
* @Configuration
|
* @Configuration
|
||||||
* @EnableGlobalMultiFactorAuthentication(authorities = { GrantedAuthorities.FACTOR_OTT, GrantedAuthorities.FACTOR_PASSWORD })
|
* @EnableMultiFactorAuthentication(authorities = { GrantedAuthorities.FACTOR_OTT, GrantedAuthorities.FACTOR_PASSWORD })
|
||||||
* public class MyConfiguration {
|
* public class MyConfiguration {
|
||||||
* // ...
|
* // ...
|
||||||
* }
|
* }
|
||||||
@@ -51,8 +54,8 @@ import org.springframework.security.authorization.DefaultAuthorizationManagerFac
|
|||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.TYPE)
|
@Target(ElementType.TYPE)
|
||||||
@Documented
|
@Documented
|
||||||
@Import(GlobalMultiFactorAuthenticationSelector.class)
|
@Import(MultiFactorAuthenticationSelector.class)
|
||||||
public @interface EnableGlobalMultiFactorAuthentication {
|
public @interface EnableMultiFactorAuthentication {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The additional authorities that are required.
|
* The additional authorities that are required.
|
||||||
+4
-4
@@ -25,19 +25,19 @@ import org.springframework.core.type.AnnotationMetadata;
|
|||||||
import org.springframework.security.authorization.DefaultAuthorizationManagerFactory;
|
import org.springframework.security.authorization.DefaultAuthorizationManagerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses {@link EnableGlobalMultiFactorAuthentication} to configure a
|
* Uses {@link EnableMultiFactorAuthentication} to configure a
|
||||||
* {@link DefaultAuthorizationManagerFactory}.
|
* {@link DefaultAuthorizationManagerFactory}.
|
||||||
*
|
*
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
* @since 7.0
|
* @since 7.0
|
||||||
* @see EnableGlobalMultiFactorAuthentication
|
* @see EnableMultiFactorAuthentication
|
||||||
*/
|
*/
|
||||||
class GlobalMultiFactorAuthenticationSelector implements ImportSelector {
|
class MultiFactorAuthenticationSelector implements ImportSelector {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] selectImports(AnnotationMetadata metadata) {
|
public String[] selectImports(AnnotationMetadata metadata) {
|
||||||
Map<String, Object> multiFactorAuthenticationAttrs = metadata
|
Map<String, Object> multiFactorAuthenticationAttrs = metadata
|
||||||
.getAnnotationAttributes(EnableGlobalMultiFactorAuthentication.class.getName());
|
.getAnnotationAttributes(EnableMultiFactorAuthentication.class.getName());
|
||||||
String[] authorities = (String[]) multiFactorAuthenticationAttrs.getOrDefault("authorities", new String[0]);
|
String[] authorities = (String[]) multiFactorAuthenticationAttrs.getOrDefault("authorities", new String[0]);
|
||||||
List<String> imports = new ArrayList<>(2);
|
List<String> imports = new ArrayList<>(2);
|
||||||
if (authorities.length > 0) {
|
if (authorities.length > 0) {
|
||||||
+3
-3
@@ -53,14 +53,14 @@ import static org.mockito.BDDMockito.given;
|
|||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link EnableGlobalMultiFactorAuthentication}.
|
* Tests for {@link EnableMultiFactorAuthentication}.
|
||||||
*
|
*
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
*/
|
*/
|
||||||
@ExtendWith(SpringExtension.class)
|
@ExtendWith(SpringExtension.class)
|
||||||
@WebAppConfiguration
|
@WebAppConfiguration
|
||||||
@WithMockUser(authorities = FactorGrantedAuthority.PASSWORD_AUTHORITY)
|
@WithMockUser(authorities = FactorGrantedAuthority.PASSWORD_AUTHORITY)
|
||||||
public class EnableGlobalMultiFactorAuthenticationFiltersSetTests {
|
public class EnableMultiFactorAuthenticationFiltersSetTests {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private AuthenticationManager manager;
|
private AuthenticationManager manager;
|
||||||
@@ -105,7 +105,7 @@ public class EnableGlobalMultiFactorAuthenticationFiltersSetTests {
|
|||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableGlobalMultiFactorAuthentication(
|
@EnableMultiFactorAuthentication(
|
||||||
authorities = { FactorGrantedAuthority.OTT_AUTHORITY, FactorGrantedAuthority.PASSWORD_AUTHORITY })
|
authorities = { FactorGrantedAuthority.OTT_AUTHORITY, FactorGrantedAuthority.PASSWORD_AUTHORITY })
|
||||||
static class Config {
|
static class Config {
|
||||||
|
|
||||||
+3
-3
@@ -59,13 +59,13 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder
|
|||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link EnableGlobalMultiFactorAuthentication}.
|
* Tests for {@link EnableMultiFactorAuthentication}.
|
||||||
*
|
*
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
*/
|
*/
|
||||||
@ExtendWith(SpringExtension.class)
|
@ExtendWith(SpringExtension.class)
|
||||||
@WebAppConfiguration
|
@WebAppConfiguration
|
||||||
public class EnableGlobalMultiFactorAuthenticationTests {
|
public class EnableMultiFactorAuthenticationTests {
|
||||||
|
|
||||||
private static final String ATTR_NAME = "org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors$SecurityContextRequestPostProcessorSupport$TestSecurityContextRepository.REPO";
|
private static final String ATTR_NAME = "org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors$SecurityContextRequestPostProcessorSupport$TestSecurityContextRepository.REPO";
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ public class EnableGlobalMultiFactorAuthenticationTests {
|
|||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@EnableMethodSecurity
|
@EnableMethodSecurity
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableGlobalMultiFactorAuthentication(
|
@EnableMultiFactorAuthentication(
|
||||||
authorities = { FactorGrantedAuthority.OTT_AUTHORITY, FactorGrantedAuthority.PASSWORD_AUTHORITY })
|
authorities = { FactorGrantedAuthority.OTT_AUTHORITY, FactorGrantedAuthority.PASSWORD_AUTHORITY })
|
||||||
static class Config {
|
static class Config {
|
||||||
|
|
||||||
@@ -18,17 +18,17 @@ In order to require MFA with Spring Security you must:
|
|||||||
- Specify an authorization rule that requires multiple factors
|
- Specify an authorization rule that requires multiple factors
|
||||||
- Setup authentication for each of those factors
|
- Setup authentication for each of those factors
|
||||||
|
|
||||||
[[egmfa]]
|
[[emfa]]
|
||||||
== @EnableGlobalMultiFactorAuthentication
|
== @EnableMultiFactorAuthentication
|
||||||
|
|
||||||
javadoc:org.springframework.security.config.annotation.authorization.EnableGlobalMultiFactorAuthentication[format=annotation] simplifies Global MFA (the entire application requires MFA).
|
javadoc:org.springframework.security.config.annotation.authorization.EnableMultiFactorAuthentication[format=annotation] makes it easy to enable multifactor authentication.
|
||||||
Below you can find a configuration that adds the requirement for both passwords and OTT to every authorization rule.
|
Below you can find a configuration that adds the requirement for both passwords and OTT to every authorization rule.
|
||||||
|
|
||||||
include-code::./EnableGlobalMultiFactorAuthenticationConfiguration[tag=enable-global-mfa,indent=0]
|
include-code::./EnableMultiFactorAuthenticationConfiguration[tag=enable-mfa,indent=0]
|
||||||
|
|
||||||
We are now able to concisely create a configuration that always requires multiple factors.
|
We are now able to concisely create a configuration that always requires multiple factors.
|
||||||
|
|
||||||
include-code::./EnableGlobalMultiFactorAuthenticationConfiguration[tag=httpSecurity,indent=0]
|
include-code::./EnableMultiFactorAuthenticationConfiguration[tag=httpSecurity,indent=0]
|
||||||
<1> URLs that begin with `/admin/**` require the authorities `FACTOR_OTT`, `FACTOR_PASSWORD`, `ROLE_ADMIN`.
|
<1> URLs that begin with `/admin/**` require the authorities `FACTOR_OTT`, `FACTOR_PASSWORD`, `ROLE_ADMIN`.
|
||||||
<2> Every other URL requires the authorities `FACTOR_OTT`, `FACTOR_PASSWORD`
|
<2> Every other URL requires the authorities `FACTOR_OTT`, `FACTOR_PASSWORD`
|
||||||
<3> Set up the authentication mechanisms that can provide the required factors.
|
<3> Set up the authentication mechanisms that can provide the required factors.
|
||||||
@@ -40,18 +40,18 @@ If the user logged in initially with a token, then Spring Security redirects to
|
|||||||
[[authorization-manager-factory]]
|
[[authorization-manager-factory]]
|
||||||
== AuthorizationManagerFactory
|
== AuthorizationManagerFactory
|
||||||
|
|
||||||
The `@EnableGlobalMultiFactorAuthentication` annotation is just a shortcut for publishing an javadoc:org.springframework.security.authorization.AuthorizationManagerFactory[] Bean.
|
The `@EnableMultiFactorAuthentication` `authorities` property is just a shortcut for publishing an javadoc:org.springframework.security.authorization.AuthorizationManagerFactory[] Bean.
|
||||||
When an `AuthorizationManagerFactory` Bean is available, it is used by Spring Security to create authorization rules, like `hasAnyRole(String)`, that are defined on the `AuthorizationManagerFactory` Bean interface.
|
When an `AuthorizationManagerFactory` Bean is available, it is used by Spring Security to create authorization rules, like `hasAnyRole(String)`, that are defined on the `AuthorizationManagerFactory` Bean interface.
|
||||||
The implementation published by `@EnableGlobalMultiFactorAuthentication` will ensure that each authorization is combined with the requirement of having the specified factors.
|
The implementation published by `@EnableMultiFactorAuthentication` will ensure that each authorization is combined with the requirement of having the specified factors.
|
||||||
|
|
||||||
The `AuthorizationManagerFactory` Bean below is what is published in the previously discussed xref:./mfa.adoc#using-egmfa[`@EnableGlobalMultiFactorAuthentication` example].
|
The `AuthorizationManagerFactory` Bean below is what is published in the previously discussed xref:./mfa.adoc#emfa[`@EnableMultiFactorAuthentication` example].
|
||||||
|
|
||||||
include-code::./UseAuthorizationManagerFactoryConfiguration[tag=authorizationManagerFactoryBean,indent=0]
|
include-code::./UseAuthorizationManagerFactoryConfiguration[tag=authorizationManagerFactoryBean,indent=0]
|
||||||
|
|
||||||
[[selective-mfa]]
|
[[selective-mfa]]
|
||||||
== Selectively Requiring MFA
|
== Selectively Requiring MFA
|
||||||
|
|
||||||
We have demonstrated how to configure an entire application to require MFA (Global MFA) by using xref:./mfa.adoc#egmfa[`@EnableGlobalMultiFactorAuthentication`].
|
We have demonstrated how to configure an entire application to require MFA by using xref:./mfa.adoc#emfa[`@EnableMultiFactorAuthentication`]s `authorities` property.
|
||||||
However, there are times that an application only wants parts of the application to require MFA.
|
However, there are times that an application only wants parts of the application to require MFA.
|
||||||
Consider the following requirements:
|
Consider the following requirements:
|
||||||
|
|
||||||
@@ -63,6 +63,13 @@ In this case, some URLs require MFA while others do not.
|
|||||||
This means that the global approach that we saw before does not work.
|
This means that the global approach that we saw before does not work.
|
||||||
Fortunately, we can use what we learned in xref:./mfa.adoc#authorization-manager-factory[] to solve this in a concise manner.
|
Fortunately, we can use what we learned in xref:./mfa.adoc#authorization-manager-factory[] to solve this in a concise manner.
|
||||||
|
|
||||||
|
Start by specifying `@EnableMultiFactorAuthentication` without any authorities.
|
||||||
|
By doing so we enable MFA support, but no `AuthorizationManagerFactory` Bean is published.
|
||||||
|
|
||||||
|
include-code::./SelectiveMfaConfiguration[tag=enable-mfa,indent=0]
|
||||||
|
|
||||||
|
Next create an `AuthorizationManagerFactory` instance, but do not publish it as a Bean.
|
||||||
|
|
||||||
include-code::./SelectiveMfaConfiguration[tag=httpSecurity,indent=0]
|
include-code::./SelectiveMfaConfiguration[tag=httpSecurity,indent=0]
|
||||||
<1> Create a `DefaultAuthorizationManagerFactory` as we did previously, but do not publish it as a Bean.
|
<1> Create a `DefaultAuthorizationManagerFactory` as we did previously, but do not publish it as a Bean.
|
||||||
By not publishing it as a Bean, we are able to selectively use the `AuthorizationManagerFactory` instead of using it for every authorization rule.
|
By not publishing it as a Bean, we are able to selectively use the `AuthorizationManagerFactory` instead of using it for every authorization rule.
|
||||||
|
|||||||
+6
-6
@@ -1,9 +1,9 @@
|
|||||||
package org.springframework.security.docs.servlet.authentication.egmfa;
|
package org.springframework.security.docs.servlet.authentication.emfa;
|
||||||
|
|
||||||
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.config.Customizer;
|
import org.springframework.security.config.Customizer;
|
||||||
import org.springframework.security.config.annotation.authorization.EnableGlobalMultiFactorAuthentication;
|
import org.springframework.security.config.annotation.authorization.EnableMultiFactorAuthentication;
|
||||||
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;
|
||||||
import org.springframework.security.core.authority.FactorGrantedAuthority;
|
import org.springframework.security.core.authority.FactorGrantedAuthority;
|
||||||
@@ -16,12 +16,12 @@ import org.springframework.security.web.authentication.ott.RedirectOneTimeTokenG
|
|||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
// tag::enable-global-mfa[]
|
// tag::enable-mfa[]
|
||||||
@EnableGlobalMultiFactorAuthentication(authorities = {
|
@EnableMultiFactorAuthentication(authorities = {
|
||||||
FactorGrantedAuthority.PASSWORD_AUTHORITY,
|
FactorGrantedAuthority.PASSWORD_AUTHORITY,
|
||||||
FactorGrantedAuthority.OTT_AUTHORITY })
|
FactorGrantedAuthority.OTT_AUTHORITY })
|
||||||
// end::enable-global-mfa[]
|
// end::enable-mfa[]
|
||||||
public class EnableGlobalMultiFactorAuthenticationConfiguration {
|
public class EnableMultiFactorAuthenticationConfiguration {
|
||||||
|
|
||||||
// tag::httpSecurity[]
|
// tag::httpSecurity[]
|
||||||
@Bean
|
@Bean
|
||||||
+7
-7
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.security.docs.servlet.authentication.egmfa;
|
package org.springframework.security.docs.servlet.authentication.emfa;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
@@ -44,7 +44,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
|||||||
*/
|
*/
|
||||||
@ExtendWith({ SpringExtension.class, SpringTestContextExtension.class })
|
@ExtendWith({ SpringExtension.class, SpringTestContextExtension.class })
|
||||||
@TestExecutionListeners(WithSecurityContextTestExecutionListener.class)
|
@TestExecutionListeners(WithSecurityContextTestExecutionListener.class)
|
||||||
public class EnableGlobalMultiFactorAuthenticationTests {
|
public class EnableMultiFactorAuthenticationTests {
|
||||||
|
|
||||||
public final SpringTestContext spring = new SpringTestContext(this);
|
public final SpringTestContext spring = new SpringTestContext(this);
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ public class EnableGlobalMultiFactorAuthenticationTests {
|
|||||||
@Test
|
@Test
|
||||||
@WithMockUser(authorities = { FactorGrantedAuthority.PASSWORD_AUTHORITY, FactorGrantedAuthority.OTT_AUTHORITY, "ROLE_USER" })
|
@WithMockUser(authorities = { FactorGrantedAuthority.PASSWORD_AUTHORITY, FactorGrantedAuthority.OTT_AUTHORITY, "ROLE_USER" })
|
||||||
void getWhenAuthenticatedWithPasswordAndOttThenPermits() throws Exception {
|
void getWhenAuthenticatedWithPasswordAndOttThenPermits() throws Exception {
|
||||||
this.spring.register(EnableGlobalMultiFactorAuthenticationConfiguration.class, Http200Controller.class).autowire();
|
this.spring.register(EnableMultiFactorAuthenticationConfiguration.class, Http200Controller.class).autowire();
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
this.mockMvc.perform(get("/"))
|
this.mockMvc.perform(get("/"))
|
||||||
.andExpect(status().isOk())
|
.andExpect(status().isOk())
|
||||||
@@ -65,7 +65,7 @@ public class EnableGlobalMultiFactorAuthenticationTests {
|
|||||||
@Test
|
@Test
|
||||||
@WithMockUser(authorities = FactorGrantedAuthority.PASSWORD_AUTHORITY)
|
@WithMockUser(authorities = FactorGrantedAuthority.PASSWORD_AUTHORITY)
|
||||||
void getWhenAuthenticatedWithPasswordThenRedirectsToOtt() throws Exception {
|
void getWhenAuthenticatedWithPasswordThenRedirectsToOtt() throws Exception {
|
||||||
this.spring.register(EnableGlobalMultiFactorAuthenticationConfiguration.class, Http200Controller.class).autowire();
|
this.spring.register(EnableMultiFactorAuthenticationConfiguration.class, Http200Controller.class).autowire();
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
this.mockMvc.perform(get("/"))
|
this.mockMvc.perform(get("/"))
|
||||||
.andExpect(status().is3xxRedirection())
|
.andExpect(status().is3xxRedirection())
|
||||||
@@ -76,7 +76,7 @@ public class EnableGlobalMultiFactorAuthenticationTests {
|
|||||||
@Test
|
@Test
|
||||||
@WithMockUser(authorities = FactorGrantedAuthority.OTT_AUTHORITY)
|
@WithMockUser(authorities = FactorGrantedAuthority.OTT_AUTHORITY)
|
||||||
void getWhenAuthenticatedWithOttThenRedirectsToPassword() throws Exception {
|
void getWhenAuthenticatedWithOttThenRedirectsToPassword() throws Exception {
|
||||||
this.spring.register(EnableGlobalMultiFactorAuthenticationConfiguration.class, Http200Controller.class).autowire();
|
this.spring.register(EnableMultiFactorAuthenticationConfiguration.class, Http200Controller.class).autowire();
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
this.mockMvc.perform(get("/"))
|
this.mockMvc.perform(get("/"))
|
||||||
.andExpect(status().is3xxRedirection())
|
.andExpect(status().is3xxRedirection())
|
||||||
@@ -87,7 +87,7 @@ public class EnableGlobalMultiFactorAuthenticationTests {
|
|||||||
@Test
|
@Test
|
||||||
@WithMockUser
|
@WithMockUser
|
||||||
void getWhenAuthenticatedThenRedirectsToPassword() throws Exception {
|
void getWhenAuthenticatedThenRedirectsToPassword() throws Exception {
|
||||||
this.spring.register(EnableGlobalMultiFactorAuthenticationConfiguration.class, Http200Controller.class).autowire();
|
this.spring.register(EnableMultiFactorAuthenticationConfiguration.class, Http200Controller.class).autowire();
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
this.mockMvc.perform(get("/"))
|
this.mockMvc.perform(get("/"))
|
||||||
.andExpect(status().is3xxRedirection())
|
.andExpect(status().is3xxRedirection())
|
||||||
@@ -97,7 +97,7 @@ public class EnableGlobalMultiFactorAuthenticationTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void getWhenUnauthenticatedThenRedirectsToBoth() throws Exception {
|
void getWhenUnauthenticatedThenRedirectsToBoth() throws Exception {
|
||||||
this.spring.register(EnableGlobalMultiFactorAuthenticationConfiguration.class, Http200Controller.class).autowire();
|
this.spring.register(EnableMultiFactorAuthenticationConfiguration.class, Http200Controller.class).autowire();
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
this.mockMvc.perform(get("/"))
|
this.mockMvc.perform(get("/"))
|
||||||
.andExpect(status().is3xxRedirection())
|
.andExpect(status().is3xxRedirection())
|
||||||
+4
@@ -5,6 +5,7 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
import org.springframework.security.authorization.AuthorizationManagerFactories;
|
import org.springframework.security.authorization.AuthorizationManagerFactories;
|
||||||
import org.springframework.security.authorization.AuthorizationManagerFactory;
|
import org.springframework.security.authorization.AuthorizationManagerFactory;
|
||||||
import org.springframework.security.config.Customizer;
|
import org.springframework.security.config.Customizer;
|
||||||
|
import org.springframework.security.config.annotation.authorization.EnableMultiFactorAuthentication;
|
||||||
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;
|
||||||
import org.springframework.security.core.authority.FactorGrantedAuthority;
|
import org.springframework.security.core.authority.FactorGrantedAuthority;
|
||||||
@@ -16,6 +17,9 @@ import org.springframework.security.web.authentication.ott.OneTimeTokenGeneratio
|
|||||||
import org.springframework.security.web.authentication.ott.RedirectOneTimeTokenGenerationSuccessHandler;
|
import org.springframework.security.web.authentication.ott.RedirectOneTimeTokenGenerationSuccessHandler;
|
||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
|
// tag::enable-mfa[]
|
||||||
|
@EnableMultiFactorAuthentication(authorities = {})
|
||||||
|
// end::enable-mfa[]
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
class SelectiveMfaConfiguration {
|
class SelectiveMfaConfiguration {
|
||||||
|
|
||||||
|
|||||||
+6
-6
@@ -1,8 +1,8 @@
|
|||||||
package org.springframework.security.kt.docs.servlet.authentication.egmfa
|
package org.springframework.security.kt.docs.servlet.authentication.emfa
|
||||||
|
|
||||||
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.config.annotation.authorization.EnableGlobalMultiFactorAuthentication
|
import org.springframework.security.config.annotation.authorization.EnableMultiFactorAuthentication
|
||||||
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
|
||||||
import org.springframework.security.config.annotation.web.invoke
|
import org.springframework.security.config.annotation.web.invoke
|
||||||
@@ -17,12 +17,12 @@ import org.springframework.security.web.authentication.ott.RedirectOneTimeTokenG
|
|||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
|
||||||
// tag::enable-global-mfa[]
|
// tag::enable-mfa[]
|
||||||
@EnableGlobalMultiFactorAuthentication( authorities = [
|
@EnableMultiFactorAuthentication( authorities = [
|
||||||
FactorGrantedAuthority.PASSWORD_AUTHORITY,
|
FactorGrantedAuthority.PASSWORD_AUTHORITY,
|
||||||
FactorGrantedAuthority.OTT_AUTHORITY])
|
FactorGrantedAuthority.OTT_AUTHORITY])
|
||||||
// end::enable-global-mfa[]
|
// end::enable-mfa[]
|
||||||
internal class EnableGlobalMultiFactorAuthenticationConfiguration {
|
internal class EnableMultiFactorAuthenticationConfiguration {
|
||||||
|
|
||||||
// tag::httpSecurity[]
|
// tag::httpSecurity[]
|
||||||
@Bean
|
@Bean
|
||||||
+7
-7
@@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springframework.security.kt.docs.servlet.authentication.egmfa
|
package org.springframework.security.kt.docs.servlet.authentication.emfa
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.extension.ExtendWith
|
import org.junit.jupiter.api.extension.ExtendWith
|
||||||
@@ -39,7 +39,7 @@ import org.springframework.web.bind.annotation.RestController
|
|||||||
*/
|
*/
|
||||||
@ExtendWith(SpringExtension::class, SpringTestContextExtension::class)
|
@ExtendWith(SpringExtension::class, SpringTestContextExtension::class)
|
||||||
@TestExecutionListeners(WithSecurityContextTestExecutionListener::class)
|
@TestExecutionListeners(WithSecurityContextTestExecutionListener::class)
|
||||||
class EnableGlobalMultiFactorAuthenticationConfigurationTests {
|
class EnableMultiFactorAuthenticationConfigurationTests {
|
||||||
@JvmField
|
@JvmField
|
||||||
val spring: SpringTestContext = SpringTestContext(this)
|
val spring: SpringTestContext = SpringTestContext(this)
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ class EnableGlobalMultiFactorAuthenticationConfigurationTests {
|
|||||||
@WithMockUser(authorities = [FactorGrantedAuthority.PASSWORD_AUTHORITY, FactorGrantedAuthority.OTT_AUTHORITY, "ROLE_ADMIN"])
|
@WithMockUser(authorities = [FactorGrantedAuthority.PASSWORD_AUTHORITY, FactorGrantedAuthority.OTT_AUTHORITY, "ROLE_ADMIN"])
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
fun getWhenAuthenticatedWithPasswordAndOttThenPermits() {
|
fun getWhenAuthenticatedWithPasswordAndOttThenPermits() {
|
||||||
this.spring.register(EnableGlobalMultiFactorAuthenticationConfiguration::class.java, Http200Controller::class.java).autowire()
|
this.spring.register(EnableMultiFactorAuthenticationConfiguration::class.java, Http200Controller::class.java).autowire()
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
this.mockMvc!!.perform(MockMvcRequestBuilders.get("/"))
|
this.mockMvc!!.perform(MockMvcRequestBuilders.get("/"))
|
||||||
.andExpect(MockMvcResultMatchers.status().isOk())
|
.andExpect(MockMvcResultMatchers.status().isOk())
|
||||||
@@ -62,7 +62,7 @@ class EnableGlobalMultiFactorAuthenticationConfigurationTests {
|
|||||||
@WithMockUser(authorities = [FactorGrantedAuthority.PASSWORD_AUTHORITY])
|
@WithMockUser(authorities = [FactorGrantedAuthority.PASSWORD_AUTHORITY])
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
fun getWhenAuthenticatedWithPasswordThenRedirectsToOtt() {
|
fun getWhenAuthenticatedWithPasswordThenRedirectsToOtt() {
|
||||||
this.spring.register(EnableGlobalMultiFactorAuthenticationConfiguration::class.java, Http200Controller::class.java).autowire()
|
this.spring.register(EnableMultiFactorAuthenticationConfiguration::class.java, Http200Controller::class.java).autowire()
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
this.mockMvc!!.perform(MockMvcRequestBuilders.get("/"))
|
this.mockMvc!!.perform(MockMvcRequestBuilders.get("/"))
|
||||||
.andExpect(MockMvcResultMatchers.status().is3xxRedirection())
|
.andExpect(MockMvcResultMatchers.status().is3xxRedirection())
|
||||||
@@ -74,7 +74,7 @@ class EnableGlobalMultiFactorAuthenticationConfigurationTests {
|
|||||||
@WithMockUser(authorities = [FactorGrantedAuthority.OTT_AUTHORITY])
|
@WithMockUser(authorities = [FactorGrantedAuthority.OTT_AUTHORITY])
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
fun getWhenAuthenticatedWithOttThenRedirectsToPassword() {
|
fun getWhenAuthenticatedWithOttThenRedirectsToPassword() {
|
||||||
this.spring.register(EnableGlobalMultiFactorAuthenticationConfiguration::class.java, Http200Controller::class.java).autowire()
|
this.spring.register(EnableMultiFactorAuthenticationConfiguration::class.java, Http200Controller::class.java).autowire()
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
this.mockMvc!!.perform(MockMvcRequestBuilders.get("/"))
|
this.mockMvc!!.perform(MockMvcRequestBuilders.get("/"))
|
||||||
.andExpect(MockMvcResultMatchers.status().is3xxRedirection())
|
.andExpect(MockMvcResultMatchers.status().is3xxRedirection())
|
||||||
@@ -86,7 +86,7 @@ class EnableGlobalMultiFactorAuthenticationConfigurationTests {
|
|||||||
@WithMockUser
|
@WithMockUser
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
fun getWhenAuthenticatedThenRedirectsToPassword() {
|
fun getWhenAuthenticatedThenRedirectsToPassword() {
|
||||||
this.spring.register(EnableGlobalMultiFactorAuthenticationConfiguration::class.java, Http200Controller::class.java).autowire()
|
this.spring.register(EnableMultiFactorAuthenticationConfiguration::class.java, Http200Controller::class.java).autowire()
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
this.mockMvc!!.perform(MockMvcRequestBuilders.get("/"))
|
this.mockMvc!!.perform(MockMvcRequestBuilders.get("/"))
|
||||||
.andExpect(MockMvcResultMatchers.status().is3xxRedirection())
|
.andExpect(MockMvcResultMatchers.status().is3xxRedirection())
|
||||||
@@ -97,7 +97,7 @@ class EnableGlobalMultiFactorAuthenticationConfigurationTests {
|
|||||||
@Test
|
@Test
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
fun getWhenUnauthenticatedThenRedirectsToBoth() {
|
fun getWhenUnauthenticatedThenRedirectsToBoth() {
|
||||||
this.spring.register(EnableGlobalMultiFactorAuthenticationConfiguration::class.java, Http200Controller::class.java).autowire()
|
this.spring.register(EnableMultiFactorAuthenticationConfiguration::class.java, Http200Controller::class.java).autowire()
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
this.mockMvc!!.perform(MockMvcRequestBuilders.get("/"))
|
this.mockMvc!!.perform(MockMvcRequestBuilders.get("/"))
|
||||||
.andExpect(MockMvcResultMatchers.status().is3xxRedirection())
|
.andExpect(MockMvcResultMatchers.status().is3xxRedirection())
|
||||||
+4
@@ -4,6 +4,7 @@ import org.springframework.context.annotation.Bean
|
|||||||
import org.springframework.context.annotation.Configuration
|
import org.springframework.context.annotation.Configuration
|
||||||
import org.springframework.security.authorization.AuthorizationManagerFactories
|
import org.springframework.security.authorization.AuthorizationManagerFactories
|
||||||
import org.springframework.security.authorization.AuthorizationManagerFactory
|
import org.springframework.security.authorization.AuthorizationManagerFactory
|
||||||
|
import org.springframework.security.config.annotation.authorization.EnableMultiFactorAuthentication
|
||||||
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
|
||||||
import org.springframework.security.config.annotation.web.invoke
|
import org.springframework.security.config.annotation.web.invoke
|
||||||
@@ -15,6 +16,9 @@ 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
|
||||||
|
|
||||||
|
// tag::enable-mfa[]
|
||||||
|
@EnableMultiFactorAuthentication(authorities = [])
|
||||||
|
// end::enable-mfa[]
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
internal class SelectiveMfaConfiguration {
|
internal class SelectiveMfaConfiguration {
|
||||||
|
|||||||
Reference in New Issue
Block a user