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.plugins; 021 022import java.io.IOException; 023import java.util.ArrayList; 024import java.util.List; 025import java.util.Map; 026import java.util.Map.Entry; 027 028import javax.servlet.http.Cookie; 029import javax.servlet.http.HttpServletRequest; 030import javax.servlet.http.HttpServletResponse; 031 032import org.apache.commons.lang.StringUtils; 033import org.nuxeo.common.utils.Base64; 034import org.nuxeo.ecm.platform.api.login.UserIdentificationInfo; 035import org.nuxeo.ecm.platform.ui.web.auth.NXAuthConstants; 036import org.nuxeo.ecm.platform.ui.web.auth.interfaces.NuxeoAuthenticationPlugin; 037 038public class BasicAuthenticator implements NuxeoAuthenticationPlugin { 039 040 protected static final String REALM_NAME_KEY = "RealmName"; 041 042 protected static final String FORCE_PROMPT_KEY = "ForcePromptURL"; 043 044 protected static final String AUTO_PROMPT_KEY = "AutoPrompt"; 045 046 protected static final String PROMPT_URL_KEY = "PromptUrl"; 047 048 protected static final String DEFAULT_REALMNAME = "Nuxeo 5"; 049 050 protected static final String BA_HEADER_NAME = "WWW-Authenticate"; 051 052 protected static final String EXCLUDE_URL_KEY = "ExcludeBAHeader"; 053 054 protected String realName; 055 056 protected Boolean autoPrompt = false; 057 058 protected List<String> forcePromptURLs; 059 060 private List<String> excludedHeadersForBasicAuth; 061 062 @Override 063 public Boolean handleLoginPrompt(HttpServletRequest httpRequest, HttpServletResponse httpResponse, String baseURL) { 064 try { 065 066 if (needToAddBAHeader(httpRequest)) { 067 String baHeader = "Basic realm=\"" + realName + '\"'; 068 httpResponse.addHeader(BA_HEADER_NAME, baHeader); 069 } 070 int statusCode; 071 Integer requestStatusCode = (Integer) httpRequest.getAttribute(NXAuthConstants.LOGIN_STATUS_CODE); 072 if (requestStatusCode != null) { 073 statusCode = requestStatusCode; 074 } else { 075 statusCode = HttpServletResponse.SC_UNAUTHORIZED; 076 } 077 httpResponse.sendError(statusCode); 078 return true; 079 } catch (IOException e) { 080 return false; 081 } 082 } 083 084 /** 085 * Checks if we need to include a basic auth header back to the client. 086 * 087 * @param httpRequest 088 * @return true if we need to include the auth header 089 * @since 5.9.2 090 */ 091 private boolean needToAddBAHeader(HttpServletRequest httpRequest) { 092 for (String header : excludedHeadersForBasicAuth) { 093 if (StringUtils.isNotBlank(httpRequest.getHeader(header))) { 094 return false; 095 } 096 if (httpRequest.getCookies() != null) { 097 for (Cookie cookie : httpRequest.getCookies()) { 098 if (cookie.getName().equals(header)) { 099 return false; 100 } 101 } 102 } 103 } 104 return true; 105 } 106 107 @Override 108 public UserIdentificationInfo handleRetrieveIdentity(HttpServletRequest httpRequest, 109 HttpServletResponse httpResponse) { 110 111 String auth = httpRequest.getHeader("authorization"); 112 113 if (auth != null && auth.toLowerCase().startsWith("basic")) { 114 int idx = auth.indexOf(' '); 115 String b64userPassword = auth.substring(idx + 1); 116 byte[] clearUp = Base64.decode(b64userPassword); 117 String userCredentials = new String(clearUp); 118 int idxOfColon = userCredentials.indexOf(':'); 119 if (idxOfColon > 0 && idxOfColon < userCredentials.length() - 1) { 120 String username = userCredentials.substring(0, idxOfColon); 121 String password = userCredentials.substring(idxOfColon + 1); 122 return new UserIdentificationInfo(username, password); 123 } else { 124 return null; 125 } 126 } 127 return null; 128 } 129 130 @Override 131 public Boolean needLoginPrompt(HttpServletRequest httpRequest) { 132 if (autoPrompt) { 133 return true; 134 } else { 135 String requestedURI = httpRequest.getRequestURI(); 136 String context = httpRequest.getContextPath() + '/'; 137 requestedURI = requestedURI.substring(context.length()); 138 for (String prefixURL : forcePromptURLs) { 139 if (requestedURI.startsWith(prefixURL)) { 140 return true; 141 } 142 } 143 return false; 144 } 145 } 146 147 @Override 148 public void initPlugin(Map<String, String> parameters) { 149 if (parameters.containsKey(REALM_NAME_KEY)) { 150 realName = parameters.get(REALM_NAME_KEY); 151 } else { 152 realName = DEFAULT_REALMNAME; 153 } 154 155 if (parameters.containsKey(AUTO_PROMPT_KEY)) { 156 autoPrompt = parameters.get(AUTO_PROMPT_KEY).equalsIgnoreCase("true"); 157 } 158 159 forcePromptURLs = new ArrayList<String>(); 160 for (Entry<String, String> entry : parameters.entrySet()) { 161 if (entry.getKey().startsWith(FORCE_PROMPT_KEY)) { 162 forcePromptURLs.add(entry.getValue()); 163 } 164 } 165 166 excludedHeadersForBasicAuth = new ArrayList<>(); 167 for (Entry<String, String> entry : parameters.entrySet()) { 168 if (entry.getKey().startsWith(EXCLUDE_URL_KEY)) { 169 excludedHeadersForBasicAuth.add(entry.getValue()); 170 } 171 } 172 } 173 174 @Override 175 public List<String> getUnAuthenticatedURLPrefix() { 176 return null; 177 } 178 179}