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