package org.apereo.cas.authentication.handler.support; import org.apereo.cas.authentication.AbstractAuthenticationHandler; import org.apereo.cas.authentication.Credential; import org.apereo.cas.authentication.DefaultHandlerResult; import org.apereo.cas.authentication.HandlerResult; import org.apereo.cas.authentication.HttpBasedServiceCredential; import org.apereo.cas.authentication.principal.PrincipalFactory; import org.apereo.cas.services.ServicesManager; import org.apereo.cas.util.http.HttpClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.security.auth.login.FailedLoginException; import java.net.URL; import java.security.GeneralSecurityException; /** * Class to validate the credential presented by communicating with the web * server and checking the certificate that is returned against the hostname, * etc. * <p> * This class is concerned with ensuring that the protocol is HTTPS and that a * response is returned. The SSL handshake that occurs automatically by opening * a connection does the heavy process of authenticating. * * @author Scott Battaglia * @since 3.0.0 */ public class HttpBasedServiceCredentialsAuthenticationHandler extends AbstractAuthenticationHandler { private static final Logger LOGGER = LoggerFactory.getLogger(HttpBasedServiceCredentialsAuthenticationHandler.class); /** Instance of Apache Commons HttpClient. */ private final HttpClient httpClient; /** * Instantiates a new Abstract authentication handler. * * @param name Handler name. * @param servicesManager the services manager. * @param principalFactory the principal factory * @param order the order * @param httpClient the http client */ public HttpBasedServiceCredentialsAuthenticationHandler(final String name, final ServicesManager servicesManager, final PrincipalFactory principalFactory, final Integer order, final HttpClient httpClient) { super(name, servicesManager, principalFactory, order); this.httpClient = httpClient; } @Override public HandlerResult authenticate(final Credential credential) throws GeneralSecurityException { final HttpBasedServiceCredential httpCredential = (HttpBasedServiceCredential) credential; if (!httpCredential.getService().getProxyPolicy().isAllowedProxyCallbackUrl(httpCredential.getCallbackUrl())) { LOGGER.warn("Proxy policy for service [{}] cannot authorize the requested callback url [{}].", httpCredential.getService().getServiceId(), httpCredential.getCallbackUrl()); throw new FailedLoginException(httpCredential.getCallbackUrl() + " cannot be authorized"); } LOGGER.debug("Attempting to authenticate [{}]", httpCredential); final URL callbackUrl = httpCredential.getCallbackUrl(); if (!this.httpClient.isValidEndPoint(callbackUrl)) { throw new FailedLoginException(callbackUrl.toExternalForm() + " sent an unacceptable response status code"); } return new DefaultHandlerResult(this, httpCredential, this.principalFactory.createPrincipal(httpCredential.getId())); } /** * * @return true if the credential provided are not null and the credential * are a subclass of (or equal to) HttpBasedServiceCredential. */ @Override public boolean supports(final Credential credential) { return credential instanceof HttpBasedServiceCredential; } }