1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.esigate.cas;
17
18 import java.security.Principal;
19 import java.util.Properties;
20
21 import org.apache.http.Header;
22 import org.apache.http.HttpResponse;
23 import org.apache.http.HttpStatus;
24 import org.apache.http.client.methods.CloseableHttpResponse;
25 import org.apache.http.util.EntityUtils;
26 import org.esigate.Driver;
27 import org.esigate.HttpErrorPage;
28 import org.esigate.events.Event;
29 import org.esigate.events.EventDefinition;
30 import org.esigate.events.EventManager;
31 import org.esigate.events.IEventListener;
32 import org.esigate.events.impl.FragmentEvent;
33 import org.esigate.extension.Extension;
34 import org.esigate.http.IncomingRequest;
35 import org.esigate.http.OutgoingRequest;
36 import org.esigate.util.Parameter;
37 import org.esigate.util.ParameterString;
38 import org.jasig.cas.client.authentication.AttributePrincipal;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 public class CasAuthenticationHandler implements IEventListener, Extension {
43
44 public static final Parameter<String> CAS_LOGIN_URL = new ParameterString("casLoginUrl", "/login");
45 private static final Logger LOG = LoggerFactory.getLogger(CasAuthenticationHandler.class);
46 private Driver driver;
47 private String loginUrl;
48
49 private void addCasAuthentication(OutgoingRequest outgoingRequest, IncomingRequest incomingRequest) {
50 String location = outgoingRequest.getRequestLine().getUri();
51 String resultLocation = location;
52 AttributePrincipal principal = getCasAuthentication(incomingRequest);
53 if (principal != null) {
54 LOG.debug("User logged in CAS as: " + principal.getName());
55 String casProxyTicket = principal.getProxyTicketFor(resultLocation);
56 LOG.debug("Proxy ticket retrieved: " + principal.getName() + " for service: " + location + " : "
57 + casProxyTicket);
58 if (casProxyTicket != null) {
59 if (resultLocation.indexOf("?") > 0) {
60 resultLocation = resultLocation + "&ticket=" + casProxyTicket;
61 } else {
62 resultLocation = resultLocation + "?ticket=" + casProxyTicket;
63 }
64 }
65 }
66 outgoingRequest.setUri(resultLocation);
67 }
68
69 @Override
70 public boolean event(EventDefinition id, Event event) {
71 if (EventManager.EVENT_FRAGMENT_POST.equals(id)) {
72 FragmentEvent e = (FragmentEvent) event;
73 IncomingRequest incomingRequest = e.getOriginalRequest();
74 CloseableHttpResponse httpResponse = e.getHttpResponse();
75 if (isRedirectToCasServer(httpResponse)) {
76 if (getCasAuthentication(incomingRequest) != null) {
77 LOG.debug("CAS authentication required for {}", e);
78 EntityUtils.consumeQuietly(e.getHttpResponse().getEntity());
79 e.setHttpResponse(null);
80 addCasAuthentication(e.getHttpRequest(), e.getOriginalRequest());
81 try {
82 LOG.debug("Sending new request {}", e);
83 e.setHttpResponse(this.driver.getRequestExecutor().execute(e.getHttpRequest()));
84 } catch (HttpErrorPage e1) {
85 e.setHttpResponse(e1.getHttpResponse());
86 }
87 } else {
88 LOG.debug("CAS authentication required but we are not authenticated for {}", e);
89 e.setHttpResponse(HttpErrorPage.generateHttpResponse(HttpStatus.SC_UNAUTHORIZED,
90 "CAS authentication required"));
91 }
92 }
93 }
94 return true;
95 }
96
97 private AttributePrincipal getCasAuthentication(IncomingRequest incomingRequest) {
98 Principal principal = incomingRequest.getUserPrincipal();
99 if (principal != null && principal instanceof AttributePrincipal) {
100 return (AttributePrincipal) principal;
101 }
102 return null;
103 }
104
105
106
107
108
109
110 @Override
111 public final void init(Driver d, Properties properties) {
112 this.driver = d;
113 this.driver.getEventManager().register(EventManager.EVENT_FRAGMENT_PRE, this);
114 this.driver.getEventManager().register(EventManager.EVENT_FRAGMENT_POST, this);
115 loginUrl = CAS_LOGIN_URL.getValue(properties);
116 }
117
118 private boolean isRedirectToCasServer(HttpResponse httpResponse) {
119 Header locationHeader = httpResponse.getFirstHeader("Location");
120 if (locationHeader != null) {
121 String locationHeaderValue = locationHeader.getValue();
122 if (locationHeaderValue != null && locationHeaderValue.contains(loginUrl)) {
123 return true;
124 }
125 }
126 return false;
127 }
128
129 }