resolveEventViaAttribute(Principal,Map,Collection,RegisteredService,RequestContext,Collection,Predicate)   F
last analyzed

Complexity

Conditions 9

Size

Total Lines 37

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 37
c 0
b 0
f 0
cc 9
rs 3
1
package org.apereo.cas.web.flow.resolver.impl;
2
3
import org.apache.commons.lang3.StringUtils;
4
import org.apereo.cas.CentralAuthenticationService;
5
import org.apereo.cas.authentication.Authentication;
6
import org.apereo.cas.authentication.AuthenticationException;
7
import org.apereo.cas.authentication.AuthenticationResult;
8
import org.apereo.cas.authentication.AuthenticationResultBuilder;
9
import org.apereo.cas.authentication.AuthenticationServiceSelectionPlan;
10
import org.apereo.cas.authentication.AuthenticationSystemSupport;
11
import org.apereo.cas.authentication.Credential;
12
import org.apereo.cas.authentication.HandlerResult;
13
import org.apereo.cas.authentication.MessageDescriptor;
14
import org.apereo.cas.authentication.MultifactorAuthenticationUtils;
15
import org.apereo.cas.authentication.principal.Principal;
16
import org.apereo.cas.authentication.principal.Service;
17
import org.apereo.cas.services.MultifactorAuthenticationProvider;
18
import org.apereo.cas.services.MultifactorAuthenticationProviderSelector;
19
import org.apereo.cas.services.RegisteredService;
20
import org.apereo.cas.services.RegisteredServiceMultifactorPolicy;
21
import org.apereo.cas.services.ServicesManager;
22
import org.apereo.cas.ticket.TicketGrantingTicket;
23
import org.apereo.cas.ticket.registry.TicketRegistrySupport;
24
import org.apereo.cas.util.CollectionUtils;
25
import org.apereo.cas.web.flow.CasWebflowConstants;
26
import org.apereo.cas.web.flow.resolver.CasWebflowEventResolver;
27
import org.apereo.cas.web.support.WebUtils;
28
import org.slf4j.Logger;
29
import org.slf4j.LoggerFactory;
30
import org.springframework.beans.factory.annotation.Autowired;
31
import org.springframework.binding.message.MessageBuilder;
32
import org.springframework.binding.message.MessageContext;
33
import org.springframework.context.ApplicationEventPublisher;
34
import org.springframework.context.ConfigurableApplicationContext;
35
import org.springframework.web.util.CookieGenerator;
36
import org.springframework.webflow.action.EventFactorySupport;
37
import org.springframework.webflow.core.collection.AttributeMap;
38
import org.springframework.webflow.core.collection.LocalAttributeMap;
39
import org.springframework.webflow.definition.TransitionDefinition;
40
import org.springframework.webflow.execution.Event;
41
import org.springframework.webflow.execution.RequestContext;
42
43
import java.util.Collection;
44
import java.util.HashMap;
45
import java.util.HashSet;
46
import java.util.Map;
47
import java.util.Optional;
48
import java.util.Set;
49
import java.util.function.Predicate;
50
import java.util.stream.Collectors;
51
52
/**
53
 * This is {@link AbstractCasWebflowEventResolver} that provides parent
54
 * operations for all child event resolvers to handle core webflow changes.
55
 *
56
 * @author Misagh Moayyed
57
 * @since 5.0.0
58
 */
59
public abstract class AbstractCasWebflowEventResolver implements CasWebflowEventResolver {
60
61
    private static final String RESOLVED_AUTHENTICATION_EVENTS = "resolvedAuthenticationEvents";
62
    private static final String DEFAULT_MESSAGE_BUNDLE_PREFIX = "authenticationFailure.";
63
64
    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractCasWebflowEventResolver.class);
65
66
    /**
67
     * CAS event publisher.
68
     */
69
    @Autowired
70
    protected ApplicationEventPublisher eventPublisher;
71
72
    /**
73
     * The Application context.
74
     */
75
    @Autowired
76
    protected ConfigurableApplicationContext applicationContext;
77
78
    /**
79
     * The Authentication system support.
80
     */
81
    protected final AuthenticationSystemSupport authenticationSystemSupport;
82
83
    /**
84
     * Ticket registry support.
85
     */
86
    protected final TicketRegistrySupport ticketRegistrySupport;
87
88
    /**
89
     * The Services manager.
90
     */
91
    protected final ServicesManager servicesManager;
92
93
    /**
94
     * The Central authentication service.
95
     */
