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.getURLSignIn();
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[] organizationIds = new long[0];
138         boolean sendEmail = false;
139 
140         return UserLocalServiceUtil.addUser(
141             creatorUserId, companyId, autoPassword, password1, password2,
142             autoScreenName, screenName, emailAddress, locale, firstName,
143             middleName, lastName, prefixId, suffixId, male, birthdayMonth,
144             birthdayDay, birthdayYear, jobTitle, organizationIds, sendEmail);
145     }
146 
147     protected String getFirstValue(List<String> values) {
148         if ((values == null) || (values.size() < 1)) {
149             return null;
150         }
151 
152         return values.get(0);
153     }
154 
155     protected User readResponse(
156             ThemeDisplay themeDisplay, HttpServletRequest req)
157         throws Exception {
158 
159         HttpSession ses = req.getSession();
160 
161         ConsumerManager manager = OpenIdUtil.getConsumerManager();
162 
163         ParameterList params = new ParameterList(req.getParameterMap());
164 
165         DiscoveryInformation discovered =
166             (DiscoveryInformation)ses.getAttribute(WebKeys.OPEN_ID_DISCO);
167 
168         if (discovered == null) {
169             return null;
170         }
171 
172         StringBuffer receivingURL = req.getRequestURL();
173         String queryString = req.getQueryString();
174 
175         if ((queryString != null) && (queryString.length() > 0)) {
176             receivingURL.append(StringPool.QUESTION);
177             receivingURL.append(req.getQueryString());
178         }
179 
180         VerificationResult verification = manager.verify(
181             receivingURL.toString(), 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 screenName = OpenIdUtil.getScreenName(authSuccess.getIdentity());
241 
242         User user = null;
243 
244         try {
245             user = UserLocalServiceUtil.getUserByScreenName(
246                 themeDisplay.getCompanyId(), screenName);
247         }
248         catch (NoSuchUserException nsue) {
249             if (Validator.isNull(firstName) || Validator.isNull(lastName) ||
250                 Validator.isNull(emailAddress)) {
251 
252                 SessionErrors.add(req, "missingOpenIdUserInformation");
253 
254                 _log.error(
255                     "The OpenID provider did not send the required " +
256                         "attributes to create an account");
257 
258                 return null;
259             }
260 
261             user = addUser(
262                 themeDisplay.getCompanyId(), firstName, lastName, emailAddress,
263                 screenName, themeDisplay.getLocale());
264         }
265 
266         ses.setAttribute(WebKeys.OPEN_ID_LOGIN, new Long(user.getUserId()));
267 
268         return user;
269     }
270 
271     private static Log _log = LogFactory.getLog(OpenIdResponseAction.class);
272 
273 }