0
# Provider Selection
1
2
Specialized components for handling composite MFA scenarios where multiple providers are available and selection logic is required. These components manage the process of presenting provider choices to users and handling their selections with persistence capabilities.
3
4
## Capabilities
5
6
### MultifactorProviderSelectionCriteria
7
8
Functional interface that defines strategy for determining when to proceed with MFA provider selection.
9
10
```java { .api }
11
/**
12
* Strategy interface for determining when to proceed with MFA provider selection
13
*/
14
@FunctionalInterface
15
public interface MultifactorProviderSelectionCriteria {
16
17
/**
18
* Determine if MFA provider selection should proceed
19
* @param requestContext The webflow request context
20
* @return true if provider selection should proceed
21
*/
22
boolean shouldProceedWithMultifactorProviderSelection(RequestContext requestContext);
23
24
/**
25
* Static factory method for creating default criteria
26
* @return Default criteria instance
27
*/
28
static MultifactorProviderSelectionCriteria select() {
29
return context -> true; // Default implementation always proceeds
30
}
31
}
32
```
33
34
**Usage Example:**
35
36
```java
37
// Custom selection criteria
38
MultifactorProviderSelectionCriteria customCriteria = requestContext -> {
39
val authentication = WebUtils.getAuthentication(requestContext);
40
val principal = authentication.getPrincipal();
41
42
// Only proceed with selection if user has multiple registered devices
43
val devices = getRegisteredDevicesForUser(principal);
44
return devices.size() > 1;
45
};
46
47
// Use in action configuration
48
@Bean
49
public MultifactorProviderSelectionCriteria mfaSelectionCriteria() {
50
return MultifactorProviderSelectionCriteria.select(); // or custom implementation
51
}
52
```
53
54
### MultifactorProviderSelectionAction
55
56
Action that evaluates selection criteria to determine if provider selection should proceed.
57
58
```java { .api }
59
/**
60
* Action that evaluates selection criteria to determine if provider selection should proceed
61
*/
62
public class MultifactorProviderSelectionAction extends BaseCasWebflowAction {
63
64
/**
65
* Constructor
66
* @param selectionCriteria Criteria for determining if selection should proceed
67
*/
68
public MultifactorProviderSelectionAction(MultifactorProviderSelectionCriteria selectionCriteria);
69
70
/**
71
* Execute provider selection evaluation
72
* @param requestContext The webflow request context
73
* @return Event indicating whether to proceed with selection (yes/no)
74
* @throws Exception If evaluation fails
75
*/
76
@Override
77
protected Event doExecuteInternal(RequestContext requestContext) throws Exception;
78
}
79
```
80
81
### PrepareMultifactorProviderSelectionAction
82
83
Prepares available MFA providers for selection based on availability and bypass rules.
84
85
```java { .api }
86
/**
87
* Action that prepares available MFA providers for selection based on availability and bypass rules
88
*/
89
public class PrepareMultifactorProviderSelectionAction extends BaseCasWebflowAction {
90
91
/**
92
* Constructor
93
* @param applicationContext Spring application context
94
*/
95
public PrepareMultifactorProviderSelectionAction(ConfigurableApplicationContext applicationContext);
96
97
/**
98
* Execute provider preparation for selection
99
* @param requestContext The webflow request context
100
* @return Event indicating success or failure of preparation
101
* @throws Exception If preparation fails
102
*/
103
@Override
104
protected Event doExecuteInternal(RequestContext requestContext) throws Exception;
105
}
106
```
107
108
### MultifactorProviderSelectedAction
109
110
Handles the selection of a specific MFA provider and remembers the choice via cookies.
111
112
```java { .api }
113
/**
114
* Action that handles selection of a specific MFA provider and remembers the choice
115
*/
116
public class MultifactorProviderSelectedAction extends BaseCasWebflowAction {
117
118
/**
119
* Request parameter name for the selected MFA provider
120
*/
121
static final String PARAMETER_SELECTED_MFA_PROVIDER = "mfaProvider";
122
123
/**
124
* Constructor
125
* @param multifactorProviderCookieBuilder Cookie generator for remembering selection
126
* @param casProperties CAS configuration properties
127
*/
128
public MultifactorProviderSelectedAction(
129
CasCookieBuilder multifactorProviderCookieBuilder,
130
CasConfigurationProperties casProperties);
131
132
/**
133
* Pre-execution hook for provider selection
134
* @param context The webflow request context
135
* @return Event result of pre-execution
136
* @throws Exception If pre-execution fails
137
*/
138
@Override
139
protected Event doPreExecute(RequestContext context) throws Exception;
140
141
/**
142
* Execute provider selection handling
143
* @param requestContext The webflow request context
144
* @return Event indicating success or failure of selection
145
* @throws Exception If selection handling fails
146
*/
147
@Override
148
protected Event doExecuteInternal(RequestContext requestContext) throws Exception;
149
150
/**
151
* Remember the selected multifactor authentication provider via cookie
152
* @param context The webflow request context
153
* @param providerId The selected provider ID
154
*/
155
protected void rememberSelectedMultifactorAuthenticationProvider(RequestContext context, String providerId);
156
}
157
```
158
159
**Complete Provider Selection Flow Example:**
160
161
```java
162
@Configuration
163
public class CompositeProviderSelectionConfiguration {
164
165
@Bean
166
public MultifactorProviderSelectionCriteria compositeProviderSelectionCriteria() {
167
return requestContext -> {
168
// Get available providers from flow scope
169
val availableProviders = MultifactorAuthenticationWebflowUtils
170
.getSelectableMultifactorAuthenticationProviders(requestContext);
171
172
// Only proceed with selection if multiple providers are available
173
return availableProviders != null && availableProviders.size() > 1;
174
};
175
}
176
177
@Bean
178
public Action multifactorProviderSelectionAction(
179
MultifactorProviderSelectionCriteria selectionCriteria) {
180
return new MultifactorProviderSelectionAction(selectionCriteria);
181
}
182
183
@Bean
184
public Action prepareMultifactorProviderSelectionAction(
185
ConfigurableApplicationContext applicationContext) {
186
return new PrepareMultifactorProviderSelectionAction(applicationContext);
187
}
188
189
@Bean
190
public Action multifactorProviderSelectedAction(
191
@Qualifier("compositeProviderSelectionCookieGenerator")
192
CasCookieBuilder cookieGenerator,
193
CasConfigurationProperties casProperties) {
194
return new MultifactorProviderSelectedAction(cookieGenerator, casProperties);
195
}
196
197
@Bean
198
public CasCookieBuilder compositeProviderSelectionCookieGenerator(
199
CasConfigurationProperties casProperties) {
200
return new DefaultCasCookieBuilder(
201
"COMPOSITE_MFA_PROVIDER_SELECTION",
202
casProperties.getSessionReplication().getCookie());
203
}
204
}
205
```
206
207
**Webflow Integration Example:**
208
209
The provider selection actions are typically used in a webflow sequence like this:
210
211
```xml
212
<!-- Check if provider selection should proceed -->
213
<action-state id="checkCompositeProviderSelection">
214
<evaluate expression="multifactorProviderSelectionAction"/>
215
<transition on="yes" to="prepareProviderSelection"/>
216
<transition on="no" to="mfaCheckAvailable"/>
217
</action-state>
218
219
<!-- Prepare available providers for selection -->
220
<action-state id="prepareProviderSelection">
221
<evaluate expression="prepareMultifactorProviderSelectionAction"/>
222
<transition on="success" to="viewProviderSelection"/>
223
<transition on="error" to="mfaUnavailable"/>
224
</action-state>
225
226
<!-- Display provider selection view -->
227
<view-state id="viewProviderSelection" view="mfa/casCompositeProviderSelectionView">
228
<transition on="submit" to="providerSelected"/>
229
</view-state>
230
231
<!-- Handle provider selection -->
232
<action-state id="providerSelected">
233
<evaluate expression="multifactorProviderSelectedAction"/>
234
<transition on="success" to="mfaCheckAvailable"/>
235
<transition on="error" to="viewProviderSelection"/>
236
</action-state>
237
```
238
239
**JSP/Thymeleaf View Example:**
240
241
```html
242
<!-- Provider selection form -->
243
<form method="post">
244
<div class="mfa-provider-selection">
245
<h3>Select Authentication Method</h3>
246
247
<c:forEach var="provider" items="${mfaSelectableProviders}">
248
<div class="provider-option">
249
<input type="radio"
250
name="mfaProvider"
251
value="${provider}"
252
id="provider_${provider}"/>
253
<label for="provider_${provider}">
254
${provider} <!-- Or lookup friendly name -->
255
</label>
256
</div>
257
</c:forEach>
258
259
<button type="submit" name="_eventId" value="submit">Continue</button>
260
</div>
261
</form>
262
```
263
264
## Cookie-based Provider Memory
265
266
The `MultifactorProviderSelectedAction` automatically remembers user selections via cookies:
267
268
```java
269
// Cookie configuration example
270
@Bean
271
public CasCookieBuilder compositeProviderSelectionCookieGenerator(
272
CasConfigurationProperties casProperties) {
273
274
val cookieProps = casProperties.getSessionReplication().getCookie();
275
return CasCookieBuilder.builder()
276
.name("COMPOSITE_MFA_PROVIDER_SELECTION")
277
.domain(cookieProps.getDomain())
278
.path(cookieProps.getPath())
279
.maxAge(Duration.ofDays(30)) // Remember for 30 days
280
.secure(cookieProps.isSecure())
281
.httpOnly(cookieProps.isHttpOnly())
282
.sameSitePolicy(cookieProps.getSameSitePolicy())
283
.build();
284
}
285
```
286
287
This enables the system to automatically select the user's previously chosen provider in future authentication attempts, reducing friction while still allowing users to change their selection when needed.