96
    protected final CentralAuthenticationService centralAuthenticationService;
97
98
    /**
99
     * Warn cookie generator.
100
     */
101
    protected final CookieGenerator warnCookieGenerator;
102
103
    /**
104
     * The mfa selector.
105
     */
106
    protected final MultifactorAuthenticationProviderSelector multifactorAuthenticationProviderSelector;
107
108
    /**
109
     * Extract the service specially in the event that it's proxied by a callback.
110
     */
111
    protected final AuthenticationServiceSelectionPlan authenticationRequestServiceSelectionStrategies;
112
113
    public AbstractCasWebflowEventResolver(final AuthenticationSystemSupport authenticationSystemSupport,
114
                                           final CentralAuthenticationService centralAuthenticationService, final ServicesManager servicesManager,
115
                                           final TicketRegistrySupport ticketRegistrySupport, final CookieGenerator warnCookieGenerator,
116
                                           final AuthenticationServiceSelectionPlan authenticationSelectionStrategies,
117
                                           final MultifactorAuthenticationProviderSelector selector) {
118
        this.authenticationSystemSupport = authenticationSystemSupport;
119
        this.centralAuthenticationService = centralAuthenticationService;
120
        this.servicesManager = servicesManager;
121
        this.ticketRegistrySupport = ticketRegistrySupport;
122
        this.warnCookieGenerator = warnCookieGenerator;
123
        authenticationRequestServiceSelectionStrategies = authenticationSelectionStrategies;
124
        multifactorAuthenticationProviderSelector = selector;
125
    }
126
127
    /**
128
     * Adds a warning message to the message context.
129
     *
130
     * @param context Message context.
131
     * @param warning Warning message.
132
     */
133
    protected static void addMessageDescriptorToMessageContext(final MessageContext context, final MessageDescriptor warning) {
134
        final MessageBuilder builder = new MessageBuilder()
135
                .warning()
136
                .code(warning.getCode())
137
                .defaultText(warning.getDefaultMessage())
138
                .args((Object[]) warning.getParams());
139
        context.addMessage(builder.build());
140
    }
141
142
    /**
143
     * New event based on the id, which contains an error attribute referring to the exception occurred.
144
     *
145
     * @param id    the id
146
     * @param error the error
147
     * @return the event
148
     */
149
    protected Event newEvent(final String id, final Exception error) {
150
        return new Event(this, id, new LocalAttributeMap(CasWebflowConstants.TRANSITION_ID_ERROR, error));
151
    }
152
153
    /**
154
     * New event based on the given id.
155
     *
156
     * @param id the id
157
     * @return the event
158
     */
159
    protected Event newEvent(final String id) {
160
        return new Event(this, id);
161
    }
162
163
    /**
164
     * Add warning messages to message context if needed.
165
     *
166
     * @param tgtId          the tgt id
167
     * @param messageContext the message context
168
     * @return true if warnings were found and added, false otherwise.
169
     * @since 4.1.0
170
     */
171
    private static boolean addWarningMessagesToMessageContextIfNeeded(final TicketGrantingTicket tgtId, final MessageContext messageContext) {
172
        boolean foundAndAddedWarnings = false;
173
        for (final Map.Entry<String, HandlerResult> entry : tgtId.getAuthentication().getSuccesses().entrySet()) {
174
            for (final MessageDescriptor message : entry.getValue().getWarnings()) {
175
                addMessageDescriptorToMessageContext(messageContext, message);
176
                foundAndAddedWarnings = true;
177
            }
178
        }
179
        return foundAndAddedWarnings;
180
181
    }
182
183
184
    /**
185
     * Gets credential from context.
186
     *
187
     * @param context the context
188
     * @return the credential from context
189
     */
190
    protected Credential getCredentialFromContext(final RequestContext context) {
191
        return WebUtils.getCredential(context);
192
    }
193
194
    /**
195
     * Grant ticket granting ticket.
196
     *
197
     * @param context                     the context
198
     * @param authenticationResultBuilder the authentication result builder
199
     * @param service                     the service
200
     * @return the event
201
     */
