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