001/*
002 * (C) Copyright 2006-2009 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Nuxeo - initial API and implementation
016 *
017 * $Id: ClearTrustAuthenticator.java 33212 2009-04-22 14:06:56Z madarche $
018 */
019
020package org.nuxeo.ecm.platform.ui.web.auth.cleartrust;
021
022import java.io.IOException;
023import java.util.ArrayList;
024import java.util.Enumeration;
025import java.util.List;
026import java.util.Map;
027
028import javax.servlet.http.Cookie;
029import javax.servlet.http.HttpServletRequest;
030import javax.servlet.http.HttpServletResponse;
031
032import org.apache.commons.logging.Log;
033import org.apache.commons.logging.LogFactory;
034import org.nuxeo.ecm.platform.api.login.UserIdentificationInfo;
035import org.nuxeo.ecm.platform.ui.web.auth.interfaces.NuxeoAuthenticationPlugin;
036import org.nuxeo.ecm.platform.ui.web.auth.interfaces.NuxeoAuthenticationPluginLogoutExtension;
037
038/**
039 * @author M.-A. Darche
040 */
041public class ClearTrustAuthenticator implements NuxeoAuthenticationPlugin, NuxeoAuthenticationPluginLogoutExtension {
042
043    protected static final String CLEARTRUST_HEADER_UID = "REMOTE_USER";
044
045    protected static final String CLEARTRUST_COOKIE_SESSION_A = "ACTSESSION";
046
047    protected static final String CLEARTRUST_COOKIE_SESSION = "CTSESSION";
048
049    protected String cookieDomain = "";
050
051    protected String cleartrustLoginUrl = "";
052
053    protected String cleartrustLogoutUrl = "";
054
055    private static final Log log = LogFactory.getLog(ClearTrustAuthenticator.class);
056
057    public List<String> getUnAuthenticatedURLPrefix() {
058        // There isn't any URL that should not need authentication
059        return null;
060    }
061
062    /**
063     * Redirects to the ClearTrust login page if the request doesn't contain cookies indicating that a positive
064     * authentication occurred.
065     *
066     * @return true if AuthFilter must stop execution (ie: login prompt generated a redirect), false otherwise
067     */
068    public Boolean handleLoginPrompt(HttpServletRequest request, HttpServletResponse response, String baseURL) {
069        log.debug("handleLoginPrompt ...");
070        log.debug("handleLoginPrompt requestURL = " + request.getRequestURL());
071        Cookie[] cookies = getCookies(request);
072        displayRequestInformation(request);
073        displayCookieInformation(cookies);
074        String ctSession = getCookieValue(CLEARTRUST_COOKIE_SESSION, cookies);
075        String ctSessionA = getCookieValue(CLEARTRUST_COOKIE_SESSION_A, cookies);
076        log.debug("ctSession = " + ctSession);
077        log.debug("ctSessionA = " + ctSessionA);
078
079        boolean redirectToClearTrustLoginPage = false;
080        if (ctSession == null) {
081            log.debug("No ClearTrust session: not authorizing + redirecting to ClearTrust");
082            redirectToClearTrustLoginPage = true;
083        }
084
085        if ("%20".equals(ctSessionA)) {
086            log.debug("User has logout from ClearTrust: not authorizing + redirecting to ClearTrust");
087            redirectToClearTrustLoginPage = true;
088        }
089
090        String ctUid = request.getHeader(CLEARTRUST_HEADER_UID);
091        log.debug("ctUid = [" + ctUid + "]");
092        if (ctUid == null) {
093            redirectToClearTrustLoginPage = true;
094        }
095
096        if (redirectToClearTrustLoginPage) {
097            String loginUrl = cleartrustLoginUrl;
098            try {
099                if (cleartrustLoginUrl == null || "".equals(cleartrustLoginUrl)) {
100                    // loginUrl = baseURL
101                    // + NuxeoAuthenticationFilter.DEFAULT_START_PAGE;
102                    loginUrl = baseURL + "login.jsp";
103                }
104                log.debug("Redirecting to loginUrl: " + loginUrl);
105                response.sendRedirect(loginUrl);
106                return true;
107            } catch (IOException ex) {
108                log.error("Unable to redirect to ClearTrust login URL [" + loginUrl + "]:", ex);
109                return false;
110            }
111        }
112        log.debug("ClearTrust authentication is OK, letting the user in.");
113        return false;
114    }
115
116    public UserIdentificationInfo handleRetrieveIdentity(HttpServletRequest request, HttpServletResponse httpResponse) {
117        log.debug("handleRetrieveIdentity ...");
118        Cookie[] cookies = getCookies(request);
119        displayRequestInformation(request);
120        displayCookieInformation(cookies);
121
122        String ctUid = request.getHeader(CLEARTRUST_HEADER_UID);
123        log.debug("handleRetrieveIdentity ctUid = [" + ctUid + "]");
124        String userName = ctUid;
125        UserIdentificationInfo uui = new UserIdentificationInfo(userName,
126                "No password needed for ClearTrust authentication");
127        log.debug("handleRetrieveIdentity going on with authenticated user = [" + userName + "]");
128        return uui;
129    }
130
131    public Boolean needLoginPrompt(HttpServletRequest request) {
132        // Returning true means that the handleLoginPrompt method will be called
133        return true;
134    }
135
136    /**
137     * @return true if there is a redirection
138     */
139    public Boolean handleLogout(HttpServletRequest request, HttpServletResponse response) {
140        log.debug("handleLogout ...");
141        expireCookie(CLEARTRUST_COOKIE_SESSION, request, response);
142        expireCookie(CLEARTRUST_COOKIE_SESSION_A, request, response);
143
144        if (cleartrustLogoutUrl == null || "".equals(cleartrustLogoutUrl)) {
145            return false;
146        }
147
148        try {
149            log.debug("Redirecting to logoutUrl = [" + cleartrustLogoutUrl + "] ...");
150            response.sendRedirect(cleartrustLogoutUrl);
151            log.debug("handleLogout DONE!");
152            return true;
153        } catch (IOException e) {
154            log.error("Unable to redirect to the logout URL [" + cleartrustLogoutUrl + "] :", e);
155            return false;
156        }
157    }
158
159    protected Cookie[] getCookies(HttpServletRequest request) {
160        Cookie[] cookies = request.getCookies();
161        if (cookies == null) {
162            cookies = new Cookie[0];
163        }
164        return cookies;
165    }
166
167    private String getCookieValue(String cookieName, Cookie[] cookies) {
168        String cookieValue = null;
169        for (Cookie cookie : cookies) {
170            if (cookieName.equals(cookie.getName())) {
171                cookieValue = cookie.getValue();
172            }
173        }
174        return cookieValue;
175    }
176
177    private void expireCookie(String cookieName, HttpServletRequest request, HttpServletResponse response) {
178        log.debug("expiring cookie [" + cookieName + "]  ...");
179        Cookie cookie = new Cookie(cookieName, "");
180        // A zero value causes the cookie to be deleted
181        cookie.setMaxAge(0);
182        cookie.setPath("/");
183        response.addCookie(cookie);
184    }
185
186    protected void displayCookieInformation(Cookie[] cookies) {
187        log.debug(">>>>>>>>>>>>> Here are the cookies: ");
188        for (Cookie cookie : cookies) {
189            log.debug("displayCookieInformation cookie name: [" + cookie.getName() + "] path: [" + cookie.getPath()
190                    + "] domain: " + cookie.getDomain() + " max age: " + cookie.getMaxAge() + " value: ["
191                    + cookie.getValue() + "]");
192        }
193    }
194
195    protected void displayRequestInformation(HttpServletRequest request) {
196        log.debug(">>>>>>>>>>>>> Here is the request: ");
197        for (Enumeration headerNames = request.getHeaderNames(); headerNames.hasMoreElements();) {
198            String headerName = (String) headerNames.nextElement();
199            log.debug("header " + headerName + " : [" + request.getHeader(headerName) + "]");
200        }
201        for (Enumeration attributeNames = request.getAttributeNames(); attributeNames.hasMoreElements();) {
202            String attributeName = (String) attributeNames.nextElement();
203            log.debug("attribute " + attributeName + " : [" + request.getAttribute(attributeName) + "]");
204        }
205        for (Enumeration parameterNames = request.getParameterNames(); parameterNames.hasMoreElements();) {
206            String parameterName = (String) parameterNames.nextElement();
207            log.debug("parameter " + parameterName + " : [" + request.getParameter(parameterName) + "]");
208        }
209    }
210
211    public void initPlugin(Map<String, String> parameters) {
212        log.debug("initPlugin v 1.1");
213        if (parameters.containsKey(ClearTrustParameters.COOKIE_DOMAIN)) {
214            cookieDomain = parameters.get(ClearTrustParameters.COOKIE_DOMAIN);
215            log.debug("initPlugin cookieDomain = [" + cookieDomain + "]");
216        }
217        if (parameters.containsKey(ClearTrustParameters.CLEARTRUST_LOGIN_URL)) {
218            cleartrustLoginUrl = parameters.get(ClearTrustParameters.CLEARTRUST_LOGIN_URL);
219            log.debug("initPlugin cleartrustLoginUrl = [" + cleartrustLoginUrl + "]");
220        }
221        if (parameters.containsKey(ClearTrustParameters.CLEARTRUST_LOGOUT_URL)) {
222            cleartrustLogoutUrl = parameters.get(ClearTrustParameters.CLEARTRUST_LOGOUT_URL);
223            log.debug("initPlugin cleartrustLogoutUrl = [" + cleartrustLogoutUrl + "]");
224        }
225        log.debug("initPlugin DONE");
226    }
227
228}