202
    protected Event grantTicketGrantingTicketToAuthenticationResult(final RequestContext context,
203
                                                                    final AuthenticationResultBuilder authenticationResultBuilder,
204
                                                                    final Service service) {
205
206
        LOGGER.debug("Finalizing authentication transactions and issuing ticket-granting ticket");
207
        final AuthenticationResult authenticationResult =
208
                this.authenticationSystemSupport.finalizeAllAuthenticationTransactions(authenticationResultBuilder, service);
209
        final Authentication authentication = authenticationResult.getAuthentication();
210
        final String ticketGrantingTicket = WebUtils.getTicketGrantingTicketId(context);
211
        final TicketGrantingTicket tgt = createOrUpdateTicketGrantingTicket(authenticationResult, authentication, ticketGrantingTicket);
212
213
        WebUtils.putTicketGrantingTicketInScopes(context, tgt);
214
        WebUtils.putAuthenticationResult(authenticationResult, context);
215
        WebUtils.putAuthentication(tgt.getAuthentication(), context);
216
217
        if (addWarningMessagesToMessageContextIfNeeded(tgt, context.getMessageContext())) {
218
            return newEvent(CasWebflowConstants.TRANSITION_ID_SUCCESS_WITH_WARNINGS);
219
        }
220
221
        return newEvent(CasWebflowConstants.TRANSITION_ID_SUCCESS);
222
    }
223
224
    private TicketGrantingTicket createOrUpdateTicketGrantingTicket(final AuthenticationResult authenticationResult,
225
                                                                    final Authentication authentication, final String ticketGrantingTicket) {
226
        final TicketGrantingTicket tgt;
227
        if (shouldIssueTicketGrantingTicket(authentication, ticketGrantingTicket)) {
228
            tgt = this.centralAuthenticationService.createTicketGrantingTicket(authenticationResult);
229
        } else {
230
            tgt = this.centralAuthenticationService.getTicket(ticketGrantingTicket, TicketGrantingTicket.class);
231
            tgt.getAuthentication().update(authentication);
232
            this.centralAuthenticationService.updateTicket(tgt);
233
        }
234
        return tgt;
235
    }
236
237
    private boolean shouldIssueTicketGrantingTicket(final Authentication authentication, final String ticketGrantingTicket) {
238
        boolean issueTicketGrantingTicket = true;
239
        if (StringUtils.isNotBlank(ticketGrantingTicket)) {
240
            LOGGER.debug("Located ticket-granting ticket in the context. Retrieving associated authentication");
241
            final Authentication authenticationFromTgt = this.ticketRegistrySupport.getAuthenticationFrom(ticketGrantingTicket);
242
            if (authenticationFromTgt == null) {
243
                LOGGER.debug("Authentication session associated with [{}] is no longer valid", ticketGrantingTicket);
244
                this.centralAuthenticationService.destroyTicketGrantingTicket(ticketGrantingTicket);
245
            } else if (authentication.getPrincipal().equals(authenticationFromTgt.getPrincipal())) {
246
                LOGGER.debug("Resulting authentication matches the authentication from context");
247
                issueTicketGrantingTicket = false;
248
            } else {
249
                LOGGER.debug("Resulting authentication is different from the context");
250
            }
251
        }
252
        return issueTicketGrantingTicket;
253
    }
254
255
    /**
256
     * Gets authentication provider for service.
257
     *
258
     * @param service the service
259
     * @return the authentication provider for service
260
     */
261
    protected Collection<MultifactorAuthenticationProvider> getAuthenticationProviderForService(final RegisteredService service) {
262
        final RegisteredServiceMultifactorPolicy policy = service.getMultifactorPolicy();
263
        if (policy != null) {
264
            return policy.getMultifactorAuthenticationProviders().stream()
265
                    .map(this::getMultifactorAuthenticationProviderFromApplicationContext)
266
                    .filter(Optional::isPresent).map(Optional::get)
267
                    .collect(Collectors.toSet());
268
        }
269
        return null;
270
    }
271
272
    /**
273
     * Validate event for transition.
274
     *
275
     * @param eventId    the event id
276
     * @param context    the context
277
     * @param attributes the attributes
278
     * @return the event
279
     */
280
    protected Event validateEventIdForMatchingTransitionInContext(final String eventId, final RequestContext context, final Map<String, Object> attributes) {
281
        try {
282
            final AttributeMap<Object> attributesMap = new LocalAttributeMap<>(attributes);
283
            final Event event = new Event(this, eventId, attributesMap);
284
285
            LOGGER.debug("Resulting event id is [{}]. Locating transitions in the context for that event id...", event.getId());
286
287
            final TransitionDefinition def = context.getMatchingTransition(event.getId());
288
            if (def == null) {
289
                LOGGER.warn("Transition definition cannot be found for event [{}]", event.getId());
290
                throw new AuthenticationException();
291
            }
292
            LOGGER.debug("Found matching transition [{}] with target [{}] for event [{}] with attributes [{}].",
293
                    def.getId(), def.getTargetStateId(), event.getId(), event.getAttributes());
294
            return event;
295
        } catch (final Exception e) {
296
            throw new RuntimeException(e.getMessage(), e);
297
        }
298
    }
