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