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