299
300
    /**
301
     * Build event attribute map map.
302
     *
303
     * @param principal the principal
304
     * @param service   the service
305
     * @param provider  the provider
306
     * @return the map
307
     */
308
    protected static Map<String, Object> buildEventAttributeMap(final Principal principal, final RegisteredService service,
309
                                                                final MultifactorAuthenticationProvider provider) {
310
        final Map<String, Object> map = new HashMap<>();
311
        map.put(Principal.class.getName(), principal);
312
        if (service != null) {
313
            map.put(RegisteredService.class.getName(), service);
314
        }
315
        map.put(MultifactorAuthenticationProvider.class.getName(), provider);
316
        return map;
317
    }
318
319
    private Set<Event> resolveEventViaMultivaluedAttribute(final Principal principal,
320
                                                           final Object attributeValue,
321
                                                           final RegisteredService service,
322
                                                           final RequestContext context,
323
                                                           final MultifactorAuthenticationProvider provider,
324
                                                           final Predicate<String> predicate) {
325
        final Set<Event> events = new HashSet<>();
326
        if (attributeValue instanceof Collection) {
327
            LOGGER.debug("Attribute value [{}] is a multi-valued attribute", attributeValue);
328
            final Collection<String> values = (Collection<String>) attributeValue;
329
            values.forEach(value -> {
330
                try {
331
                    if (predicate.test(value)) {
332
                        LOGGER.debug("Attribute value predicate [{}] has successfully matched the [{}]", predicate, value);
333
334
                        LOGGER.debug("Attempting to verify multifactor authentication provider [{}] for [{}]",
335
                                provider, service);
336
                        if (provider.isAvailable(service)) {
337
                            LOGGER.debug("Provider [{}] is successfully verified", provider);
338
339
                            final String id = provider.getId();
340
                            final Event event = validateEventIdForMatchingTransitionInContext(id, context,
341
                                    buildEventAttributeMap(principal, service, provider));
342
                            events.add(event);
343
                        }
344
                    } else {
345
                        LOGGER.debug("Attribute value predicate [{}] could not match the [{}]", predicate, value);
346
                    }
347
                } catch (final Exception e) {
348
                    LOGGER.debug("Ignoring [{}] since no matching transition could be found", value);
349
                }
350
            });
351
            return events;
352
        }
353
        LOGGER.debug("Attribute value [{}] of type [{}] is not a multi-valued attribute",
354
                attributeValue, attributeValue.getClass());
355
        return null;
356
    }
357
358
    private Set<Event> resolveEventViaSingleAttribute(final Principal principal,
359
                                                      final Object attributeValue,
360
                                                      final RegisteredService service,
361
                                                      final RequestContext context,
362
                                                      final MultifactorAuthenticationProvider provider,
363
                                                      final Predicate<String> predicate) {
364
        try {
365
            if (attributeValue instanceof String) {
366
                LOGGER.debug("Attribute value [{}] is a single-valued attribute", attributeValue);
367
                if (predicate.test((String) attributeValue)) {
368
                    LOGGER.debug("Attribute value predicate [{}] has matched the [{}]", predicate, attributeValue);
369
                    return evaluateEventForProviderInContext(principal, service, context, provider);
370
                }
371
                LOGGER.debug("Attribute value predicate [{}] could not match the [{}]", predicate, attributeValue);
372
            }
373
        } catch (final Exception e) {
374
            throw new RuntimeException(e.getMessage(), e);
375
        }
376
        LOGGER.debug("Attribute value [{}] is not a single-valued attribute", attributeValue);
377
        return null;
378
    }
379
380
    /**
381
     * Verify provider for current context and validate event id.
382
     *
383
     * @param principal the principal
384
     * @param service   the service
385
     * @param context   the context
386
     * @param provider  the provider
387
     * @return the set
388
     */
