1
19
20 package com.liferay.portlet.login.action;
21
22 import com.liferay.portal.DuplicateUserEmailAddressException;
23 import com.liferay.portal.NoSuchUserException;
24 import com.liferay.portal.kernel.language.LanguageUtil;
25 import com.liferay.portal.kernel.log.Log;
26 import com.liferay.portal.kernel.log.LogFactoryUtil;
27 import com.liferay.portal.kernel.servlet.SessionErrors;
28 import com.liferay.portal.kernel.servlet.SessionMessages;
29 import com.liferay.portal.kernel.util.Constants;
30 import com.liferay.portal.kernel.util.GetterUtil;
31 import com.liferay.portal.kernel.util.ParamUtil;
32 import com.liferay.portal.kernel.util.StringPool;
33 import com.liferay.portal.kernel.util.Validator;
34 import com.liferay.portal.model.User;
35 import com.liferay.portal.service.ServiceContext;
36 import com.liferay.portal.service.UserLocalServiceUtil;
37 import com.liferay.portal.struts.PortletAction;
38 import com.liferay.portal.theme.ThemeDisplay;
39 import com.liferay.portal.util.OpenIdUtil;
40 import com.liferay.portal.util.PortalUtil;
41 import com.liferay.portal.util.WebKeys;
42 import com.liferay.portlet.ActionResponseImpl;
43 import com.liferay.util.PwdGenerator;
44
45 import java.util.Calendar;
46 import java.util.List;
47 import java.util.Locale;
48
49 import javax.portlet.ActionRequest;
50 import javax.portlet.ActionResponse;
51 import javax.portlet.PortletConfig;
52 import javax.portlet.PortletURL;
53 import javax.portlet.RenderRequest;
54 import javax.portlet.RenderResponse;
55
56 import javax.servlet.http.HttpServletRequest;
57 import javax.servlet.http.HttpServletResponse;
58 import javax.servlet.http.HttpSession;
59
60 import org.apache.struts.action.ActionForm;
61 import org.apache.struts.action.ActionForward;
62 import org.apache.struts.action.ActionMapping;
63
64 import org.openid4java.OpenIDException;
65 import org.openid4java.consumer.ConsumerManager;
66 import org.openid4java.consumer.VerificationResult;
67 import org.openid4java.discovery.DiscoveryInformation;
68 import org.openid4java.discovery.Identifier;
69 import org.openid4java.message.AuthRequest;
70 import org.openid4java.message.AuthSuccess;
71 import org.openid4java.message.MessageExtension;
72 import org.openid4java.message.ParameterList;
73 import org.openid4java.message.ax.AxMessage;
74 import org.openid4java.message.ax.FetchRequest;
75 import org.openid4java.message.ax.FetchResponse;
76 import org.openid4java.message.sreg.SRegMessage;
77 import org.openid4java.message.sreg.SRegRequest;
78 import org.openid4java.message.sreg.SRegResponse;
79
80
87 public class OpenIdAction extends PortletAction {
88
89 public void processAction(
90 ActionMapping mapping, ActionForm form, PortletConfig portletConfig,
91 ActionRequest actionRequest, ActionResponse actionResponse)
92 throws Exception {
93
94 ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
95 WebKeys.THEME_DISPLAY);
96
97 if (actionRequest.getRemoteUser() != null) {
98 actionResponse.sendRedirect(themeDisplay.getPathMain());
99
100 return;
101 }
102
103 String cmd = ParamUtil.getString(actionRequest, Constants.CMD);
104
105 try {
106 if (cmd.equals(Constants.READ)) {
107 String redirect = readOpenIdResponse(
108 themeDisplay, actionRequest, actionResponse);
109
110 if (Validator.isNull(redirect)) {
111 redirect =
112 PortalUtil.getPortalURL(actionRequest) +
113 themeDisplay.getURLSignIn();
114 }
115
116 sendRedirect(actionRequest, actionResponse, redirect);
117 }
118 else {
119 sendOpenIdRequest(themeDisplay, actionRequest, actionResponse);
120 }
121 }
122 catch (Exception e) {
123 if (e instanceof DuplicateUserEmailAddressException) {
124 SessionErrors.add(actionRequest, e.getClass().getName());
125 }
126 else if (e instanceof OpenIDException) {
127 if (_log.isInfoEnabled()) {
128 _log.info(
129 "Error communicating with OpenID provider: " +
130 e.getMessage());
131 }
132
133 SessionErrors.add(actionRequest, e.getClass().getName());
134 }
135 else {
136 _log.error("Error processing the OpenID login", e);
137
138 PortalUtil.sendError(e, actionRequest, actionResponse);
139 }
140 }
141 }
142
143 public ActionForward render(
144 ActionMapping mapping, ActionForm form, PortletConfig portletConfig,
145 RenderRequest renderRequest, RenderResponse renderResponse)
146 throws Exception {
147
148 ThemeDisplay themeDisplay = (ThemeDisplay)renderRequest.getAttribute(
149 WebKeys.THEME_DISPLAY);
150
151 renderResponse.setTitle(
152 LanguageUtil.get(
153 themeDisplay.getCompanyId(), themeDisplay.getLocale(),
154 "open-id"));
155
156 return mapping.findForward("portlet.login.open_id");
157 }
158
159 protected String getFirstValue(List<String> values) {
160 if ((values == null) || (values.size() < 1)) {
161 return null;
162 }
163
164 return values.get(0);
165 }
166
167 protected boolean isCheckMethodOnProcessAction() {
168 return _CHECK_METHOD_ON_PROCESS_ACTION;
169 }
170
171 protected String readOpenIdResponse(
172 ThemeDisplay themeDisplay, ActionRequest actionRequest,
173 ActionResponse actionResponse)
174 throws Exception {
175
176 HttpServletRequest request = PortalUtil.getHttpServletRequest(
177 actionRequest);
178 HttpSession session = request.getSession();
179
180 ActionResponseImpl actionResponseImpl =
181 (ActionResponseImpl)actionResponse;
182
183 ConsumerManager manager = OpenIdUtil.getConsumerManager();
184
185 ParameterList params = new ParameterList(
186 actionRequest.getParameterMap());
187
188 DiscoveryInformation discovered =
189 (DiscoveryInformation)session.getAttribute(WebKeys.OPEN_ID_DISCO);
190
191 if (discovered == null) {
192 return null;
193 }
194
195 PortletURL portletURL = actionResponseImpl.createActionURL();
196
197 portletURL.setParameter("struts_action", "/login/open_id");
198 portletURL.setParameter(Constants.CMD, Constants.READ);
199 portletURL.setParameter("saveLastPath", "0");
200
201 VerificationResult verification = manager.verify(
202 portletURL.toString(), params, discovered);
203
204 Identifier verified = verification.getVerifiedId();
205
206 if (verified == null) {
207 return null;
208 }
209
210 AuthSuccess authSuccess = (AuthSuccess)verification.getAuthResponse();
211
212 String firstName = null;
213 String lastName = null;
214 String emailAddress = null;
215
216 if (authSuccess.hasExtension(SRegMessage.OPENID_NS_SREG)) {
217 MessageExtension ext = authSuccess.getExtension(
218 SRegMessage.OPENID_NS_SREG);
219
220 if (ext instanceof SRegResponse) {
221 SRegResponse sregResp = (SRegResponse)ext;
222
223 String fullName = GetterUtil.getString(
224 sregResp.getAttributeValue("fullname"));
225
226 int pos = fullName.indexOf(StringPool.SPACE);
227
228 if ((pos != -1) && ((pos + 1) < fullName.length())) {
229 firstName = fullName.substring(0, pos);
230 lastName = fullName.substring(pos + 1);
231 }
232
233 emailAddress = sregResp.getAttributeValue("email");
234 }
235 }
236
237 if (authSuccess.hasExtension(AxMessage.OPENID_NS_AX)) {
238 MessageExtension ext = authSuccess.getExtension(
239 AxMessage.OPENID_NS_AX);
240
241 if (ext instanceof FetchResponse) {
242 FetchResponse fetchResp = (FetchResponse)ext;
243
244 if (Validator.isNull(firstName)) {
245 firstName = getFirstValue(
246 fetchResp.getAttributeValues("firstName"));
247 }
248
249 if (Validator.isNull(lastName)) {
250 lastName = getFirstValue(
251 fetchResp.getAttributeValues("lastName"));
252 }
253
254 if (Validator.isNull(emailAddress)) {
255 emailAddress = getFirstValue(
256 fetchResp.getAttributeValues("email"));
257 }
258 }
259 }
260
261 String openId = OpenIdUtil.normalize(authSuccess.getIdentity());
262
263 User user = null;
264
265 try {
266 user = UserLocalServiceUtil.getUserByOpenId(openId);
267 }
268 catch (NoSuchUserException nsue) {
269 if (Validator.isNull(firstName) || Validator.isNull(lastName) ||
270 Validator.isNull(emailAddress)) {
271
272 SessionMessages.add(request, "missingOpenIdUserInformation");
273
274 if (_log.isInfoEnabled()) {
275 _log.info(
276 "The OpenID provider did not send the required " +
277 "attributes to create an account");
278 }
279
280 PortletURL createAccountURL =
281 themeDisplay.getURLCreateAccount();
282
283 createAccountURL.setParameter("openId", openId);
284
285 session.setAttribute(
286 WebKeys.OPEN_ID_LOGIN_PENDING, Boolean.TRUE);
287
288 return createAccountURL.toString();
289 }
290
291 long creatorUserId = 0;
292 long companyId = themeDisplay.getCompanyId();
293 boolean autoPassword = false;
294 String password1 = PwdGenerator.getPassword();
295 String password2 = password1;
296 boolean autoScreenName = true;
297 String screenName = StringPool.BLANK;
298 Locale locale = themeDisplay.getLocale();
299 String middleName = StringPool.BLANK;
300 int prefixId = 0;
301 int suffixId = 0;
302 boolean male = true;
303 int birthdayMonth = Calendar.JANUARY;
304 int birthdayDay = 1;
305 int birthdayYear = 1970;
306 String jobTitle = StringPool.BLANK;
307 long[] groupIds = null;
308 long[] organizationIds = null;
309 long[] roleIds = null;
310 long[] userGroupIds = null;
311 boolean sendEmail = false;
312
313 ServiceContext serviceContext = new ServiceContext();
314
315 user = UserLocalServiceUtil.addUser(
316 creatorUserId, companyId, autoPassword, password1, password2,
317 autoScreenName, screenName, emailAddress, openId, locale,
318 firstName, middleName, lastName, prefixId, suffixId, male,
319 birthdayMonth, birthdayDay, birthdayYear, jobTitle, groupIds,
320 organizationIds, roleIds, userGroupIds, sendEmail,
321 serviceContext);
322 }
323
324 session.setAttribute(WebKeys.OPEN_ID_LOGIN, new Long(user.getUserId()));
325
326 return null;
327 }
328
329 protected void sendOpenIdRequest(
330 ThemeDisplay themeDisplay, ActionRequest actionRequest,
331 ActionResponse actionResponse)
332 throws Exception {
333
334 if (!OpenIdUtil.isEnabled(themeDisplay.getCompanyId())) {
335 return;
336 }
337
338 HttpServletRequest request = PortalUtil.getHttpServletRequest(
339 actionRequest);
340 HttpServletResponse response = PortalUtil.getHttpServletResponse(
341 actionResponse);
342 HttpSession session = request.getSession();
343
344 ActionResponseImpl actionResponseImpl =
345 (ActionResponseImpl)actionResponse;
346
347 String openId = ParamUtil.getString(actionRequest, "openId");
348
349 PortletURL portletURL = actionResponseImpl.createActionURL();
350
351 portletURL.setParameter("struts_action", "/login/open_id");
352 portletURL.setParameter(Constants.CMD, Constants.READ);
353 portletURL.setParameter("saveLastPath", "0");
354
355 ConsumerManager manager = OpenIdUtil.getConsumerManager();
356
357 List<DiscoveryInformation> discoveries = manager.discover(openId);
358
359 DiscoveryInformation discovered = manager.associate(discoveries);
360
361 session.setAttribute(WebKeys.OPEN_ID_DISCO, discovered);
362
363 AuthRequest authRequest = manager.authenticate(
364 discovered, portletURL.toString(), themeDisplay.getPortalURL());
365
366 try {
367 UserLocalServiceUtil.getUserByOpenId(openId);
368 }
369 catch (NoSuchUserException nsue) {
370 String screenName = OpenIdUtil.getScreenName(openId);
371
372 try {
373 User user = UserLocalServiceUtil.getUserByScreenName(
374 themeDisplay.getCompanyId(), screenName);
375
376 UserLocalServiceUtil.updateOpenId(user.getUserId(), openId);
377 }
378 catch (NoSuchUserException nsue2) {
379 FetchRequest fetch = FetchRequest.createFetchRequest();
380
381 fetch.addAttribute(
382 "email", "http://schema.openid.net/contact/email", true);
383 fetch.addAttribute(
384 "firstName", "http://schema.openid.net/namePerson/first",
385 true);
386 fetch.addAttribute(
387 "lastName", "http://schema.openid.net/namePerson/last",
388 true);
389
390 authRequest.addExtension(fetch);
391
392 SRegRequest sregRequest = SRegRequest.createFetchRequest();
393
394 sregRequest.addAttribute("fullname", true);
395 sregRequest.addAttribute("email", true);
396
397 authRequest.addExtension(sregRequest);
398 }
399 }
400
401 response.sendRedirect(authRequest.getDestinationUrl(true));
402 }
403
404 private static final boolean _CHECK_METHOD_ON_PROCESS_ACTION = false;
405
406 private static Log _log = LogFactoryUtil.getLog(OpenIdAction.class);
407
408 }