1   /**
2    * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.action;
24  
25  import com.liferay.portal.NoSuchUserException;
26  import com.liferay.portal.kernel.util.GetterUtil;
27  import com.liferay.portal.kernel.util.StringPool;
28  import com.liferay.portal.kernel.util.Validator;
29  import com.liferay.portal.model.User;
30  import com.liferay.portal.service.UserLocalServiceUtil;
31  import com.liferay.portal.struts.ActionConstants;
32  import com.liferay.portal.theme.ThemeDisplay;
33  import com.liferay.portal.util.OpenIdUtil;
34  import com.liferay.portal.util.PortalUtil;
35  import com.liferay.portal.util.WebKeys;
36  import com.liferay.util.PwdGenerator;
37  import com.liferay.util.servlet.SessionErrors;
38  
39  import java.util.Calendar;
40  import java.util.List;
41  import java.util.Locale;
42  
43  import javax.servlet.http.HttpServletRequest;
44  import javax.servlet.http.HttpServletResponse;
45  import javax.servlet.http.HttpSession;
46  import javax.servlet.jsp.PageContext;
47  
48  import org.apache.commons.logging.Log;
49  import org.apache.commons.logging.LogFactory;
50  import org.apache.struts.action.Action;
51  import org.apache.struts.action.ActionForm;
52  import org.apache.struts.action.ActionForward;
53  import org.apache.struts.action.ActionMapping;
54  
55  import org.openid4java.association.AssociationException;
56  import org.openid4java.consumer.ConsumerException;
57  import org.openid4java.consumer.ConsumerManager;
58  import org.openid4java.consumer.VerificationResult;
59  import org.openid4java.discovery.DiscoveryException;
60  import org.openid4java.discovery.DiscoveryInformation;
61  import org.openid4java.discovery.Identifier;
62  import org.openid4java.message.AuthSuccess;
63  import org.openid4java.message.MessageException;
64  import org.openid4java.message.MessageExtension;
65  import org.openid4java.message.ParameterList;
66  import org.openid4java.message.ax.AxMessage;
67  import org.openid4java.message.ax.FetchResponse;
68  import org.openid4java.message.sreg.SRegMessage;
69  import org.openid4java.message.sreg.SRegResponse;
70  
71  /**
72   * <a href="OpenIdResponseAction.java.html"><b><i>View Source</i></b></a>
73   *
74   * @author Jorge Ferrer
75   *
76   */
77  public class OpenIdResponseAction extends Action {
78  
79      public ActionForward execute(
80              ActionMapping mapping, ActionForm form, HttpServletRequest req,
81              HttpServletResponse res)
82          throws Exception {
83  
84          ThemeDisplay themeDisplay =
85              (ThemeDisplay)req.getAttribute(WebKeys.THEME_DISPLAY);
86  
87          if (!OpenIdUtil.isEnabled(themeDisplay.getCompanyId())) {
88              return null;
89          }
90  
91          try {
92              readResponse(themeDisplay, req);
93          }
94          catch (Exception e) {
95              if (e instanceof AssociationException ||
96                  e instanceof ConsumerException ||
97                  e instanceof DiscoveryException ||
98                  e instanceof MessageException) {
99  
100                 SessionErrors.add(req, e.getClass().getName());
101 
102                 return mapping.findForward("portal.login");
103             }
104             else {
105                 req.setAttribute(PageContext.EXCEPTION, e);
106 
107                 return mapping.findForward(ActionConstants.COMMON_ERROR);
108             }
109         }
110 
111         String loginURL =
112             PortalUtil.getPortalURL(req) + themeDisplay.getPathMain() +
113                 "/portal/login";
114 
115         res.sendRedirect(loginURL);
116 
117         return null;
118     }
119 
120     protected User addUser(
121             long companyId, String firstName, String lastName,
122             String emailAddress, String screenName, 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 = false;
130         String middleName = StringPool.BLANK;
131         int prefixId = 0;
132         int suffixId = 0;
133         boolean male = true;
134         int birthdayMonth = Calendar.JANUARY;
135         int birthdayDay = 1;
136         int birthdayYear = 1970;
137         String jobTitle = StringPool.BLANK;
138         long[] organizationIds = new long[0];
139         boolean sendEmail = false;
140 
141         return UserLocalServiceUtil.addUser(
142             creatorUserId, companyId, autoPassword, password1, password2,
143             autoScreenName, screenName, emailAddress, locale, firstName,
144             middleName, lastName, prefixId, suffixId, male, birthdayMonth,
145             birthdayDay, birthdayYear, jobTitle, organizationIds, sendEmail);
146     }
147 
148     protected String getFirstValue(List values) {
149         if ((values == null) || (values.size() < 1)) {
150             return null;
151         }
152 
153         return (String)values.get(0);
154     }
155 
156     protected User readResponse(
157             ThemeDisplay themeDisplay, HttpServletRequest req)
158         throws Exception {
159 
160         HttpSession ses = req.getSession();
161 
162         ConsumerManager manager = OpenIdUtil.getConsumerManager();
163 
164         ParameterList params = new ParameterList(req.getParameterMap());
165 
166         DiscoveryInformation discovered =
167             (DiscoveryInformation)ses.getAttribute(WebKeys.OPEN_ID_DISCO);
168 
169         if (discovered == null) {
170             return null;
171         }
172 
173         StringBuffer receivingURL = req.getRequestURL();
174         String queryString = req.getQueryString();
175 
176         if ((queryString != null) && (queryString.length() > 0)) {
177             receivingURL.append(StringPool.QUESTION);
178             receivingURL.append(req.getQueryString());
179         }
180 
181         VerificationResult verification = manager.verify(
182             receivingURL.toString(), params, discovered);
183 
184         Identifier verified = verification.getVerifiedId();
185 
186         if (verified == null) {
187             return null;
188         }
189 
190         AuthSuccess authSuccess = (AuthSuccess)verification.getAuthResponse();
191 
192         String firstName = null;
193         String lastName = null;
194         String emailAddress = null;
195 
196         if (authSuccess.hasExtension(SRegMessage.OPENID_NS_SREG)) {
197             MessageExtension ext = authSuccess.getExtension(
198                 SRegMessage.OPENID_NS_SREG);
199 
200             if (ext instanceof SRegResponse) {
201                 SRegResponse sregResp = (SRegResponse)ext;
202 
203                 String fullName = GetterUtil.getString(
204                     sregResp.getAttributeValue("fullname"));
205 
206                 int pos = fullName.indexOf(StringPool.SPACE);
207 
208                 if ((pos != -1) && ((pos + 1) < fullName.length())) {
209                     firstName = fullName.substring(0, pos);
210                     lastName = fullName.substring(pos + 1);
211                 }
212 
213                 emailAddress = sregResp.getAttributeValue("email");
214             }
215         }
216 
217         if (authSuccess.hasExtension(AxMessage.OPENID_NS_AX)) {
218             MessageExtension ext = authSuccess.getExtension(
219                 AxMessage.OPENID_NS_AX);
220 
221             if (ext instanceof FetchResponse) {
222                 FetchResponse fetchResp = (FetchResponse)ext;
223 
224                 if (Validator.isNull(firstName)) {
225                     firstName = getFirstValue(
226                         fetchResp.getAttributeValues("firstName"));
227                 }
228 
229                 if (Validator.isNull(lastName)) {
230                     lastName = getFirstValue(
231                         fetchResp.getAttributeValues("lastName"));
232                 }
233 
234                 if (Validator.isNull(emailAddress)) {
235                     emailAddress = getFirstValue(
236                         fetchResp.getAttributeValues("email"));
237                 }
238             }
239         }
240 
241         String screenName = OpenIdUtil.getScreenName(authSuccess.getIdentity());
242 
243         User user = null;
244 
245         try {
246             user = UserLocalServiceUtil.getUserByScreenName(
247                 themeDisplay.getCompanyId(), screenName);
248         }
249         catch (NoSuchUserException nsue) {
250             if (Validator.isNull(firstName) || Validator.isNull(lastName) ||
251                 Validator.isNull(emailAddress)) {
252 
253                 SessionErrors.add(req, "missingOpenIdUserInformation");
254 
255                 _log.error(
256                     "The OpenID provider did not send the required " +
257                         "attributes to create an account");
258 
259                 return null;
260             }
261 
262             user = addUser(
263                 themeDisplay.getCompanyId(), firstName, lastName, emailAddress,
264                 screenName, themeDisplay.getLocale());
265         }
266 
267         ses.setAttribute(WebKeys.OPEN_ID_LOGIN, new Long(user.getUserId()));
268 
269         return user;
270     }
271 
272     private static Log _log = LogFactory.getLog(OpenIdResponseAction.class);
273 
274 }