389
    protected Set<Event> evaluateEventForProviderInContext(final Principal principal,
390
                                                           final RegisteredService service,
391
                                                           final RequestContext context,
392
                                                           final MultifactorAuthenticationProvider provider) {
393
        LOGGER.debug("Attempting check for availability of multifactor authentication provider [{}] for [{}]", provider, service);
394
        if (provider != null && provider.isAvailable(service)) {
395
            LOGGER.debug("Provider [{}] is successfully verified", provider);
396
            final String id = provider.getId();
397
            final Event event = validateEventIdForMatchingTransitionInContext(id, context, buildEventAttributeMap(principal, service, provider));
398
            return CollectionUtils.wrapSet(event);
399
        }
400
        LOGGER.debug("Provider [{}] could not be verified", provider);
401
        return new HashSet<>(0);
402
    }
403
404
    private Set<Event> resolveEventViaAttribute(final Principal principal,
405
                                                final Map<String, Object> attributesToExamine,
406
                                                final Collection<String> attributeNames,
407
                                                final RegisteredService service,
408
                                                final RequestContext context,
409
                                                final Collection<MultifactorAuthenticationProvider> providers,
410
                                                final Predicate<String> predicate) {
411
        if (providers == null || providers.isEmpty()) {
412
            LOGGER.debug("No authentication provider is associated with this service");
413
            return null;
414
        }
415
416
        LOGGER.debug("Locating attribute value for attribute(s): [{}]", attributeNames);
417
        for (final String attributeName : attributeNames) {
418
            final Object attributeValue = attributesToExamine.get(attributeName);
419
            if (attributeValue == null) {
420
                LOGGER.debug("Attribute value for [{}] to determine event is not configured for [{}]", attributeName, principal.getId());
421
                continue;
422
            }
423
424
            LOGGER.debug("Selecting a multifactor authentication provider out of [{}] for [{}] and service [{}]", providers, principal.getId(), service);
425
            final MultifactorAuthenticationProvider provider =
426
                    this.multifactorAuthenticationProviderSelector.resolve(providers, service, principal);
427
428
            LOGGER.debug("Located attribute value [{}] for [{}]", attributeValue, attributeNames);
429
430
            Set<Event> results = resolveEventViaSingleAttribute(principal, attributeValue, service, context, provider, predicate);
431
            if (results == null || results.isEmpty()) {
432
                results = resolveEventViaMultivaluedAttribute(principal, attributeValue, service, context, provider, predicate);
433
            }
434
            if (results != null && !results.isEmpty()) {
435
                LOGGER.debug("Resolved set of events based on the attribute [{}] are [{}]", attributeName, results);
436
                return results;
437
            }
438
        }
439
        LOGGER.debug("No set of events based on the attribute(s) [{}] could be matched", attributeNames);
440
        return null;
441
    }
442
443
    /**
444
     * Resolve event via authentication attribute set.
445
     *
446
     * @param authentication the authentication
447
     * @param attributeNames the attribute name
448
     * @param service        the service
449
     * @param context        the context
450
     * @param providers      the providers
451
     * @param predicate      the predicate
452
     * @return the set of resolved events
453
     */
454
    protected Set<Event> resolveEventViaAuthenticationAttribute(final Authentication authentication,
455
                                                                final Collection<String> attributeNames,
456
                                                                final RegisteredService service,
457
                                                                final RequestContext context,
458
                                                                final Collection<MultifactorAuthenticationProvider> providers,
459
                                                                final Predicate<String> predicate) {
460
        return resolveEventViaAttribute(authentication.getPrincipal(), authentication.getAttributes(),
461
                attributeNames, service, context, providers, predicate);
462
    }
463
464
    /**
465
     * Resolve event via principal attribute set.
466
     *
467
     * @param principal      the principal
468
     * @param attributeNames the attribute name
469
     * @param service        the service
470
     * @param context        the context
471
     * @param providers      the providers
472
     * @param predicate      the predicate
473
     * @return the set of resolved events
474
     */
475
    protected Set<Event> resolveEventViaPrincipalAttribute(final Principal principal,
476
                                                           final Collection<String> attributeNames,
477
                                                           final RegisteredService service,
478
                                                           final RequestContext context,
479
                                                           final Collection<MultifactorAuthenticationProvider> providers,
480
                                                           final Predicate<String> predicate) {
481
482
        if (attributeNames.isEmpty()) {
483
            LOGGER.debug("No attribute names are provided to trigger a multifactor authentication provider via [{}]", getName());
484
            return null; 
485
        }
486
        
487
        if (providers == null || providers.isEmpty()) {
488
            LOGGER.error("No multifactor authentication providers are available in the application context");
489
            return null;
490
        }
491
        
492
        return resolveEventViaAttribute(principal, principal.getAttributes(), attributeNames, service, context, providers, predicate);
493
    }
