|
1
|
|
|
package org.apereo.cas.web.flow; |
|
2
|
|
|
|
|
3
|
|
|
import org.apache.commons.lang3.StringUtils; |
|
4
|
|
|
import org.apereo.cas.authentication.AuthenticationServiceSelectionPlan; |
|
5
|
|
|
import org.apereo.cas.authentication.principal.Service; |
|
6
|
|
|
import org.apereo.cas.configuration.CasConfigurationProperties; |
|
7
|
|
|
import org.apereo.cas.services.RegisteredService; |
|
8
|
|
|
import org.apereo.cas.services.RegisteredServiceAccessStrategy; |
|
9
|
|
|
import org.apereo.cas.services.ServicesManager; |
|
10
|
|
|
import org.apereo.cas.services.UnauthorizedServiceException; |
|
11
|
|
|
import org.apereo.cas.web.support.ArgumentExtractor; |
|
12
|
|
|
import org.apereo.cas.web.support.CookieRetrievingCookieGenerator; |
|
13
|
|
|
import org.apereo.cas.web.support.WebUtils; |
|
14
|
|
|
import org.slf4j.Logger; |
|
15
|
|
|
import org.slf4j.LoggerFactory; |
|
16
|
|
|
import org.springframework.webflow.action.AbstractAction; |
|
17
|
|
|
import org.springframework.webflow.execution.Event; |
|
18
|
|
|
import org.springframework.webflow.execution.RequestContext; |
|
19
|
|
|
import org.springframework.webflow.execution.repository.NoSuchFlowExecutionException; |
|
20
|
|
|
|
|
21
|
|
|
import javax.servlet.http.HttpServletRequest; |
|
22
|
|
|
import java.util.List; |
|
23
|
|
|
|
|
24
|
|
|
/** |
|
25
|
|
|
* Class to automatically set the paths for the CookieGenerators. |
|
26
|
|
|
* <p> |
|
27
|
|
|
* Note: This is technically not threadsafe, but because its overriding with a |
|
28
|
|
|
* constant value it doesn't matter. |
|
29
|
|
|
* <p> |
|
30
|
|
|
* Note: As of CAS 3.1, this is a required class that retrieves and exposes the |
|
31
|
|
|
* values in the two cookies for subclasses to use. |
|
32
|
|
|
* |
|
33
|
|
|
* @author Scott Battaglia |
|
34
|
|
|
* @since 3.1 |
|
35
|
|
|
*/ |
|
36
|
|
|
public class InitialFlowSetupAction extends AbstractAction { |
|
37
|
|
|
|
|
38
|
|
|
private static final Logger LOGGER = LoggerFactory.getLogger(InitialFlowSetupAction.class); |
|
39
|
|
|
|
|
40
|
|
|
private final CasConfigurationProperties casProperties; |
|
41
|
|
|
private final ServicesManager servicesManager; |
|
42
|
|
|
private final AuthenticationServiceSelectionPlan authenticationRequestServiceSelectionStrategies; |
|
43
|
|
|
private final CookieRetrievingCookieGenerator warnCookieGenerator; |
|
44
|
|
|
private final CookieRetrievingCookieGenerator ticketGrantingTicketCookieGenerator; |
|
45
|
|
|
private final List<ArgumentExtractor> argumentExtractors; |
|
46
|
|
|
|
|
47
|
|
|
public InitialFlowSetupAction(final List<ArgumentExtractor> argumentExtractors, |
|
48
|
|
|
final ServicesManager servicesManager, |
|
49
|
|
|
final AuthenticationServiceSelectionPlan authenticationRequestServiceSelectionPlan, |
|
50
|
|
|
final CookieRetrievingCookieGenerator ticketGrantingTicketCookieGenerator, |
|
51
|
|
|
final CookieRetrievingCookieGenerator warnCookieGenerator, |
|
52
|
|
|
final CasConfigurationProperties casProperties) { |
|
53
|
|
|
this.argumentExtractors = argumentExtractors; |
|
54
|
|
|
this.servicesManager = servicesManager; |
|
55
|
|
|
this.authenticationRequestServiceSelectionStrategies = authenticationRequestServiceSelectionPlan; |
|
56
|
|
|
this.ticketGrantingTicketCookieGenerator = ticketGrantingTicketCookieGenerator; |
|
57
|
|
|
this.warnCookieGenerator = warnCookieGenerator; |
|
58
|
|
|
this.casProperties = casProperties; |
|
59
|
|
|
} |
|
60
|
|
|
|
|
61
|
|
|
@Override |
|
62
|
|
|
protected Event doExecute(final RequestContext context) { |
|
63
|
|
|
configureCookieGenerators(context); |
|
64
|
|
|
configureWebflowContext(context); |
|
65
|
|
|
configureWebflowContextForService(context); |
|
66
|
|
|
return success(); |
|
67
|
|
|
} |
|
68
|
|
|
|
|
69
|
|
|
private void configureWebflowContextForService(final RequestContext context) { |
|
70
|
|
|
final Service service = WebUtils.getService(this.argumentExtractors, context); |
|
71
|
|
|
if (service != null) { |
|
72
|
|
|
LOGGER.debug("Placing service in context scope: [{}]", service.getId()); |
|
73
|
|
|
|
|
74
|
|
|
final Service selectedService = authenticationRequestServiceSelectionStrategies.resolveService(service); |
|
75
|
|
|
final RegisteredService registeredService = this.servicesManager.findServiceBy(selectedService); |
|
76
|
|
|
if (registeredService != null && registeredService.getAccessStrategy().isServiceAccessAllowed()) { |
|
77
|
|
|
LOGGER.debug("Placing registered service [{}] with id [{}] in context scope", |
|
78
|
|
|
registeredService.getServiceId(), |
|
79
|
|
|
registeredService.getId()); |
|
80
|
|
|
WebUtils.putRegisteredService(context, registeredService); |
|
81
|
|
|
|
|
82
|
|
|
final RegisteredServiceAccessStrategy accessStrategy = registeredService.getAccessStrategy(); |
|
83
|
|
|
if (accessStrategy.getUnauthorizedRedirectUrl() != null) { |
|
84
|
|
|
LOGGER.debug("Placing registered service's unauthorized redirect url [{}] with id [{}] in context scope", |
|
85
|
|
|
accessStrategy.getUnauthorizedRedirectUrl(), |
|
86
|
|
|
registeredService.getServiceId()); |
|
87
|
|
|
WebUtils.putUnauthorizedRedirectUrl(context, accessStrategy.getUnauthorizedRedirectUrl()); |
|
88
|
|
|
} |
|
89
|
|
|
} |
|
90
|
|
|
} else if (!casProperties.getSso().isMissingService()) { |
|
91
|
|
|
LOGGER.warn("No service authentication request is available at [{}]. CAS is configured to disable the flow.", |
|
92
|
|
|
WebUtils.getHttpServletRequestFromExternalWebflowContext(context).getRequestURL()); |
|
93
|
|
|
throw new NoSuchFlowExecutionException(context.getFlowExecutionContext().getKey(), |
|
94
|
|
|
new UnauthorizedServiceException("screen.service.required.message", "Service is required")); |
|
95
|
|
|
} |
|
96
|
|
|
WebUtils.putService(context, service); |
|
97
|
|
|
} |
|
98
|
|
|
|
|
99
|
|
|
private void configureWebflowContext(final RequestContext context) { |
|
100
|
|
|
final HttpServletRequest request = WebUtils.getHttpServletRequestFromExternalWebflowContext(context); |
|
101
|
|
|
WebUtils.putTicketGrantingTicketInScopes(context, this.ticketGrantingTicketCookieGenerator.retrieveCookieValue(request)); |
|
102
|
|
|
WebUtils.putGoogleAnalyticsTrackingIdIntoFlowScope(context, casProperties.getGoogleAnalytics().getGoogleAnalyticsTrackingId()); |
|
103
|
|
|
WebUtils.putWarningCookie(context, Boolean.valueOf(this.warnCookieGenerator.retrieveCookieValue(request))); |
|
104
|
|
|
WebUtils.putGeoLocationTrackingIntoFlowScope(context, casProperties.getEvents().isTrackGeolocation()); |
|
105
|
|
|
WebUtils.putRecaptchaSiteKeyIntoFlowScope(context, casProperties.getGoogleRecaptcha().getSiteKey()); |
|
106
|
|
|
WebUtils.putStaticAuthenticationIntoFlowScope(context, |
|
107
|
|
|
StringUtils.isNotBlank(casProperties.getAuthn().getAccept().getUsers()) |
|
108
|
|
|
|| StringUtils.isNotBlank(casProperties.getAuthn().getReject().getUsers())); |
|
109
|
|
|
WebUtils.putPasswordManagementEnabled(context, casProperties.getAuthn().getPm().isEnabled()); |
|
110
|
|
|
WebUtils.putRememberMeAuthenticationEnabled(context, casProperties.getTicket().getTgt().getRememberMe().isEnabled()); |
|
111
|
|
|
} |
|
112
|
|
|
|
|
113
|
|
|
private void configureCookieGenerators(final RequestContext context) { |
|
114
|
|
|
final String contextPath = context.getExternalContext().getContextPath(); |
|
115
|
|
|
final String cookiePath = StringUtils.isNotBlank(contextPath) ? contextPath + '/' : "/"; |
|
116
|
|
|
|
|
117
|
|
|
if (StringUtils.isBlank(this.warnCookieGenerator.getCookiePath())) { |
|
118
|
|
|
LOGGER.info("Setting path for cookies for warn cookie generator to: [{}] ", cookiePath); |
|
119
|
|
|
this.warnCookieGenerator.setCookiePath(cookiePath); |
|
120
|
|
|
} else { |
|
121
|
|
|
LOGGER.debug("Warning cookie path is set to [{}] and path [{}]", this.warnCookieGenerator.getCookieDomain(), |
|
122
|
|
|
this.warnCookieGenerator.getCookiePath()); |
|
123
|
|
|
} |
|
124
|
|
|
if (StringUtils.isBlank(this.ticketGrantingTicketCookieGenerator.getCookiePath())) { |
|
125
|
|
|
LOGGER.debug("Setting path for cookies for TGC cookie generator to: [{}] ", cookiePath); |
|
126
|
|
|
this.ticketGrantingTicketCookieGenerator.setCookiePath(cookiePath); |
|
127
|
|
|
} else { |
|
128
|
|
|
LOGGER.debug("TGC cookie path is set to [{}] and path [{}]", this.ticketGrantingTicketCookieGenerator.getCookieDomain(), |
|
129
|
|
|
this.ticketGrantingTicketCookieGenerator.getCookiePath()); |
|
130
|
|
|
} |
|
131
|
|
|
} |
|
132
|
|
|
|
|
133
|
|
|
public ServicesManager getServicesManager() { |
|
134
|
|
|
return servicesManager; |
|
135
|
|
|
} |
|
136
|
|
|
} |
|
137
|
|
|
|