Skip to content

Commit e641403

Browse files
committed
Add Sample Doc
1 parent 293553c commit e641403

File tree

1 file changed

+186
-0
lines changed
  • docs/modules/ROOT/pages/servlet/authentication

1 file changed

+186
-0
lines changed
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
= Multi-Factor Authentication
2+
3+
Spring Security 7+ supports Multi-factor Authentication.
4+
This means that you can supply multiple authentication mechanisms and require that they be provided in a certain order for the principal to be deemed fully authenticated.
5+
6+
This is provided by way of authorities that represent each completed authentication.
7+
For example, when form login is completed, the resulting authentication will include an `AUTHN_FORM` granted authority.
8+
9+
This means that you can require that a certain endpoint require form login by specifying the authority in the `authorizeHttpRequests` DSL like so:
10+
11+
[tabs]
12+
======
13+
Java::
14+
+
15+
[source,java,role="primary"]
16+
----
17+
@Bean
18+
SecurityFilterChain filterchain(HttpSecurity http) throws Exception {
19+
http
20+
.authorizeHttpRequests((authorize) -> authorize
21+
.anyRequest().hasAuthority("AUTHN_FORM")
22+
)
23+
.formLogin((form) -> form.factor(Customizer.withDefaults()));
24+
return http.build();
25+
}
26+
----
27+
28+
Kotlin::
29+
+
30+
[source,kotlin,role="secondary"]
31+
----
32+
@Bean
33+
fun filterChain(val http: HttpSecurity): SecurityFilterChain {
34+
http {
35+
authorizeHttpRequests {
36+
authorize(anyRequest, hasAuthority("AUTHN_FORM"))
37+
formLogin {
38+
factor {}
39+
}
40+
}
41+
}
42+
return http.build()
43+
}
44+
----
45+
======
46+
47+
== Architecture
48+
49+
Each authentication factor in Spring Security is represented by a filter in the filter chain.
50+
Any authentication factor participating in multi-factor authentication is augmented in three ways:
51+
52+
1. Its authentication manager grants at least an authority that represents the completed authorization, for example, `AUTHN_FORM` for form login `AUTHN_BEARER` for bearer tokens.
53+
2. It adds its `AUTHN_XXX` authority as a default-required authority to the `authorizeHttpRequests` DSL.
54+
3. It registers an `AuthorizationEntryPoint` to the `exceptionHandling` DSL to indicate what authorization requests it can grant and how to request them.
55+
56+
== Requiring More Than One Factor
57+
58+
You can register any Spring Security authentication mechanism as an authentication factor using the exposed `.factor` DSL like so:
59+
60+
[tabs]
61+
======
62+
Java::
63+
+
64+
[source,java,role="primary"]
65+
----
66+
@Bean
67+
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
68+
http
69+
.authorizeHttpRequests((authorize) -> authorize.anyRequest().authenticated())
70+
.x509((x509) -> x509.factor(Customizer.withDefaults()))
71+
.formLogin((form) -> form.factor(Customizer.withDefaults()));
72+
return http.build();
73+
}
74+
----
75+
76+
Kotlin::
77+
+
78+
[source,kotlin,role="secondary"]
79+
----
80+
@Bean
81+
fun filterChain(val http: HttpSecurity): SecurityFilterChain {
82+
http {
83+
authorizeHttpRequests {
84+
authorize(anyRequest, authenticated)
85+
x509 {
86+
factor {}
87+
}
88+
formLogin {
89+
factor {}
90+
}
91+
}
92+
}
93+
}
94+
----
95+
======
96+
97+
[TIP]
98+
=====
99+
You can identity additional authentication mechanisms that are not a factor in your multi-factor authentication setup.
100+
In this case, you should use `.access()` to override any default authentication manager that is added to other authorization rules.
101+
Or, you can publish a custom `AuthorizationManagerFactory` bean.
102+
=====
103+
104+
[TIP]
105+
=====
106+
Generally speaking, the order in which you declare the factors is the order in which Spring Security will attempt them when collecting the needed authorities.
107+
Note however, if you have overridden the `AuthenticationEntryPoint` or are using factors that register a `defaultAuthenticationEntryPointFor`, these will take precedence.
108+
=====
109+
110+
== Granting additional authorities
111+
112+
You may want to grant additional authorities.
113+
This can be done in the DSL by stating the name of the authority tied to the mechanism.
114+
115+
For example, you may have an authority that you want to grant for only a few minutes, so that it can be asked for again later on in the case of a more highly-sensitive page:
116+
117+
[tabs]
118+
======
119+
Java::
120+
+
121+
[source,java,role="primary"]
122+
----
123+
@Bean
124+
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
125+
http
126+
.authorizeHttpRequests((authorize) -> authorize
127+
.requestMatchers("/profile/**").hasAuthority("profile:read")
128+
.anyRequest().authenticated()
129+
)
130+
.x509((x509) -> x509.factor(Customizer.withDefaults()))
131+
.formLogin((form) -> form.factor((f) -> f
132+
.grants(Duration.ofMinutes(5), "profile:read")
133+
));
134+
return http.build();
135+
}
136+
----
137+
138+
Kotlin::
139+
+
140+
[source,kotlin,role="secondary"]
141+
----
142+
@Bean
143+
fun filterChain(val http: HttpSecurity): SecurityFilterChain {
144+
http {
145+
authorizeHttpRequests {
146+
authorize("/profile/**", hasAuthority("profile:read"))
147+
authorize(anyRequest, authenticated)
148+
x509 {
149+
factor {}
150+
}
151+
formLogin {
152+
factor {
153+
grants(Duration.ofMinutes(5), "profile:read")
154+
}
155+
}
156+
}
157+
}
158+
}
159+
----
160+
======
161+
162+
The above indicates that the `/profile/**` endpoints are more sensitive and require re-authorization in order to go to them, if that authorization hasn't been obtained in the last five minutes.
163+
It further states that the "profile:read" authority can be re-obtained using form login.
164+
165+
== Registering a custom entry point
166+
167+
Sometimes the way an authentication factor works when already logged in is different then when you are not yet logged in.
168+
169+
For example, a form login page may not need you to provide the username again, only the credentials.
170+
Or an OTT login page may simply auto-POST since it already has all the information it needs to generate the token.
171+
172+
You can register a custom `AuthenticationEntryPoint` to indicate post-authentication behavior by calling the `authenticationEntryPoint` method in the `factor` DSL.
173+
174+
[TIP]
175+
====
176+
A handy implementation is `PostAuthenticationEntryPoint`, which uses `FormPostRedirectStrategy` to create an auto-POST page.
177+
====
178+
179+
[NOTE]
180+
====
181+
Like other nested DSLs in Spring Security, if you have a custom `AuthenticationEntryPoint` in your factor's main configuration, you will either need to provide that or the appropriate post-authentication version to the `factor` DSL.
182+
====
183+
184+
== Custom authentication factors
185+
186+
You can provide a custom authentication factor by using the `MfaConfigurer` configurer, which comes with the needed configuration methods to register extra authorities and a custom `AuthenticationEntryPoint`.

0 commit comments

Comments
 (0)