494
495
    @Override
496
    public Set<Event> resolve(final RequestContext context) {
497
        WebUtils.putWarnCookieIfRequestParameterPresent(this.warnCookieGenerator, context);
498
        WebUtils.putPublicWorkstationToFlowIfRequestParameterPresent(context);
499
        return resolveInternal(context);
500
    }
501
502
    @Override
503
    public Event resolveSingle(final RequestContext context) {
504
        final Set<Event> events = resolve(context);
505
        if (events == null || events.isEmpty()) {
506
            return null;
507
        }
508
        final Event event = events.iterator().next();
509
        LOGGER.debug("Resolved single event [{}] via [{}] for this context", event.getId(), event.getSource().getClass().getName());
510
        return event;
511
    }
512
513
    /**
514
     * Find the MultifactorAuthenticationProvider in the application contact that matches the specified providerId (e.g. "mfa-duo").
515
     *
516
     * @param providerId the provider id
517
     * @return the registered service multifactor authentication provider
518
     */
519
    protected Optional<MultifactorAuthenticationProvider> getMultifactorAuthenticationProviderFromApplicationContext(final String providerId) {
520
        
521
        try {
522
            LOGGER.debug("Locating bean definition for [{}]", providerId);
523
            return MultifactorAuthenticationUtils.getAvailableMultifactorAuthenticationProviders(applicationContext).values().stream()
524
                    .filter(p -> p.matches(providerId))
525
                    .findFirst();
526
        } catch (final Exception e) {
527
            LOGGER.debug("Could not locate [{}] bean id in the application context as an authentication provider.", providerId);
528
        }
529
        return Optional.empty();
530
    }
531
532
    /**
533
     * Put resolved events as attribute.
534
     *
535
     * @param context        the context
536
     * @param resolvedEvents the resolved events
537
     */
538
    protected void putResolvedEventsAsAttribute(final RequestContext context, final Set<Event> resolvedEvents) {
539
        context.getAttributes().put(RESOLVED_AUTHENTICATION_EVENTS, resolvedEvents);
540
    }
541
542
    /**
543
     * Resolve service from authentication request.
544
     *
545
     * @param service the service
546
     * @return the service
547
     */
548
    protected Service resolveServiceFromAuthenticationRequest(final Service service) {
549
        return this.authenticationRequestServiceSelectionStrategies.resolveService(service);
550
    }
551
552
    /**
553
     * Resolve service from authentication request service.
554
     *
555
     * @param context the context
556
     * @return the service
557
     */
558
    protected Service resolveServiceFromAuthenticationRequest(final RequestContext context) {
559
        final Service ctxService = WebUtils.getService(context);
560
        return resolveServiceFromAuthenticationRequest(ctxService);
561
    }
562
563
    /**
564
     * Gets resolved events as attribute.
565
     *
566
     * @param context the context
567
     * @return the resolved events as attribute
568
     */
569
    protected Set<Event> getResolvedEventsAsAttribute(final RequestContext context) {
570
        return context.getAttributes().get(RESOLVED_AUTHENTICATION_EVENTS, Set.class);
571
    }
572
573
    /**
574
     * Handle authentication transaction and grant ticket granting ticket.
575
     *
576
     * @param context the context
577
     * @return the set
578
     */
579
    protected Set<Event> handleAuthenticationTransactionAndGrantTicketGrantingTicket(final RequestContext context) {
580
        try {
581
            final Credential credential = getCredentialFromContext(context);
582
            AuthenticationResultBuilder builder = WebUtils.getAuthenticationResultBuilder(context);
583
584
            LOGGER.debug("Handling authentication transaction for credential [{}]", credential);
585
            final Service service = WebUtils.getService(context);
586
            builder = this.authenticationSystemSupport.handleAuthenticationTransaction(service, builder, credential);
587
588
            LOGGER.debug("Issuing ticket-granting tickets for service [{}]", service);
589
            return CollectionUtils.wrapSet(grantTicketGrantingTicketToAuthenticationResult(context, builder, service));
590
        } catch (final Exception e) {
591
            LOGGER.error(e.getMessage(), e);
592
            final MessageContext messageContext = context.getMessageContext();
593
            messageContext.addMessage(new MessageBuilder().error()
594
                    .code(DEFAULT_MESSAGE_BUNDLE_PREFIX.concat(e.getClass().getSimpleName())).build());
595
            return CollectionUtils.wrapSet(new EventFactorySupport().error(this));
596
        }
597
    }
598
}
599