001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.login.util;
016    
017    import com.liferay.portal.kernel.cluster.ClusterExecutorUtil;
018    import com.liferay.portal.kernel.cluster.ClusterNode;
019    import com.liferay.portal.kernel.exception.PortalException;
020    import com.liferay.portal.kernel.exception.SystemException;
021    import com.liferay.portal.kernel.json.JSONFactoryUtil;
022    import com.liferay.portal.kernel.json.JSONObject;
023    import com.liferay.portal.kernel.log.Log;
024    import com.liferay.portal.kernel.log.LogFactoryUtil;
025    import com.liferay.portal.kernel.messaging.DestinationNames;
026    import com.liferay.portal.kernel.messaging.MessageBusUtil;
027    import com.liferay.portal.kernel.servlet.SessionMessages;
028    import com.liferay.portal.kernel.util.CookieKeys;
029    import com.liferay.portal.kernel.util.GetterUtil;
030    import com.liferay.portal.kernel.util.Http;
031    import com.liferay.portal.kernel.util.MapUtil;
032    import com.liferay.portal.kernel.util.ParamUtil;
033    import com.liferay.portal.kernel.util.StringPool;
034    import com.liferay.portal.kernel.util.Validator;
035    import com.liferay.portal.liveusers.LiveUsers;
036    import com.liferay.portal.model.Company;
037    import com.liferay.portal.model.CompanyConstants;
038    import com.liferay.portal.model.User;
039    import com.liferay.portal.model.UserTracker;
040    import com.liferay.portal.security.auth.AuthException;
041    import com.liferay.portal.security.auth.AuthenticatedUserUUIDStoreUtil;
042    import com.liferay.portal.security.auth.Authenticator;
043    import com.liferay.portal.service.CompanyLocalServiceUtil;
044    import com.liferay.portal.service.ServiceContext;
045    import com.liferay.portal.service.ServiceContextFactory;
046    import com.liferay.portal.service.UserLocalServiceUtil;
047    import com.liferay.portal.theme.ThemeDisplay;
048    import com.liferay.portal.util.PortalUtil;
049    import com.liferay.portal.util.PortletKeys;
050    import com.liferay.portal.util.PropsValues;
051    import com.liferay.portal.util.WebKeys;
052    import com.liferay.portlet.PortletURLFactoryUtil;
053    import com.liferay.util.Encryptor;
054    
055    import java.util.ArrayList;
056    import java.util.Enumeration;
057    import java.util.HashMap;
058    import java.util.List;
059    import java.util.Map;
060    
061    import javax.portlet.ActionRequest;
062    import javax.portlet.PortletMode;
063    import javax.portlet.PortletModeException;
064    import javax.portlet.PortletPreferences;
065    import javax.portlet.PortletRequest;
066    import javax.portlet.PortletURL;
067    import javax.portlet.WindowState;
068    import javax.portlet.WindowStateException;
069    
070    import javax.servlet.http.Cookie;
071    import javax.servlet.http.HttpServletRequest;
072    import javax.servlet.http.HttpServletResponse;
073    import javax.servlet.http.HttpSession;
074    
075    /**
076     * @author Brian Wing Shun Chan
077     * @author Scott Lee
078     */
079    public class LoginUtil {
080    
081            public static long getAuthenticatedUserId(
082                            HttpServletRequest request, String login, String password,
083                            String authType)
084                    throws PortalException, SystemException {
085    
086                    long userId = GetterUtil.getLong(login);
087    
088                    Company company = PortalUtil.getCompany(request);
089    
090                    String requestURI = request.getRequestURI();
091    
092                    String contextPath = PortalUtil.getPathContext();
093    
094                    if (requestURI.startsWith(contextPath.concat("/api/liferay"))) {
095                            throw new AuthException();
096                    }
097                    else {
098                            Map<String, String[]> headerMap = new HashMap<String, String[]>();
099    
100                            Enumeration<String> enu1 = request.getHeaderNames();
101    
102                            while (enu1.hasMoreElements()) {
103                                    String name = enu1.nextElement();
104    
105                                    Enumeration<String> enu2 = request.getHeaders(name);
106    
107                                    List<String> headers = new ArrayList<String>();
108    
109                                    while (enu2.hasMoreElements()) {
110                                            String value = enu2.nextElement();
111    
112                                            headers.add(value);
113                                    }
114    
115                                    headerMap.put(
116                                            name, headers.toArray(new String[headers.size()]));
117                            }
118    
119                            Map<String, String[]> parameterMap = request.getParameterMap();
120                            Map<String, Object> resultsMap = new HashMap<String, Object>();
121    
122                            if (Validator.isNull(authType)) {
123                                    authType = company.getAuthType();
124                            }
125    
126                            int authResult = Authenticator.FAILURE;
127    
128                            if (authType.equals(CompanyConstants.AUTH_TYPE_EA)) {
129                                    authResult = UserLocalServiceUtil.authenticateByEmailAddress(
130                                            company.getCompanyId(), login, password, headerMap,
131                                            parameterMap, resultsMap);
132    
133                                    userId = MapUtil.getLong(resultsMap, "userId", userId);
134                            }
135                            else if (authType.equals(CompanyConstants.AUTH_TYPE_SN)) {
136                                    authResult = UserLocalServiceUtil.authenticateByScreenName(
137                                            company.getCompanyId(), login, password, headerMap,
138                                            parameterMap, resultsMap);
139    
140                                    userId = MapUtil.getLong(resultsMap, "userId", userId);
141                            }
142                            else if (authType.equals(CompanyConstants.AUTH_TYPE_ID)) {
143                                    authResult = UserLocalServiceUtil.authenticateByUserId(
144                                            company.getCompanyId(), userId, password, headerMap,
145                                            parameterMap, resultsMap);
146                            }
147    
148                            if (authResult != Authenticator.SUCCESS) {
149                                    throw new AuthException();
150                            }
151                    }
152    
153                    return userId;
154            }
155    
156            public static String getEmailFromAddress(
157                            PortletPreferences preferences, long companyId)
158                    throws SystemException {
159    
160                    return PortalUtil.getEmailFromAddress(
161                            preferences, companyId, PropsValues.LOGIN_EMAIL_FROM_ADDRESS);
162            }
163    
164            public static String getEmailFromName(
165                            PortletPreferences preferences, long companyId)
166                    throws SystemException {
167    
168                    return PortalUtil.getEmailFromName(
169                            preferences, companyId, PropsValues.LOGIN_EMAIL_FROM_NAME);
170            }
171    
172            public static String getLogin(
173                            HttpServletRequest request, String paramName, Company company)
174                    throws SystemException {
175    
176                    String login = request.getParameter(paramName);
177    
178                    if ((login == null) || login.equals(StringPool.NULL)) {
179                            login = GetterUtil.getString(
180                                    CookieKeys.getCookie(request, CookieKeys.LOGIN, false));
181    
182                            if (PropsValues.COMPANY_LOGIN_PREPOPULATE_DOMAIN &&
183                                    Validator.isNull(login) &&
184                                    company.getAuthType().equals(CompanyConstants.AUTH_TYPE_EA)) {
185    
186                                    login = "@" + company.getMx();
187                            }
188                    }
189    
190                    return login;
191            }
192    
193            public static PortletURL getLoginURL(HttpServletRequest request, long plid)
194                    throws PortletModeException, WindowStateException {
195    
196                    PortletURL portletURL = PortletURLFactoryUtil.create(
197                            request, PortletKeys.LOGIN, plid, PortletRequest.RENDER_PHASE);
198    
199                    portletURL.setParameter("saveLastPath", Boolean.FALSE.toString());
200                    portletURL.setParameter("struts_action", "/login/login");
201                    portletURL.setPortletMode(PortletMode.VIEW);
202                    portletURL.setWindowState(WindowState.MAXIMIZED);
203    
204                    return portletURL;
205            }
206    
207            public static void login(
208                            HttpServletRequest request, HttpServletResponse response,
209                            String login, String password, boolean rememberMe, String authType)
210                    throws Exception {
211    
212                    CookieKeys.validateSupportCookie(request);
213    
214                    HttpSession session = request.getSession();
215    
216                    Company company = PortalUtil.getCompany(request);
217    
218                    long userId = getAuthenticatedUserId(
219                            request, login, password, authType);
220    
221                    if (!PropsValues.AUTH_SIMULTANEOUS_LOGINS) {
222                            Map<String, UserTracker> sessionUsers = LiveUsers.getSessionUsers(
223                                    company.getCompanyId());
224    
225                            List<UserTracker> userTrackers = new ArrayList<UserTracker>(
226                                    sessionUsers.values());
227    
228                            for (UserTracker userTracker : userTrackers) {
229                                    if (userId != userTracker.getUserId()) {
230                                            continue;
231                                    }
232    
233                                    JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
234    
235                                    ClusterNode clusterNode =
236                                            ClusterExecutorUtil.getLocalClusterNode();
237    
238                                    if (clusterNode != null) {
239                                            jsonObject.put(
240                                                    "clusterNodeId", clusterNode.getClusterNodeId());
241                                    }
242    
243                                    jsonObject.put("command", "signOut");
244    
245                                    long companyId = CompanyLocalServiceUtil.getCompanyIdByUserId(
246                                            userId);
247    
248                                    jsonObject.put("companyId", companyId);
249                                    jsonObject.put("sessionId", userTracker.getSessionId());
250                                    jsonObject.put("userId", userId);
251    
252                                    MessageBusUtil.sendMessage(
253                                            DestinationNames.LIVE_USERS, jsonObject.toString());
254                            }
255                    }
256    
257                    if (PropsValues.SESSION_ENABLE_PHISHING_PROTECTION) {
258                            session = renewSession(request, session);
259                    }
260    
261                    // Set cookies
262    
263                    String domain = CookieKeys.getDomain(request);
264    
265                    User user = UserLocalServiceUtil.getUserById(userId);
266    
267                    String userIdString = String.valueOf(userId);
268    
269                    session.setAttribute("j_username", userIdString);
270                    session.setAttribute("j_password", user.getPassword());
271                    session.setAttribute("j_remoteuser", userIdString);
272    
273                    if (PropsValues.SESSION_STORE_PASSWORD) {
274                            session.setAttribute(WebKeys.USER_PASSWORD, password);
275                    }
276    
277                    Cookie companyIdCookie = new Cookie(
278                            CookieKeys.COMPANY_ID, String.valueOf(company.getCompanyId()));
279    
280                    if (Validator.isNotNull(domain)) {
281                            companyIdCookie.setDomain(domain);
282                    }
283    
284                    companyIdCookie.setPath(StringPool.SLASH);
285    
286                    Cookie idCookie = new Cookie(
287                            CookieKeys.ID,
288                            Encryptor.encrypt(company.getKeyObj(), userIdString));
289    
290                    if (Validator.isNotNull(domain)) {
291                            idCookie.setDomain(domain);
292                    }
293    
294                    idCookie.setPath(StringPool.SLASH);
295    
296                    Cookie passwordCookie = new Cookie(
297                            CookieKeys.PASSWORD,
298                            Encryptor.encrypt(company.getKeyObj(), password));
299    
300                    if (Validator.isNotNull(domain)) {
301                            passwordCookie.setDomain(domain);
302                    }
303    
304                    passwordCookie.setPath(StringPool.SLASH);
305    
306                    Cookie rememberMeCookie = new Cookie(
307                            CookieKeys.REMEMBER_ME, Boolean.TRUE.toString());
308    
309                    if (Validator.isNotNull(domain)) {
310                            rememberMeCookie.setDomain(domain);
311                    }
312    
313                    rememberMeCookie.setPath(StringPool.SLASH);
314    
315                    int loginMaxAge = PropsValues.COMPANY_SECURITY_AUTO_LOGIN_MAX_AGE;
316    
317                    String userUUID = userIdString.concat(StringPool.PERIOD).concat(
318                            String.valueOf(System.nanoTime()));
319    
320                    Cookie userUUIDCookie = new Cookie(
321                            CookieKeys.USER_UUID,
322                            Encryptor.encrypt(company.getKeyObj(), userUUID));
323    
324                    userUUIDCookie.setPath(StringPool.SLASH);
325    
326                    session.setAttribute(WebKeys.USER_UUID, userUUID);
327    
328                    if (PropsValues.SESSION_DISABLED) {
329                            rememberMe = true;
330                    }
331    
332                    if (rememberMe) {
333                            companyIdCookie.setMaxAge(loginMaxAge);
334                            idCookie.setMaxAge(loginMaxAge);
335                            passwordCookie.setMaxAge(loginMaxAge);
336                            rememberMeCookie.setMaxAge(loginMaxAge);
337                            userUUIDCookie.setMaxAge(loginMaxAge);
338                    }
339                    else {
340    
341                            // This was explicitly changed from 0 to -1 so that the cookie lasts
342                            // as long as the browser. This allows an external servlet wrapped
343                            // in AutoLoginFilter to work throughout the client connection. The
344                            // cookies ARE removed on an actual logout, so there is no security
345                            // issue. See LEP-4678 and LEP-5177.
346    
347                            companyIdCookie.setMaxAge(-1);
348                            idCookie.setMaxAge(-1);
349                            passwordCookie.setMaxAge(-1);
350                            rememberMeCookie.setMaxAge(0);
351                            userUUIDCookie.setMaxAge(-1);
352                    }
353    
354                    Cookie loginCookie = new Cookie(CookieKeys.LOGIN, login);
355    
356                    if (Validator.isNotNull(domain)) {
357                            loginCookie.setDomain(domain);
358                    }
359    
360                    loginCookie.setMaxAge(loginMaxAge);
361                    loginCookie.setPath(StringPool.SLASH);
362    
363                    Cookie screenNameCookie = new Cookie(
364                            CookieKeys.SCREEN_NAME,
365                            Encryptor.encrypt(company.getKeyObj(), user.getScreenName()));
366    
367                    if (Validator.isNotNull(domain)) {
368                            screenNameCookie.setDomain(domain);
369                    }
370    
371                    screenNameCookie.setMaxAge(loginMaxAge);
372                    screenNameCookie.setPath(StringPool.SLASH);
373    
374                    boolean secure = request.isSecure();
375    
376                    if (secure && !PropsValues.COMPANY_SECURITY_AUTH_REQUIRES_HTTPS &&
377                            !Http.HTTPS.equalsIgnoreCase(PropsValues.WEB_SERVER_PROTOCOL)) {
378    
379                            Boolean httpsInitial = (Boolean)session.getAttribute(
380                                    WebKeys.HTTPS_INITIAL);
381    
382                            if ((httpsInitial == null) || !httpsInitial.booleanValue()) {
383                                    secure = false;
384                            }
385                    }
386    
387                    CookieKeys.addCookie(request, response, companyIdCookie, secure);
388                    CookieKeys.addCookie(request, response, idCookie, secure);
389                    CookieKeys.addCookie(request, response, userUUIDCookie, secure);
390    
391                    if (rememberMe) {
392                            CookieKeys.addCookie(request, response, loginCookie, secure);
393                            CookieKeys.addCookie(request, response, passwordCookie, secure);
394                            CookieKeys.addCookie(request, response, rememberMeCookie, secure);
395                            CookieKeys.addCookie(request, response, screenNameCookie, secure);
396                    }
397    
398                    AuthenticatedUserUUIDStoreUtil.register(userUUID);
399            }
400    
401            public static HttpSession renewSession(
402                            HttpServletRequest request, HttpSession session)
403                    throws Exception {
404    
405                    // Invalidate the previous session to prevent phishing
406    
407                    String[] protectedAttributeNames =
408                            PropsValues.SESSION_PHISHING_PROTECTED_ATTRIBUTES;
409    
410                    Map<String, Object> protectedAttributes = new HashMap<String, Object>();
411    
412                    for (String protectedAttributeName : protectedAttributeNames) {
413                            Object protectedAttributeValue = session.getAttribute(
414                                    protectedAttributeName);
415    
416                            if (protectedAttributeValue == null) {
417                                    continue;
418                            }
419    
420                            protectedAttributes.put(
421                                    protectedAttributeName, protectedAttributeValue);
422                    }
423    
424                    try {
425                            session.invalidate();
426                    }
427                    catch (IllegalStateException ise) {
428    
429                            // This only happens in Geronimo
430    
431                            if (_log.isWarnEnabled()) {
432                                    _log.warn(ise.getMessage());
433                            }
434                    }
435    
436                    session = request.getSession(true);
437    
438                    for (String protectedAttributeName : protectedAttributeNames) {
439                            Object protectedAttributeValue = protectedAttributes.get(
440                                    protectedAttributeName);
441    
442                            if (protectedAttributeValue == null) {
443                                    continue;
444                            }
445    
446                            session.setAttribute(
447                                    protectedAttributeName, protectedAttributeValue);
448                    }
449    
450                    return session;
451            }
452    
453            public static void sendPassword(ActionRequest actionRequest)
454                    throws Exception {
455    
456                    String toAddress = ParamUtil.getString(actionRequest, "emailAddress");
457    
458                    sendPassword(actionRequest, null, null, toAddress, null, null);
459            }
460    
461            public static void sendPassword(
462                            ActionRequest actionRequest, String fromName, String fromAddress,
463                            String toAddress, String subject, String body)
464                    throws Exception {
465    
466                    HttpServletRequest request = PortalUtil.getHttpServletRequest(
467                            actionRequest);
468    
469                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
470                            WebKeys.THEME_DISPLAY);
471    
472                    Company company = themeDisplay.getCompany();
473    
474                    if (!company.isSendPassword() && !company.isSendPasswordResetLink()) {
475                            return;
476                    }
477    
478                    ServiceContext serviceContext = ServiceContextFactory.getInstance(
479                            User.class.getName(), actionRequest);
480    
481                    UserLocalServiceUtil.sendPassword(
482                            company.getCompanyId(), toAddress, fromName, fromAddress, subject,
483                            body, serviceContext);
484    
485                    SessionMessages.add(actionRequest, "requestProcessed", toAddress);
486            }
487    
488            private static Log _log = LogFactoryUtil.getLog(LoginUtil.class);
489    
490    }