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 ServiceContext serviceContext = new ServiceContext();
316
317 user = UserLocalServiceUtil.addUser(
318 creatorUserId, companyId, autoPassword, password1, password2,
319 autoScreenName, screenName, emailAddress, openId, locale,
320 firstName, middleName, lastName, prefixId, suffixId, male,
321 birthdayMonth, birthdayDay, birthdayYear, jobTitle, groupIds,
322 organizationIds, roleIds, userGroupIds, sendEmail,
323 serviceContext);
324 }
325
326 session.setAttribute(WebKeys.OPEN_ID_LOGIN, new Long(user.getUserId()));
327
328 return null;
329 }
330
331 protected void sendOpenIdRequest(
332 ThemeDisplay themeDisplay, ActionRequest actionRequest,
333 ActionResponse actionResponse)
334 throws Exception {
335
336 if (!OpenIdUtil.isEnabled(themeDisplay.getCompanyId())) {
337 return;
338 }
339
340 HttpServletRequest request = PortalUtil.getHttpServletRequest(
341 actionRequest);
342 HttpServletResponse response = PortalUtil.getHttpServletResponse(
343 actionResponse);
344 HttpSession session = request.getSession();
345
346 ActionResponseImpl actionResponseImpl =
347 (ActionResponseImpl)actionResponse;
348
349 String openId = ParamUtil.getString(actionRequest, "openId");
350
351 PortletURL portletURL = actionResponseImpl.createActionURL();
352
353 portletURL.setParameter("struts_action", "/login/open_id");
354 portletURL.setParameter(Constants.CMD, Constants.READ);
355 portletURL.setParameter("saveLastPath", "0");
356
357 ConsumerManager manager = OpenIdUtil.getConsumerManager();
358
359 List<DiscoveryInformation> discoveries = manager.discover(openId);
360
361 DiscoveryInformation discovered = manager.associate(discoveries);
362
363 session.setAttribute(WebKeys.OPEN_ID_DISCO, discovered);
364
365 AuthRequest authRequest = manager.authenticate(
366 discovered, portletURL.toString(), themeDisplay.getPortalURL());
367
368 try {
369 UserLocalServiceUtil.getUserByOpenId(openId);
370 }
371 catch (NoSuchUserException nsue) {
372 String screenName = OpenIdUtil.getScreenName(openId);
373
374 try {
375 User user = UserLocalServiceUtil.getUserByScreenName(
376 themeDisplay.getCompanyId(), screenName);
377
378 UserLocalServiceUtil.updateOpenId(user.getUserId(), openId);
379 }
380 catch (NoSuchUserException nsue2) {
381 FetchRequest fetch = FetchRequest.createFetchRequest();
382
383 fetch.addAttribute(
384 "email", "http://schema.openid.net/contact/email", true);
385 fetch.addAttribute(
386 "firstName", "http://schema.openid.net/namePerson/first",
387 true);
388 fetch.addAttribute(
389 "lastName", "http://schema.openid.net/namePerson/last",
390 true);
391
392 authRequest.addExtension(fetch);
393
394 SRegRequest sregRequest = SRegRequest.createFetchRequest();
395
396 sregRequest.addAttribute("fullname", true);
397 sregRequest.addAttribute("email", true);
398
399 authRequest.addExtension(sregRequest);
400 }
401 }
402
403 response.sendRedirect(authRequest.getDestinationUrl(true));
404 }
405
406 private static final boolean _CHECK_METHOD_ON_PROCESS_ACTION = false;
407
408 private static Log _log = LogFactoryUtil.getLog(OpenIdAction.class);
409
410 }