CasAuthenticationHandler.java
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.esigate.cas;
import java.security.Principal;
import java.util.Properties;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.util.EntityUtils;
import org.esigate.Driver;
import org.esigate.HttpErrorPage;
import org.esigate.events.Event;
import org.esigate.events.EventDefinition;
import org.esigate.events.EventManager;
import org.esigate.events.IEventListener;
import org.esigate.events.impl.FragmentEvent;
import org.esigate.extension.Extension;
import org.esigate.http.IncomingRequest;
import org.esigate.http.OutgoingRequest;
import org.esigate.util.Parameter;
import org.esigate.util.ParameterString;
import org.jasig.cas.client.authentication.AttributePrincipal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CasAuthenticationHandler implements IEventListener, Extension {
// Configuration properties names
public static final Parameter<String> CAS_LOGIN_URL = new ParameterString("casLoginUrl", "/login");
private static final Logger LOG = LoggerFactory.getLogger(CasAuthenticationHandler.class);
private Driver driver;
private String loginUrl;
private void addCasAuthentication(OutgoingRequest outgoingRequest, IncomingRequest incomingRequest) {
String location = outgoingRequest.getRequestLine().getUri();
String resultLocation = location;
AttributePrincipal principal = getCasAuthentication(incomingRequest);
if (principal != null) {
LOG.debug("User logged in CAS as: " + principal.getName());
String casProxyTicket = principal.getProxyTicketFor(resultLocation);
LOG.debug("Proxy ticket retrieved: " + principal.getName() + " for service: " + location + " : "
+ casProxyTicket);
if (casProxyTicket != null) {
if (resultLocation.indexOf("?") > 0) {
resultLocation = resultLocation + "&ticket=" + casProxyTicket;
} else {
resultLocation = resultLocation + "?ticket=" + casProxyTicket;
}
}
}
outgoingRequest.setUri(resultLocation);
}
@Override
public boolean event(EventDefinition id, Event event) {
if (EventManager.EVENT_FRAGMENT_POST.equals(id)) {
FragmentEvent e = (FragmentEvent) event;
IncomingRequest incomingRequest = e.getOriginalRequest();
CloseableHttpResponse httpResponse = e.getHttpResponse();
if (isRedirectToCasServer(httpResponse)) {
if (getCasAuthentication(incomingRequest) != null) {
LOG.debug("CAS authentication required for {}", e);
EntityUtils.consumeQuietly(e.getHttpResponse().getEntity());
e.setHttpResponse(null);
addCasAuthentication(e.getHttpRequest(), e.getOriginalRequest());
try {
LOG.debug("Sending new request {}", e);
e.setHttpResponse(this.driver.getRequestExecutor().execute(e.getHttpRequest()));
} catch (HttpErrorPage e1) {
e.setHttpResponse(e1.getHttpResponse());
}
} else {
LOG.debug("CAS authentication required but we are not authenticated for {}", e);
e.setHttpResponse(HttpErrorPage.generateHttpResponse(HttpStatus.SC_UNAUTHORIZED,
"CAS authentication required"));
}
}
}
return true;
}
private AttributePrincipal getCasAuthentication(IncomingRequest incomingRequest) {
Principal principal = incomingRequest.getUserPrincipal();
if (principal != null && principal instanceof AttributePrincipal) {
return (AttributePrincipal) principal;
}
return null;
}
/*
* (non-Javadoc)
*
* @see org.esigate.extension.Extension#init(org.esigate.Driver, java.util.Properties)
*/
@Override
public final void init(Driver d, Properties properties) {
this.driver = d;
this.driver.getEventManager().register(EventManager.EVENT_FRAGMENT_PRE, this);
this.driver.getEventManager().register(EventManager.EVENT_FRAGMENT_POST, this);
loginUrl = CAS_LOGIN_URL.getValue(properties);
}
private boolean isRedirectToCasServer(HttpResponse httpResponse) {
Header locationHeader = httpResponse.getFirstHeader("Location");
if (locationHeader != null) {
String locationHeaderValue = locationHeader.getValue();
if (locationHeaderValue != null && locationHeaderValue.contains(loginUrl)) {
return true;
}
}
return false;
}
}