001/* 002 * (C) Copyright 2006-2007 Nuxeo SAS (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: JOOoConvertPluginImpl.java 18651 2007-05-13 20:28:53Z sfermigier $ 018 */ 019 020package org.nuxeo.ecm.platform.ui.web.auth.proxy; 021 022import java.io.Serializable; 023import java.util.HashMap; 024import java.util.List; 025import java.util.Map; 026import java.util.regex.Matcher; 027import java.util.regex.Pattern; 028 029import javax.servlet.http.HttpServletRequest; 030import javax.servlet.http.HttpServletResponse; 031import javax.servlet.http.HttpSession; 032 033import org.apache.commons.logging.Log; 034import org.apache.commons.logging.LogFactory; 035import org.nuxeo.ecm.core.api.DocumentModelList; 036import org.nuxeo.ecm.directory.DirectoryException; 037import org.nuxeo.ecm.directory.Session; 038import org.nuxeo.ecm.directory.api.DirectoryService; 039import org.nuxeo.ecm.platform.api.login.UserIdentificationInfo; 040import org.nuxeo.ecm.platform.ui.web.auth.NXAuthConstants; 041import org.nuxeo.ecm.platform.ui.web.auth.NuxeoAuthenticationFilter; 042import org.nuxeo.ecm.platform.ui.web.auth.interfaces.NuxeoAuthenticationPlugin; 043import org.nuxeo.ecm.platform.usermanager.UserManager; 044import org.nuxeo.runtime.api.Framework; 045 046public class ProxyAuthenticator implements NuxeoAuthenticationPlugin { 047 048 private static final Log log = LogFactory.getLog(ProxyAuthenticator.class); 049 050 private static final String HEADER_NAME_KEY = "ssoHeaderName"; 051 052 private static final String HEADER_NOREDIRECT_KEY = "ssoNeverRedirect"; 053 054 public static final String USERNAME_REMOVE_EXPRESSION = "usernameUnwantedPartExpression"; 055 056 protected String userIdHeaderName = "remote_user"; 057 058 protected String regexp = null; 059 060 protected boolean noRedirect; 061 062 public static final String HTTP_CREDENTIAL_DIRECTORY_FIELD_PROPERTY_NAME = "org.nuxeo.ecm.platform.login.mod_sso.credentialDirectoryField"; 063 064 private Pattern usernamePartRemovalPattern; 065 066 public List<String> getUnAuthenticatedURLPrefix() { 067 return null; 068 } 069 070 public Boolean handleLoginPrompt(HttpServletRequest httpRequest, HttpServletResponse httpResponse, String baseURL) { 071 return false; 072 } 073 074 public UserIdentificationInfo handleRetrieveIdentity(HttpServletRequest httpRequest, 075 HttpServletResponse httpResponse) { 076 String userName = httpRequest.getHeader(userIdHeaderName); 077 if (userName == null) { 078 return null; 079 } 080 if (regexp != null && usernamePartRemovalPattern != null) { 081 String tmpUsername = userName; 082 Matcher matcher = usernamePartRemovalPattern.matcher(userName); 083 // Remove all instance of regexp from username string 084 userName = matcher.replaceAll(""); 085 log.debug(String.format("userName changed from '%s' to '%s'", tmpUsername, userName)); 086 } 087 088 String credentialFieldName = Framework.getRuntime().getProperty(HTTP_CREDENTIAL_DIRECTORY_FIELD_PROPERTY_NAME); 089 if (credentialFieldName != null) { 090 // use custom directory field to find the user with the ID given in 091 // the HTTP header 092 String directoryName = Framework.getService(UserManager.class).getUserDirectoryName(); 093 try (Session userDir = Framework.getService(DirectoryService.class).open(directoryName)) { 094 Map<String, Serializable> queryFilters = new HashMap<String, Serializable>(); 095 queryFilters.put(credentialFieldName, userName); 096 DocumentModelList result = userDir.query(queryFilters); 097 if (result.isEmpty()) { 098 log.error(String.format("could not find any user with %s='%s' in directory %s", 099 credentialFieldName, userName, directoryName)); 100 return null; 101 } 102 if (result.size() > 1) { 103 log.error(String.format("found more than one entry for %s='%s' in directory %s", 104 credentialFieldName, userName, directoryName)); 105 return null; 106 } 107 // use the ID of the found user entry as new identification for 108 // the principal 109 userName = result.get(0).getId(); 110 } catch (DirectoryException e) { 111 log.error(String.format("could not retrieve user entry with %s='%s': %s", credentialFieldName, 112 userName, e.getMessage()), e); 113 return null; 114 } 115 } 116 117 if (!noRedirect) { 118 handleRedirectToValidStartPage(httpRequest, httpResponse); 119 } 120 return new UserIdentificationInfo(userName, userName); 121 } 122 123 /** 124 * Handle redirection so that context is rebuilt correctly see NXP-2060 + NXP-2064 125 */ 126 protected void handleRedirectToValidStartPage(HttpServletRequest httpRequest, HttpServletResponse httpResponse) { 127 boolean isStartPageValid = false; 128 if (httpRequest.getMethod().equals("GET") || httpRequest.getMethod().equals("POST")) { 129 // try to keep valid start page 130 NuxeoAuthenticationFilter filter = new NuxeoAuthenticationFilter(); 131 isStartPageValid = filter.saveRequestedURLBeforeRedirect(httpRequest, httpResponse); 132 } 133 HttpSession session; 134 if (httpResponse.isCommitted()) { 135 session = httpRequest.getSession(false); 136 } else { 137 session = httpRequest.getSession(true); 138 } 139 if (session != null && !isStartPageValid) { 140 session.setAttribute(NXAuthConstants.START_PAGE_SAVE_KEY, NuxeoAuthenticationFilter.DEFAULT_START_PAGE 141 + "?loginRedirection=true"); 142 } 143 } 144 145 public void initPlugin(Map<String, String> parameters) { 146 if (parameters.containsKey(HEADER_NAME_KEY)) { 147 userIdHeaderName = parameters.get(HEADER_NAME_KEY); 148 } 149 if (parameters.containsKey(HEADER_NOREDIRECT_KEY)) { 150 noRedirect = Boolean.parseBoolean(parameters.get(HEADER_NOREDIRECT_KEY)); 151 } 152 if (parameters.containsKey(USERNAME_REMOVE_EXPRESSION)) { 153 regexp = parameters.get(USERNAME_REMOVE_EXPRESSION); 154 log.debug(String.format("Will remove all instances of '%s' from userName string.", regexp)); 155 usernamePartRemovalPattern = Pattern.compile(regexp); 156 } 157 } 158 159 public Boolean needLoginPrompt(HttpServletRequest httpRequest) { 160 return false; 161 } 162 163}