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