1   /**
2    * Copyright (c) 2000-2007 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.StringPool;
27  import com.liferay.portal.kernel.util.Validator;
28  import com.liferay.portal.model.User;
29  import com.liferay.portal.service.UserLocalServiceUtil;
30  import com.liferay.portal.struts.ActionConstants;
31  import com.liferay.portal.theme.ThemeDisplay;
32  import com.liferay.portal.util.OpenIdUtil;
33  import com.liferay.portal.util.PortalUtil;
34  import com.liferay.portal.util.WebKeys;
35  import com.liferay.util.PwdGenerator;
36  import com.liferay.util.servlet.SessionErrors;
37  
38  import java.util.Calendar;
39  import java.util.List;
40  import java.util.Locale;
41  
42  import javax.servlet.http.HttpServletRequest;
43  import javax.servlet.http.HttpServletResponse;
44  import javax.servlet.http.HttpSession;
45  import javax.servlet.jsp.PageContext;
46  
47  import org.apache.commons.logging.Log;
48  import org.apache.commons.logging.LogFactory;
49  import org.apache.struts.action.Action;
50  import org.apache.struts.action.ActionForm;
51  import org.apache.struts.action.ActionForward;
52  import org.apache.struts.action.ActionMapping;
53  
54  import org.openid4java.association.AssociationException;
55  import org.openid4java.consumer.ConsumerException;
56  import org.openid4java.consumer.ConsumerManager;
57  import org.openid4java.consumer.VerificationResult;
58  import org.openid4java.discovery.DiscoveryException;
59  import org.openid4java.discovery.DiscoveryInformation;
60  import org.openid4java.discovery.Identifier;
61  import org.openid4java.message.AuthSuccess;
62  import org.openid4java.message.MessageException;
63  import org.openid4java.message.MessageExtension;
64  import org.openid4java.message.ParameterList;
65  import org.openid4java.message.ax.AxMessage;
66  import org.openid4java.message.ax.FetchResponse;
67  import org.openid4java.message.sreg.SRegMessage;
68  import org.openid4java.message.sreg.SRegResponse;
69  
70  /**
71   * <a href="OpenIdResponseAction.java.html"><b><i>View Source</i></b></a>
72   *
73   * @author Jorge Ferrer
74   *
75   */
76  public class OpenIdResponseAction extends Action {
77  
78      public ActionForward execute(
79              ActionMapping mapping, ActionForm form, HttpServletRequest req,
80              HttpServletResponse res)
81          throws Exception {
82  
83          ThemeDisplay themeDisplay =
84              (ThemeDisplay)req.getAttribute(WebKeys.THEME_DISPLAY);
85  
86          if (!OpenIdUtil.isEnabled(themeDisplay.getCompanyId())) {
87              return null;
88          }
89  
90          try {
91              readResponse(themeDisplay, req);
92          }
93          catch (Exception e) {
94              if (e instanceof AssociationException ||
95                  e instanceof ConsumerException ||
96                  e instanceof DiscoveryException ||
97                  e instanceof MessageException) {
98  
99                  SessionErrors.add(req, e.getClass().getName());
100 
101                 return mapping.findForward("portal.login");
102             }
103             else {
104                 req.setAttribute(PageContext.EXCEPTION, e);
105 
106                 return mapping.findForward(ActionConstants.COMMON_ERROR);
107             }
108         }
109 
110         String loginURL =
111             PortalUtil.getPortalURL(req) + themeDisplay.getPathMain() +
112                 "/portal/login";
113 
114         res.sendRedirect(loginURL);
115 
116         return null;
117     }
118 
119     protected User addUser(
120             long companyId, String firstName, String lastName,
121             String emailAddress, String screenName, Locale locale)
122         throws Exception {
123 
124         long creatorUserId = 0;
125         boolean autoPassword = false;
126         String password1 = PwdGenerator.getPassword();
127         String password2 = password1;
128         boolean autoScreenName = false;
129         String middleName = StringPool.BLANK;
130         int prefixId = 0;
131         int suffixId = 0;
132         boolean male = true;
133         int birthdayMonth = Calendar.JANUARY;
134         int birthdayDay = 1;
135         int birthdayYear = 1970;
136         String jobTitle = StringPool.BLANK;
137         long organizationId = 0;
138         long locationId = 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, organizationId, locationId,
146             sendEmail);
147     }
148 
149     protected String getFirstValue(List values) {
150         if ((values == null) || (values.size() < 1)) {
151             return null;
152         }
153 
154         return (String)values.get(0);
155     }
156 
157     protected User readResponse(
158             ThemeDisplay themeDisplay, HttpServletRequest req)
159         throws Exception {
160 
161         HttpSession ses = req.getSession();
162 
163         ConsumerManager manager = OpenIdUtil.getConsumerManager();
164 
165         ParameterList params = new ParameterList(req.getParameterMap());
166 
167         DiscoveryInformation discovered =
168             (DiscoveryInformation)ses.getAttribute(WebKeys.OPEN_ID_DISCO);
169 
170         if (discovered == null) {
171             return null;
172         }
173 
174         StringBuffer receivingURL = req.getRequestURL();
175         String queryString = req.getQueryString();
176 
177         if ((queryString != null) && (queryString.length() > 0)) {
178             receivingURL.append(StringPool.QUESTION);
179             receivingURL.append(req.getQueryString());
180         }
181 
182         VerificationResult verification = manager.verify(
183             receivingURL.toString(), params, discovered);
184 
185         Identifier verified = verification.getVerifiedId();
186 
187         if (verified == null) {
188             return null;
189         }
190 
191         AuthSuccess authSuccess = (AuthSuccess)verification.getAuthResponse();
192 
193         String firstName = null;
194         String lastName = null;
195         String emailAddress = null;
196 
197         if (authSuccess.hasExtension(SRegMessage.OPENID_NS_SREG)) {
198             MessageExtension ext = authSuccess.getExtension(
199                 SRegMessage.OPENID_NS_SREG);
200 
201             if (ext instanceof SRegResponse) {
202                 SRegResponse sregResp = (SRegResponse)ext;
203 
204                 String fullName = sregResp.getAttributeValue("fullname");
205                 firstName = fullName.substring(
206                     0, fullName.indexOf(StringPool.SPACE));
207                 lastName = fullName.substring(
208                     fullName.indexOf(StringPool.SPACE) + 1);
209 
210                 emailAddress = sregResp.getAttributeValue("email");
211             }
212         }
213 
214         if (authSuccess.hasExtension(AxMessage.OPENID_NS_AX)) {
215             MessageExtension ext = authSuccess.getExtension(
216                 AxMessage.OPENID_NS_AX);
217 
218             if (ext instanceof FetchResponse) {
219                 FetchResponse fetchResp = (FetchResponse)ext;
220 
221                 if (Validator.isNull(firstName)) {
222                     firstName = getFirstValue(
223                         fetchResp.getAttributeValues("firstName"));
224                 }
225 
226                 if (Validator.isNull(lastName)) {
227                     lastName = getFirstValue(
228                             fetchResp.getAttributeValues("lastName"));
229                 }
230 
231                 if (Validator.isNull(emailAddress)) {
232                     emailAddress = getFirstValue(
233                             fetchResp.getAttributeValues("email"));
234                 }
235             }
236         }
237 
238         String screenName = OpenIdUtil.getScreenName(authSuccess.getIdentity());
239 
240         User user = null;
241 
242         try {
243             user = UserLocalServiceUtil.getUserByScreenName(
244                 themeDisplay.getCompanyId(), screenName);
245         }
246         catch (NoSuchUserException nsue) {
247             if (Validator.isNull(firstName) || Validator.isNull(lastName) ||
248                 Validator.isNull(emailAddress)) {
249 
250                 SessionErrors.add(req, "missingOpenIdUserInformation");
251 
252                 _log.error(
253                     "The OpenID provider did not send the required " +
254                         "attributes to create an account");
255 
256                 return null;
257             }
258 
259             user = addUser(
260                 themeDisplay.getCompanyId(), firstName, lastName, emailAddress,
261                 screenName, themeDisplay.getLocale());
262         }
263 
264         ses.setAttribute(WebKeys.OPEN_ID_LOGIN, new Long(user.getUserId()));
265 
266         return user;
267     }
268 
269     private static Log _log = LogFactory.getLog(OpenIdResponseAction.class);
270 
271 }