package org.apereo.cas.ws.idp.web;
import com.google.common.base.Throwables;
import org.apache.commons.lang3.StringUtils;
import org.apereo.cas.CasProtocolConstants;
import org.apereo.cas.authentication.AuthenticationServiceSelectionStrategy;
import org.apereo.cas.authentication.adaptive.UnauthorizedAuthenticationException;
import org.apereo.cas.authentication.principal.Service;
import org.apereo.cas.authentication.principal.ServiceFactory;
import org.apereo.cas.authentication.principal.WebApplicationService;
import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.services.ServicesManager;
import org.apereo.cas.ticket.SecurityTokenTicketFactory;
import org.apereo.cas.ticket.registry.TicketRegistry;
import org.apereo.cas.ticket.registry.TicketRegistrySupport;
import org.apereo.cas.util.http.HttpClient;
import org.apereo.cas.web.support.CookieRetrievingCookieGenerator;
import org.apereo.cas.ws.idp.WSFederationConstants;
import org.apereo.cas.ws.idp.services.WSFederationRegisteredService;
import org.jasig.cas.client.authentication.AuthenticationRedirectStrategy;
import org.jasig.cas.client.authentication.DefaultAuthenticationRedirectStrategy;
import org.jasig.cas.client.util.CommonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collections;
/**
* This is {@link WSFederationValidateRequestController}.
*
* @author Misagh Moayyed
* @since 5.1.0
*/
public class WSFederationValidateRequestController extends BaseWSFederationRequestController {
private static final Logger LOGGER = LoggerFactory.getLogger(WSFederationValidateRequestController.class);
public WSFederationValidateRequestController(
final ServicesManager servicesManager,
final ServiceFactory<WebApplicationService> webApplicationServiceFactory,
final CasConfigurationProperties casProperties,
final AuthenticationServiceSelectionStrategy serviceSelectionStrategy,
final HttpClient httpClient,
final SecurityTokenTicketFactory securityTokenTicketFactory,
final TicketRegistry ticketRegistry,
final CookieRetrievingCookieGenerator ticketGrantingTicketCookieGenerator,
final TicketRegistrySupport ticketRegistrySupport) {
super(servicesManager,
webApplicationServiceFactory, casProperties, serviceSelectionStrategy, httpClient,
securityTokenTicketFactory, ticketRegistry, ticketGrantingTicketCookieGenerator, ticketRegistrySupport);
}
/**
* Handle federation request.
*
* @param response the response
* @param request the request
* @throws Exception the exception
*/
@GetMapping(path = WSFederationConstants.ENDPOINT_FEDERATION_REQUEST)
protected void handleFederationRequest(final HttpServletResponse response, final HttpServletRequest request) throws Exception {
final WSFederationRequest fedRequest = WSFederationRequest.of(request);
switch (fedRequest.getWa().toLowerCase()) {
case WSFederationConstants.WSIGNOUT10:
case WSFederationConstants.WSIGNOUT_CLEANUP10:
handleLogoutRequest(fedRequest, request, response);
break;
case WSFederationConstants.WSIGNIN10:
handleInitialAuthenticationRequest(fedRequest, response, request);
break;
default:
throw new UnauthorizedAuthenticationException("The authentication request is not recognized",
Collections.emptyMap());
}
}
private void handleLogoutRequest(final WSFederationRequest fedRequest, final HttpServletRequest request,
final HttpServletResponse response) throws Exception {
String logoutUrl = casProperties.getServer().getLogoutUrl();
if (StringUtils.isNotBlank(fedRequest.getWreply())) {
final Service service = webApplicationServiceFactory.createService(fedRequest.getWreply());
final WSFederationRegisteredService registeredService = getWsFederationRegisteredService(service);
LOGGER.debug("Invoking logout operation for request [{}], redirecting next to [{}] matched against [{}]",
fedRequest, fedRequest.getWreply(), registeredService);
final String logoutParam = casProperties.getLogout().getRedirectParameter();
logoutUrl = logoutUrl.concat("?").concat(logoutParam).concat("=").concat(service.getId());
}
final AuthenticationRedirectStrategy authenticationRedirectStrategy = new DefaultAuthenticationRedirectStrategy();
authenticationRedirectStrategy.redirect(request, response, logoutUrl);
}
private void handleInitialAuthenticationRequest(final WSFederationRequest fedRequest,
final HttpServletResponse response, final HttpServletRequest request) {
final WSFederationRegisteredService service = findAndValidateFederationRequestForRegisteredService(response, request, fedRequest);
LOGGER.debug("Redirecting to identity provider for initial authentication [{}]", fedRequest);
redirectToIdentityProvider(fedRequest, response, request, service);
}
private void redirectToIdentityProvider(final WSFederationRequest fedRequest, final HttpServletResponse response,
final HttpServletRequest request, final WSFederationRegisteredService service) {
try {
final String serviceUrl = constructServiceUrl(request, response, fedRequest);
LOGGER.debug("Created service url [{}] mapped to [{}]", serviceUrl, service);
final boolean renew = shouldRenewAuthentication(fedRequest, request);
final String initialUrl = CommonUtils.constructRedirectUrl(casProperties.getServer().getLoginUrl(),
CasProtocolConstants.PARAMETER_SERVICE, serviceUrl, renew, false);
LOGGER.debug("Redirecting authN request to [{}]", initialUrl);
final AuthenticationRedirectStrategy authenticationRedirectStrategy = new DefaultAuthenticationRedirectStrategy();
authenticationRedirectStrategy.redirect(request, response, initialUrl);
} catch (final Exception e) {
throw Throwables.propagate(e);
}
}
}