1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.action;
16  
17  import com.liferay.portal.DuplicateUserEmailAddressException;
18  import com.liferay.portal.NoSuchUserException;
19  import com.liferay.portal.kernel.log.Log;
20  import com.liferay.portal.kernel.log.LogFactoryUtil;
21  import com.liferay.portal.kernel.servlet.SessionErrors;
22  import com.liferay.portal.kernel.servlet.SessionMessages;
23  import com.liferay.portal.kernel.util.GetterUtil;
24  import com.liferay.portal.kernel.util.ParamUtil;
25  import com.liferay.portal.kernel.util.StringPool;
26  import com.liferay.portal.kernel.util.Validator;
27  import com.liferay.portal.model.User;
28  import com.liferay.portal.service.UserLocalServiceUtil;
29  import com.liferay.portal.theme.ThemeDisplay;
30  import com.liferay.portal.util.OpenIdUtil;
31  import com.liferay.portal.util.PortalUtil;
32  import com.liferay.portal.util.WebKeys;
33  import com.liferay.util.PwdGenerator;
34  
35  import java.util.Calendar;
36  import java.util.List;
37  import java.util.Locale;
38  
39  import javax.portlet.PortletURL;
40  
41  import javax.servlet.http.HttpServletRequest;
42  import javax.servlet.http.HttpServletResponse;
43  import javax.servlet.http.HttpSession;
44  
45  import org.apache.struts.action.Action;
46  import org.apache.struts.action.ActionForm;
47  import org.apache.struts.action.ActionForward;
48  import org.apache.struts.action.ActionMapping;
49  
50  import org.openid4java.association.AssociationException;
51  import org.openid4java.consumer.ConsumerException;
52  import org.openid4java.consumer.ConsumerManager;
53  import org.openid4java.consumer.VerificationResult;
54  import org.openid4java.discovery.DiscoveryException;
55  import org.openid4java.discovery.DiscoveryInformation;
56  import org.openid4java.discovery.Identifier;
57  import org.openid4java.message.AuthSuccess;
58  import org.openid4java.message.MessageException;
59  import org.openid4java.message.MessageExtension;
60  import org.openid4java.message.ParameterList;
61  import org.openid4java.message.ax.AxMessage;
62  import org.openid4java.message.ax.FetchResponse;
63  import org.openid4java.message.sreg.SRegMessage;
64  import org.openid4java.message.sreg.SRegResponse;
65  
66  /**
67   * <a href="OpenIdResponseAction.java.html"><b><i>View Source</i></b></a>
68   *
69   * @author Jorge Ferrer
70   */
71  public class OpenIdResponseAction extends Action {
72  
73      public ActionForward execute(
74              ActionMapping mapping, ActionForm form, HttpServletRequest request,
75              HttpServletResponse response)
76          throws Exception {
77  
78          ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
79              WebKeys.THEME_DISPLAY);
80  
81          if (!OpenIdUtil.isEnabled(themeDisplay.getCompanyId())) {
82              return null;
83          }
84  
85          String redirect = null;
86  
87          try {
88              redirect = readResponse(themeDisplay, request);
89          }
90          catch (Exception e) {
91              if (e instanceof AssociationException ||
92                  e instanceof ConsumerException ||
93                  e instanceof DiscoveryException ||
94                  e instanceof DuplicateUserEmailAddressException ||
95                  e instanceof MessageException) {
96  
97                  SessionErrors.add(request, e.getClass().getName());
98  
99                  return mapping.findForward("portal.login");
100             }
101             else {
102                 _log.error("Error processing OpenID response", e);
103 
104                 PortalUtil.sendError(e, request, response);
105 
106                 return null;
107             }
108         }
109 
110         if (Validator.isNull(redirect)) {
111             redirect =
112                 PortalUtil.getPortalURL(request) + themeDisplay.getURLSignIn();
113         }
114 
115         response.sendRedirect(redirect);
116 
117         return null;
118     }
119 
120     protected User addUser(
121             long companyId, String firstName, String lastName,
122             String emailAddress, String openId, Locale locale)
123         throws Exception {
124 
125         long creatorUserId = 0;
126         boolean autoPassword = false;
127         String password1 = PwdGenerator.getPassword();
128         String password2 = password1;
129         boolean autoScreenName = true;
130         String screenName = StringPool.BLANK;
131         String middleName = StringPool.BLANK;
132         int prefixId = 0;
133         int suffixId = 0;
134         boolean male = true;
135         int birthdayMonth = Calendar.JANUARY;
136         int birthdayDay = 1;
137         int birthdayYear = 1970;
138         String jobTitle = StringPool.BLANK;
139         long[] organizationIds = new long[0];
140         boolean sendEmail = false;
141 
142         User user = UserLocalServiceUtil.addUser(
143             creatorUserId, companyId, autoPassword, password1, password2,
144             autoScreenName, screenName, emailAddress, locale, firstName,
145             middleName, lastName, prefixId, suffixId, male, birthdayMonth,
146             birthdayDay, birthdayYear, jobTitle, organizationIds, sendEmail);
147 
148         UserLocalServiceUtil.updateOpenId(user.getUserId(), openId);
149 
150         return user;
151     }
152 
153     protected String getFirstValue(List<String> values) {
154         if ((values == null) || (values.size() < 1)) {
155             return null;
156         }
157 
158         return values.get(0);
159     }
160 
161     protected String readResponse(
162             ThemeDisplay themeDisplay, HttpServletRequest request)
163         throws Exception {
164 
165         HttpSession session = request.getSession();
166 
167         ConsumerManager manager = OpenIdUtil.getConsumerManager();
168 
169         ParameterList params = new ParameterList(request.getParameterMap());
170 
171         DiscoveryInformation discovered =
172             (DiscoveryInformation)session.getAttribute(WebKeys.OPEN_ID_DISCO);
173 
174         if (discovered == null) {
175             return null;
176         }
177 
178         String receivingUrl = ParamUtil.getString(request, "openid.return_to");
179 
180         VerificationResult verification = manager.verify(
181             receivingUrl, params, discovered);
182 
183         Identifier verified = verification.getVerifiedId();
184 
185         if (verified == null) {
186             return null;
187         }
188 
189         AuthSuccess authSuccess = (AuthSuccess)verification.getAuthResponse();
190 
191         String firstName = null;
192         String lastName = null;
193         String emailAddress = null;
194 
195         if (authSuccess.hasExtension(SRegMessage.OPENID_NS_SREG)) {
196             MessageExtension ext = authSuccess.getExtension(
197                 SRegMessage.OPENID_NS_SREG);
198 
199             if (ext instanceof SRegResponse) {
200                 SRegResponse sregResp = (SRegResponse)ext;
201 
202                 String fullName = GetterUtil.getString(
203                     sregResp.getAttributeValue("fullname"));
204 
205                 int pos = fullName.indexOf(StringPool.SPACE);
206 
207                 if ((pos != -1) && ((pos + 1) < fullName.length())) {
208                     firstName = fullName.substring(0, pos);
209                     lastName = fullName.substring(pos + 1);
210                 }
211 
212                 emailAddress = sregResp.getAttributeValue("email");
213             }
214         }
215 
216         if (authSuccess.hasExtension(AxMessage.OPENID_NS_AX)) {
217             MessageExtension ext = authSuccess.getExtension(
218                 AxMessage.OPENID_NS_AX);
219 
220             if (ext instanceof FetchResponse) {
221                 FetchResponse fetchResp = (FetchResponse)ext;
222 
223                 if (Validator.isNull(firstName)) {
224                     firstName = getFirstValue(
225                         fetchResp.getAttributeValues("firstName"));
226                 }
227 
228                 if (Validator.isNull(lastName)) {
229                     lastName = getFirstValue(
230                         fetchResp.getAttributeValues("lastName"));
231                 }
232 
233                 if (Validator.isNull(emailAddress)) {
234                     emailAddress = getFirstValue(
235                         fetchResp.getAttributeValues("email"));
236                 }
237             }
238         }
239 
240         String openId = OpenIdUtil.normalize(authSuccess.getIdentity());
241 
242         User user = null;
243 
244         try {
245             user = UserLocalServiceUtil.getUserByOpenId(openId);
246         }
247         catch (NoSuchUserException nsue) {
248             if (Validator.isNull(firstName) || Validator.isNull(lastName) ||
249                 Validator.isNull(emailAddress)) {
250 
251                 SessionMessages.add(request, "missingOpenIdUserInformation");
252 
253                 if (_log.isInfoEnabled()) {
254                     _log.info(
255                         "The OpenID provider did not send the required " +
256                             "attributes to create an account");
257                 }
258 
259                 PortletURL createAccountURL =
260                     themeDisplay.getURLCreateAccount();
261 
262                 createAccountURL.setParameter("openId", openId);
263 
264                 session.setAttribute(
265                     WebKeys.OPEN_ID_LOGIN_PENDING, Boolean.TRUE);
266 
267                 return createAccountURL.toString();
268             }
269 
270             user = addUser(
271                 themeDisplay.getCompanyId(), firstName, lastName, emailAddress,
272                 openId, themeDisplay.getLocale());
273         }
274 
275         session.setAttribute(WebKeys.OPEN_ID_LOGIN, new Long(user.getUserId()));
276 
277         return null;
278     }
279 
280     private static Log _log = LogFactoryUtil.getLog(OpenIdResponseAction.class);
281 
282 }