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