0
# Webflow Actions
1
2
Action classes that execute during webflow state transitions to perform MFA-specific operations like availability checks, bypassing, device management, and failure handling. Actions bridge the gap between webflow states and MFA provider implementations.
3
4
## Capabilities
5
6
### AbstractMultifactorAuthenticationAction
7
8
Base generic action class providing common functionality for MFA actions including provider resolution and principal resolution.
9
10
```java { .api }
11
/**
12
* Abstract base class for MFA actions providing provider resolution and principal resolution hooks
13
* @param <T> Type of MultifactorAuthenticationProvider this action works with
14
*/
15
public abstract class AbstractMultifactorAuthenticationAction<T extends MultifactorAuthenticationProvider>
16
extends BaseCasWebflowAction {
17
18
/**
19
* The resolved provider for this flow (available to subclasses)
20
*/
21
protected T provider;
22
23
/**
24
* Pre-execution hook that resolves the MFA provider for this flow
25
* @param requestContext The webflow request context
26
* @return Event result of pre-execution (typically null to continue)
27
* @throws Exception If provider resolution fails
28
*/
29
@Override
30
protected Event doPreExecute(RequestContext requestContext) throws Exception;
31
32
/**
33
* Resolve principal using available MultifactorAuthenticationPrincipalResolver instances
34
* @param principal The principal to resolve
35
* @param requestContext The webflow request context
36
* @return Resolved principal
37
*/
38
protected Principal resolvePrincipal(Principal principal, RequestContext requestContext);
39
40
/**
41
* Get throttled request key for authentication throttling
42
* @param authentication Current authentication
43
* @param requestContext The webflow request context
44
* @return Throttling key (typically principal ID)
45
*/
46
protected String getThrottledRequestKeyFor(Authentication authentication, RequestContext requestContext);
47
}
48
```
49
50
**Usage Example:**
51
52
```java
53
public class MyMfaVerificationAction extends AbstractMultifactorAuthenticationAction<MyMfaProvider> {
54
55
@Override
56
protected Event doExecuteInternal(RequestContext requestContext) throws Exception {
57
// Provider is automatically resolved and available as this.provider
58
val authentication = WebUtils.getAuthentication(requestContext);
59
val principal = resolvePrincipal(authentication.getPrincipal(), requestContext);
60
61
// Get MFA token from request
62
val token = requestContext.getRequestParameters().get("token");
63
64
// Verify token using the resolved provider
65
if (provider.verify(principal, token)) {
66
return success();
67
} else {
68
return error();
69
}
70
}
71
}
72
```
73
74
### MultifactorAuthenticationAvailableAction
75
76
Determines if an MFA provider is available to provide authentication.
77
78
```java { .api }
79
/**
80
* Action that determines if MFA provider is available for authentication
81
*/
82
public class MultifactorAuthenticationAvailableAction
83
extends AbstractMultifactorAuthenticationAction<MultifactorAuthenticationProvider> {
84
85
/**
86
* Default constructor - uses inherited constructor from AbstractMultifactorAuthenticationAction
87
*/
88
public MultifactorAuthenticationAvailableAction();
89
90
/**
91
* Execute availability check for the MFA provider
92
* @param requestContext The webflow request context
93
* @return Event indicating availability (yes/no)
94
* @throws Exception If availability check fails
95
*/
96
@Override
97
protected Event doExecuteInternal(RequestContext requestContext) throws Exception;
98
}
99
```
100
101
### MultifactorAuthenticationBypassAction
102
103
Determines if MFA provider can be bypassed for the current user and service.
104
105
```java { .api }
106
/**
107
* Action that determines if MFA provider can be bypassed
108
*/
109
public class MultifactorAuthenticationBypassAction
110
extends AbstractMultifactorAuthenticationAction<MultifactorAuthenticationProvider> {
111
112
/**
113
* Default constructor - uses inherited constructor from AbstractMultifactorAuthenticationAction
114
*/
115
public MultifactorAuthenticationBypassAction();
116
117
/**
118
* Execute bypass check for the MFA provider
119
* @param requestContext The webflow request context
120
* @return Event indicating bypass decision (yes/no)
121
* @throws Exception If bypass check fails
122
*/
123
@Override
124
protected Event doExecuteInternal(RequestContext requestContext) throws Exception;
125
126
/**
127
* Check if multifactor authentication should be bypassed
128
* @param requestContext The webflow request context
129
* @param registeredService The service being accessed
130
* @param provider The MFA provider
131
* @return true if MFA should be bypassed
132
*/
133
protected boolean isMultifactorAuthenticationBypass(
134
RequestContext requestContext,
135
RegisteredService registeredService,
136
MultifactorAuthenticationProvider provider);
137
}
138
```
139
140
### MultifactorAuthenticationFailureAction
141
142
Handles MFA provider failure scenarios and determines appropriate failure mode.
143
144
```java { .api }
145
/**
146
* Action that handles MFA provider failure scenarios
147
*/
148
public class MultifactorAuthenticationFailureAction
149
extends AbstractMultifactorAuthenticationAction<MultifactorAuthenticationProvider> {
150
151
/**
152
* Default constructor - uses inherited constructor from AbstractMultifactorAuthenticationAction
153
*/
154
public MultifactorAuthenticationFailureAction();
155
156
/**
157
* Execute failure handling for the MFA provider
158
* @param requestContext The webflow request context
159
* @return Event indicating failure mode (unavailable/bypass)
160
* @throws Exception If failure handling fails
161
*/
162
@Override
163
protected Event doExecuteInternal(RequestContext requestContext) throws Exception;
164
}
165
```
166
167
### MultifactorAuthenticationDeviceProviderAction
168
169
Functional interface for actions that provide MFA device information.
170
171
```java { .api }
172
/**
173
* Functional interface for actions that provide MFA device information
174
*/
175
@FunctionalInterface
176
public interface MultifactorAuthenticationDeviceProviderAction extends Action, Ordered, NamedObject {
177
178
/**
179
* Get execution order for this action
180
* @return Order value (default LOWEST_PRECEDENCE)
181
*/
182
@Override
183
default int getOrder() {
184
return Ordered.LOWEST_PRECEDENCE;
185
}
186
}
187
```
188
189
### MultifactorAuthenticationTrustedDeviceProviderAction
190
191
Functional interface for actions that handle trusted device information in MFA flows.
192
193
```java { .api }
194
/**
195
* Functional interface for actions that handle trusted device information in MFA flows
196
*/
197
@FunctionalInterface
198
public interface MultifactorAuthenticationTrustedDeviceProviderAction extends Action, Ordered, NamedObject {
199
200
/**
201
* Get execution order for this action
202
* @return Order value (default LOWEST_PRECEDENCE)
203
*/
204
@Override
205
default int getOrder() {
206
return Ordered.LOWEST_PRECEDENCE;
207
}
208
}
209
```
210
211
### DefaultMultifactorAuthenticationDeviceProviderAction
212
213
Default implementation for loading registered MFA devices for a user.
214
215
```java { .api }
216
/**
217
* Default implementation for loading registered MFA devices for a user
218
*/
219
public class DefaultMultifactorAuthenticationDeviceProviderAction
220
implements MultifactorAuthenticationDeviceProviderAction {
221
222
/**
223
* Constructor
224
* @param deviceManager MFA device manager for loading devices
225
*/
226
public DefaultMultifactorAuthenticationDeviceProviderAction(
227
MultifactorAuthenticationDeviceManager deviceManager);
228
229
/**
230
* Execute device loading action
231
* @param context The action execution context
232
* @return Event result of device loading
233
* @throws Exception If device loading fails
234
*/
235
@Override
236
public Event execute(RequestContext context) throws Exception;
237
238
/**
239
* Internal execution logic for device loading
240
* @param requestContext The webflow request context
241
* @return Event result
242
* @throws Exception If execution fails
243
*/
244
protected Event doExecuteInternal(RequestContext requestContext) throws Exception;
245
}
246
```
247
248
**Complete Action Implementation Example:**
249
250
```java
251
@Component
252
public class CustomMfaActions {
253
254
@Bean
255
public Action customMfaAvailabilityAction(ApplicationEventPublisher eventPublisher) {
256
return new CustomMfaAvailabilityAction(eventPublisher);
257
}
258
259
@Bean
260
public MultifactorAuthenticationDeviceProviderAction customDeviceAction(
261
MultifactorAuthenticationDeviceManager deviceManager) {
262
return new CustomDeviceProviderAction(deviceManager);
263
}
264
265
private static class CustomMfaAvailabilityAction extends MultifactorAuthenticationAvailableAction {
266
267
public CustomMfaAvailabilityAction(ApplicationEventPublisher eventPublisher) {
268
super(eventPublisher);
269
}
270
271
@Override
272
protected Event doExecuteInternal(RequestContext requestContext) throws Exception {
273
// this.provider is automatically resolved
274
val principal = WebUtils.getAuthentication(requestContext).getPrincipal();
275
276
// Custom availability logic
277
if (isProviderAvailableForUser(principal)) {
278
return new EventFactorySupport().event(this, CasWebflowConstants.TRANSITION_ID_YES);
279
}
280
return new EventFactorySupport().event(this, CasWebflowConstants.TRANSITION_ID_NO);
281
}
282
283
private boolean isProviderAvailableForUser(Principal principal) {
284
// Custom logic to check if provider is available for this user
285
return true;
286
}
287
}
288
289
private static class CustomDeviceProviderAction implements MultifactorAuthenticationDeviceProviderAction {
290
291
private final MultifactorAuthenticationDeviceManager deviceManager;
292
293
public CustomDeviceProviderAction(MultifactorAuthenticationDeviceManager deviceManager) {
294
this.deviceManager = deviceManager;
295
}
296
297
@Override
298
public Event execute(RequestContext context) throws Exception {
299
val authentication = WebUtils.getAuthentication(context);
300
val devices = deviceManager.findRegisteredDevices(authentication.getPrincipal());
301
302
MultifactorAuthenticationWebflowUtils.putMultifactorAuthenticationRegisteredDevices(context, devices);
303
return new EventFactorySupport().event(this, CasWebflowConstants.TRANSITION_ID_SUCCESS);
304
}
305
306
@Override
307
public String getName() {
308
return "customDeviceProviderAction";
309
}
310
}
311
}
312
```
313
314
## Action Integration
315
316
Actions are typically integrated into webflows through configuration:
317
318
```java
319
@Configuration
320
public class MyMfaWebflowActionsConfiguration {
321
322
@Bean
323
public Action myMfaCheckAvailableAction(ApplicationEventPublisher eventPublisher) {
324
return new MultifactorAuthenticationAvailableAction(eventPublisher);
325
}
326
327
@Bean
328
public Action myMfaCheckBypassAction(ApplicationEventPublisher eventPublisher) {
329
return new MultifactorAuthenticationBypassAction(eventPublisher);
330
}
331
332
@Bean
333
public Action myMfaFailureAction(ApplicationEventPublisher eventPublisher) {
334
return new MultifactorAuthenticationFailureAction(eventPublisher);
335
}
336
}
337
```
338
339
These actions are then referenced in webflow definitions by their bean names and executed during state transitions.