001/* 002 * (C) Copyright 2012 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 * bjalon 018 */ 019package org.nuxeo.ecm.mobile.filter; 020 021import java.io.IOException; 022import java.io.UnsupportedEncodingException; 023import java.util.List; 024import java.util.Map; 025 026import javax.servlet.http.HttpServletRequest; 027import javax.servlet.http.HttpServletResponse; 028 029import org.apache.commons.logging.Log; 030import org.apache.commons.logging.LogFactory; 031import org.nuxeo.common.utils.URIUtils; 032import org.nuxeo.ecm.mobile.ApplicationDefinitionService; 033import org.nuxeo.ecm.platform.api.login.UserIdentificationInfo; 034import org.nuxeo.ecm.platform.ui.web.auth.interfaces.NuxeoAuthenticationPlugin; 035import org.nuxeo.runtime.api.Framework; 036 037import static org.nuxeo.ecm.platform.ui.web.auth.NXAuthConstants.ERROR_USERNAME_MISSING; 038import static org.nuxeo.ecm.platform.ui.web.auth.NXAuthConstants.FORM_SUBMITTED_MARKER; 039import static org.nuxeo.ecm.platform.ui.web.auth.NXAuthConstants.LOGIN_ERROR; 040 041/** 042 * Authenticator that redirects user to dedicated application authentication form if user has selected this application 043 * or if this application matched the request context. Can't extends Form Authentication as login form is static and 044 * here is dynamic. 045 * 046 * @author <a href="mailto:bjalon@nuxeo.com">Benjamin JALON</a> 047 * @since 5.5 048 */ 049public class ApplicationFormAuthenticator implements NuxeoAuthenticationPlugin { 050 051 protected static final Log log = LogFactory.getLog(ApplicationFormAuthenticator.class); 052 053 private ApplicationDefinitionService service; 054 055 private String usernameKey = "user_name"; 056 057 private String passwordKey = "user_password"; 058 059 public ApplicationDefinitionService getService() { 060 if (service == null) { 061 service = Framework.getLocalService(ApplicationDefinitionService.class); 062 } 063 return service; 064 } 065 066 @Override 067 public void initPlugin(Map<String, String> parameters) { 068 if (parameters.get("UsernameKey") != null) { 069 usernameKey = parameters.get("UsernameKey"); 070 } 071 if (parameters.get("PasswordKey") != null) { 072 passwordKey = parameters.get("PasswordKey"); 073 } 074 } 075 076 @Override 077 public Boolean needLoginPrompt(HttpServletRequest httpRequest) { 078 if (getService().getApplicationBaseURL(httpRequest) != null) { 079 return true; 080 } 081 log.debug("No Application match this request, next authenticator to expose login prompt"); 082 return false; 083 } 084 085 @Override 086 public Boolean handleLoginPrompt(HttpServletRequest httpRequest, HttpServletResponse httpResponse, String baseURL) { 087 log.debug("Login Prompt - URL :" + httpRequest.getRequestURL() + "?" + httpRequest.getQueryString()); 088 089 String loginPage = getService().getLoginURL(httpRequest); 090 if (loginPage == null) { 091 log.debug("No Application matched for this request context, so next Authenticator in Chain will be used"); 092 return Boolean.FALSE; 093 } 094 095 log.debug("Application matched for this request context so login page " 096 + "used will be the target application detected: " + loginPage); 097 098 Map<String, String> parameters; 099 try { 100 RequestAdapter adapter = new RequestAdapter(httpRequest); 101 parameters = adapter.getParametersAndAddTargetURLIfNotSet(); 102 // avoid resending the password in clear !!! 103 parameters.remove(passwordKey); 104 } catch (UnsupportedEncodingException e) { 105 log.error(e, e); 106 return Boolean.FALSE; 107 } 108 String redirectUrl = URIUtils.addParametersToURIQuery(loginPage, parameters); 109 try { 110 httpResponse.sendRedirect(redirectUrl); 111 return Boolean.TRUE; 112 } catch (IOException e) { 113 log.error(e, e); 114 } 115 return Boolean.FALSE; 116 } 117 118 @Override 119 public List<String> getUnAuthenticatedURLPrefix() { 120 List<String> result = getService().getUnAuthenticatedURLPrefix(); 121 log.debug("List of skipped URL:" + result); 122 return result; 123 } 124 125 @Override 126 public UserIdentificationInfo handleRetrieveIdentity(HttpServletRequest httpRequest, 127 HttpServletResponse httpResponse) { 128 129 if (getService().getApplicationBaseURL(httpRequest) == null) { 130 log.debug("No Application match this request, use next Authenticator " + "in chain to retrieve identity"); 131 return null; 132 } 133 134 Map<String, String> parameters; 135 try { 136 RequestAdapter adapter = new RequestAdapter(httpRequest); 137 parameters = adapter.getParametersAndAddTargetURLIfNotSet(); 138 // avoid resending the password in clear !!! 139 } catch (UnsupportedEncodingException e) { 140 log.error(e, e); 141 return null; 142 } 143 144 String userName = parameters.get(usernameKey); 145 String password = parameters.get(passwordKey); 146 147 if (parameters.get(FORM_SUBMITTED_MARKER) != null && (userName == null || userName.length() == 0)) { 148 parameters.put(LOGIN_ERROR, ERROR_USERNAME_MISSING); 149 } 150 if (userName == null || userName.length() == 0) { 151 return null; 152 } 153 154 return new UserIdentificationInfo(userName, password); 155 } 156 157}