001
014
015 package com.liferay.portlet.login.action;
016
017 import com.liferay.portal.DuplicateUserEmailAddressException;
018 import com.liferay.portal.NoSuchUserException;
019 import com.liferay.portal.kernel.log.Log;
020 import com.liferay.portal.kernel.log.LogFactoryUtil;
021 import com.liferay.portal.kernel.servlet.SessionErrors;
022 import com.liferay.portal.kernel.servlet.SessionMessages;
023 import com.liferay.portal.kernel.util.CharPool;
024 import com.liferay.portal.kernel.util.Constants;
025 import com.liferay.portal.kernel.util.GetterUtil;
026 import com.liferay.portal.kernel.util.HttpUtil;
027 import com.liferay.portal.kernel.util.ParamUtil;
028 import com.liferay.portal.kernel.util.StringPool;
029 import com.liferay.portal.kernel.util.Validator;
030 import com.liferay.portal.model.User;
031 import com.liferay.portal.security.auth.PrincipalException;
032 import com.liferay.portal.service.ServiceContext;
033 import com.liferay.portal.service.UserLocalServiceUtil;
034 import com.liferay.portal.struts.PortletAction;
035 import com.liferay.portal.theme.ThemeDisplay;
036 import com.liferay.portal.util.OpenIdUtil;
037 import com.liferay.portal.util.PortalUtil;
038 import com.liferay.portal.util.WebKeys;
039 import com.liferay.portlet.ActionResponseImpl;
040 import com.liferay.util.PwdGenerator;
041
042 import java.util.Calendar;
043 import java.util.List;
044 import java.util.Locale;
045
046 import javax.portlet.ActionRequest;
047 import javax.portlet.ActionResponse;
048 import javax.portlet.PortletConfig;
049 import javax.portlet.PortletURL;
050 import javax.portlet.RenderRequest;
051 import javax.portlet.RenderResponse;
052
053 import javax.servlet.http.HttpServletRequest;
054 import javax.servlet.http.HttpServletResponse;
055 import javax.servlet.http.HttpSession;
056
057 import org.apache.struts.action.ActionForm;
058 import org.apache.struts.action.ActionForward;
059 import org.apache.struts.action.ActionMapping;
060
061 import org.openid4java.OpenIDException;
062 import org.openid4java.consumer.ConsumerManager;
063 import org.openid4java.consumer.VerificationResult;
064 import org.openid4java.discovery.DiscoveryInformation;
065 import org.openid4java.discovery.Identifier;
066 import org.openid4java.message.AuthRequest;
067 import org.openid4java.message.AuthSuccess;
068 import org.openid4java.message.MessageExtension;
069 import org.openid4java.message.ParameterList;
070 import org.openid4java.message.ax.AxMessage;
071 import org.openid4java.message.ax.FetchRequest;
072 import org.openid4java.message.ax.FetchResponse;
073 import org.openid4java.message.sreg.SRegMessage;
074 import org.openid4java.message.sreg.SRegRequest;
075 import org.openid4java.message.sreg.SRegResponse;
076
077
081 public class OpenIdAction extends PortletAction {
082
083 @Override
084 public void processAction(
085 ActionMapping mapping, ActionForm form, PortletConfig portletConfig,
086 ActionRequest actionRequest, ActionResponse actionResponse)
087 throws Exception {
088
089 ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
090 WebKeys.THEME_DISPLAY);
091
092 if (!OpenIdUtil.isEnabled(themeDisplay.getCompanyId())) {
093 throw new PrincipalException();
094 }
095
096 if (actionRequest.getRemoteUser() != null) {
097 actionResponse.sendRedirect(themeDisplay.getPathMain());
098
099 return;
100 }
101
102 String cmd = ParamUtil.getString(actionRequest, Constants.CMD);
103
104 try {
105 if (cmd.equals(Constants.READ)) {
106 String redirect = readOpenIdResponse(
107 themeDisplay, actionRequest, actionResponse);
108
109 if (Validator.isNull(redirect)) {
110 redirect =
111 PortalUtil.getPortalURL(actionRequest) +
112 themeDisplay.getURLSignIn();
113 }
114
115 sendRedirect(actionRequest, actionResponse, redirect);
116 }
117 else {
118 sendOpenIdRequest(themeDisplay, actionRequest, actionResponse);
119 }
120 }
121 catch (Exception e) {
122 if (e instanceof DuplicateUserEmailAddressException) {
123 SessionErrors.add(actionRequest, e.getClass().getName());
124 }
125 else if (e instanceof OpenIDException) {
126 if (_log.isInfoEnabled()) {
127 _log.info(
128 "Error communicating with OpenID provider: " +
129 e.getMessage());
130 }
131
132 SessionErrors.add(actionRequest, e.getClass().getName());
133 }
134 else {
135 _log.error("Error processing the OpenID login", e);
136
137 PortalUtil.sendError(e, actionRequest, actionResponse);
138 }
139 }
140 }
141
142 @Override
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 if (!OpenIdUtil.isEnabled(themeDisplay.getCompanyId())) {
152 return mapping.findForward("portlet.login.login");
153 }
154
155 renderResponse.setTitle(themeDisplay.translate("open-id"));
156
157 return mapping.findForward("portlet.login.open_id");
158 }
159
160 protected String getFirstValue(List<String> values) {
161 if ((values == null) || (values.size() < 1)) {
162 return null;
163 }
164
165 return values.get(0);
166 }
167
168 @Override
169 protected boolean isCheckMethodOnProcessAction() {
170 return _CHECK_METHOD_ON_PROCESS_ACTION;
171 }
172
173 protected String readOpenIdResponse(
174 ThemeDisplay themeDisplay, ActionRequest actionRequest,
175 ActionResponse actionResponse)
176 throws Exception {
177
178 HttpServletRequest request = PortalUtil.getHttpServletRequest(
179 actionRequest);
180 HttpSession session = request.getSession();
181
182 ConsumerManager manager = OpenIdUtil.getConsumerManager();
183
184 ParameterList params = new ParameterList(
185 actionRequest.getParameterMap());
186
187 DiscoveryInformation discovered =
188 (DiscoveryInformation)session.getAttribute(WebKeys.OPEN_ID_DISCO);
189
190 if (discovered == null) {
191 return null;
192 }
193
194 String receivingUrl = ParamUtil.getString(
195 actionRequest, "openid.return_to");
196
197 VerificationResult verification = manager.verify(
198 receivingUrl, params, discovered);
199
200 Identifier verified = verification.getVerifiedId();
201
202 if (verified == null) {
203 return null;
204 }
205
206 AuthSuccess authSuccess = (AuthSuccess)verification.getAuthResponse();
207
208 String firstName = null;
209 String lastName = null;
210 String emailAddress = null;
211
212 if (authSuccess.hasExtension(SRegMessage.OPENID_NS_SREG)) {
213 MessageExtension ext = authSuccess.getExtension(
214 SRegMessage.OPENID_NS_SREG);
215
216 if (ext instanceof SRegResponse) {
217 SRegResponse sregResp = (SRegResponse)ext;
218
219 String fullName = GetterUtil.getString(
220 sregResp.getAttributeValue("fullname"));
221
222 int pos = fullName.indexOf(CharPool.SPACE);
223
224 if ((pos != -1) && ((pos + 1) < fullName.length())) {
225 firstName = fullName.substring(0, pos);
226 lastName = fullName.substring(pos + 1);
227 }
228
229 emailAddress = sregResp.getAttributeValue("email");
230 }
231 }
232
233 if (authSuccess.hasExtension(AxMessage.OPENID_NS_AX)) {
234 MessageExtension ext = authSuccess.getExtension(
235 AxMessage.OPENID_NS_AX);
236
237 if (ext instanceof FetchResponse) {
238 FetchResponse fetchResp = (FetchResponse)ext;
239
240 if (Validator.isNull(firstName)) {
241 firstName = getFirstValue(
242 fetchResp.getAttributeValues("firstName"));
243 }
244
245 if (Validator.isNull(lastName)) {
246 lastName = getFirstValue(
247 fetchResp.getAttributeValues("lastName"));
248 }
249
250 if (Validator.isNull(emailAddress)) {
251 emailAddress = getFirstValue(
252 fetchResp.getAttributeValues("email"));
253 }
254 }
255 }
256
257 String openId = OpenIdUtil.normalize(authSuccess.getIdentity());
258
259 User user = null;
260
261 try {
262 user = UserLocalServiceUtil.getUserByOpenId(
263 themeDisplay.getCompanyId(), openId);
264 }
265 catch (NoSuchUserException nsue) {
266 if (Validator.isNull(firstName) || Validator.isNull(lastName) ||
267 Validator.isNull(emailAddress)) {
268
269 SessionMessages.add(request, "missingOpenIdUserInformation");
270
271 if (_log.isInfoEnabled()) {
272 _log.info(
273 "The OpenID provider did not send the required " +
274 "attributes to create an account");
275 }
276
277 String createAccountURL = PortalUtil.getCreateAccountURL(
278 request, themeDisplay);
279
280 createAccountURL = HttpUtil.setParameter(
281 createAccountURL, "openId", openId);
282
283 session.setAttribute(
284 WebKeys.OPEN_ID_LOGIN_PENDING, Boolean.TRUE);
285
286 return createAccountURL;
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 long facebookId = 0;
297 Locale locale = themeDisplay.getLocale();
298 String middleName = StringPool.BLANK;
299 int prefixId = 0;
300 int suffixId = 0;
301 boolean male = true;
302 int birthdayMonth = Calendar.JANUARY;
303 int birthdayDay = 1;
304 int birthdayYear = 1970;
305 String jobTitle = StringPool.BLANK;
306 long[] groupIds = null;
307 long[] organizationIds = null;
308 long[] roleIds = null;
309 long[] userGroupIds = null;
310 boolean sendEmail = false;
311
312 ServiceContext serviceContext = new ServiceContext();
313
314 user = UserLocalServiceUtil.addUser(
315 creatorUserId, companyId, autoPassword, password1, password2,
316 autoScreenName, screenName, emailAddress, facebookId, openId,
317 locale, firstName, middleName, lastName, prefixId, suffixId,
318 male, birthdayMonth, birthdayDay, birthdayYear, jobTitle,
319 groupIds, organizationIds, roleIds, userGroupIds, sendEmail,
320 serviceContext);
321 }
322
323 session.setAttribute(WebKeys.OPEN_ID_LOGIN, new Long(user.getUserId()));
324
325 return null;
326 }
327
328 protected void sendOpenIdRequest(
329 ThemeDisplay themeDisplay, ActionRequest actionRequest,
330 ActionResponse actionResponse)
331 throws Exception {
332
333 HttpServletRequest request = PortalUtil.getHttpServletRequest(
334 actionRequest);
335 HttpServletResponse response = PortalUtil.getHttpServletResponse(
336 actionResponse);
337 HttpSession session = request.getSession();
338
339 ActionResponseImpl actionResponseImpl =
340 (ActionResponseImpl)actionResponse;
341
342 String openId = ParamUtil.getString(actionRequest, "openId");
343
344 PortletURL portletURL = actionResponseImpl.createActionURL();
345
346 portletURL.setParameter("struts_action", "/login/open_id");
347 portletURL.setParameter(Constants.CMD, Constants.READ);
348 portletURL.setParameter("saveLastPath", "0");
349
350 ConsumerManager manager = OpenIdUtil.getConsumerManager();
351
352 List<DiscoveryInformation> discoveries = manager.discover(openId);
353
354 DiscoveryInformation discovered = manager.associate(discoveries);
355
356 session.setAttribute(WebKeys.OPEN_ID_DISCO, discovered);
357
358 AuthRequest authRequest = manager.authenticate(
359 discovered, portletURL.toString(), themeDisplay.getPortalURL());
360
361 try {
362 UserLocalServiceUtil.getUserByOpenId(
363 themeDisplay.getCompanyId(), openId);
364 }
365 catch (NoSuchUserException nsue) {
366 String screenName = OpenIdUtil.getScreenName(openId);
367
368 try {
369 User user = UserLocalServiceUtil.getUserByScreenName(
370 themeDisplay.getCompanyId(), screenName);
371
372 UserLocalServiceUtil.updateOpenId(user.getUserId(), openId);
373 }
374 catch (NoSuchUserException nsue2) {
375 FetchRequest fetch = FetchRequest.createFetchRequest();
376
377 fetch.addAttribute(
378 "email", "http:
379 fetch.addAttribute(
380 "firstName", "http:
381 true);
382 fetch.addAttribute(
383 "lastName", "http:
384 true);
385
386 authRequest.addExtension(fetch);
387
388 SRegRequest sregRequest = SRegRequest.createFetchRequest();
389
390 sregRequest.addAttribute("fullname", true);
391 sregRequest.addAttribute("email", true);
392
393 authRequest.addExtension(sregRequest);
394 }
395 }
396
397 response.sendRedirect(authRequest.getDestinationUrl(true));
398 }
399
400 private static final boolean _CHECK_METHOD_ON_PROCESS_ACTION = false;
401
402 private static Log _log = LogFactoryUtil.getLog(OpenIdAction.class);
403
404 }