982a60b823fba309a5e645d5cbf71fcc2b902c0d
[portal/sdk.git] /
1 /*
2  * ============LICENSE_START==========================================
3  * ONAP Portal SDK
4  * ===================================================================
5  * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
6  * ===================================================================
7  *
8  * Unless otherwise specified, all software contained herein is licensed
9  * under the Apache License, Version 2.0 (the "License");
10  * you may not use this software except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *             http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  * Unless otherwise specified, all documentation contained herein is licensed
22  * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
23  * you may not use this documentation except in compliance with the License.
24  * You may obtain a copy of the License at
25  *
26  *             https://creativecommons.org/licenses/by/4.0/
27  *
28  * Unless required by applicable law or agreed to in writing, documentation
29  * distributed under the License is distributed on an "AS IS" BASIS,
30  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
31  * See the License for the specific language governing permissions and
32  * limitations under the License.
33  *
34  * ============LICENSE_END============================================
35  *
36  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
37  */
38 package org.onap.portalapp.controller.core;
39
40 import java.net.MalformedURLException;
41 import java.net.URL;
42 import java.net.URLDecoder;
43 import java.net.URLEncoder;
44 import java.util.HashMap;
45 import java.util.List;
46 import java.util.Map;
47
48 import javax.servlet.http.Cookie;
49 import javax.servlet.http.HttpServletRequest;
50 import javax.servlet.http.HttpSession;
51
52 import org.apache.commons.lang.StringUtils;
53 import org.onap.portalsdk.core.auth.LoginStrategy;
54 import org.onap.portalsdk.core.command.LoginBean;
55 import org.onap.portalsdk.core.controller.UnRestrictedBaseController;
56 import org.onap.portalsdk.core.domain.RoleFunction;
57 import org.onap.portalsdk.core.domain.User;
58 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
59 import org.onap.portalsdk.core.menu.MenuProperties;
60 import org.onap.portalsdk.core.onboarding.listener.PortalTimeoutHandler;
61 import org.onap.portalsdk.core.onboarding.util.PortalApiConstants;
62 import org.onap.portalsdk.core.onboarding.util.PortalApiProperties;
63 import org.onap.portalsdk.core.service.LoginService;
64 import org.onap.portalsdk.core.service.RoleService;
65 import org.onap.portalsdk.core.util.SystemProperties;
66 import org.onap.portalsdk.core.web.support.AppUtils;
67 import org.onap.portalsdk.core.web.support.UserUtils;
68 import org.springframework.beans.factory.annotation.Autowired;
69 import org.springframework.stereotype.Controller;
70 import org.springframework.web.bind.annotation.RequestMapping;
71 import org.springframework.web.bind.annotation.RequestMethod;
72 import org.springframework.web.servlet.ModelAndView;
73 import org.springframework.web.util.WebUtils;
74
75 @Controller
76 @RequestMapping("/")
77 public class SingleSignOnController extends UnRestrictedBaseController {
78
79         private static final EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(SingleSignOnController.class);
80
81         @Autowired
82         private LoginService loginService;
83
84         @Autowired
85         private LoginStrategy loginStrategy;
86
87         @Autowired
88         private RoleService roleService;
89
90         private String viewName;
91         private String welcomeView;
92
93         public String getWelcomeView() {
94                 return welcomeView;
95         }
96
97         public void setWelcomeView(String welcomeView) {
98                 this.welcomeView = welcomeView;
99         }
100
101         /**
102          * Handles requests directed to the single sign-on page by the session timeout
103          * interceptor.
104          * 
105          * @param request
106          * @return Redirect to an appropriate address
107          * @throws Exception
108          */
109         @RequestMapping(value = { "/single_signon.htm" }, method = RequestMethod.GET)
110         public ModelAndView singleSignOnLogin(HttpServletRequest request) throws Exception {
111
112                 Map<String, String> model = new HashMap<>();
113                 HashMap<String, String> additionalParamsMap = new HashMap<>();
114                 LoginBean commandBean = new LoginBean();
115
116                 // SessionTimeoutInterceptor sets these parameters
117                 String forwardURL = URLDecoder.decode(request.getParameter("forwardURL"), "UTF-8");
118                 String redirectToPortal = request.getParameter("redirectToPortal");
119
120                 if (isLoginCookieExist(request) && redirectToPortal == null) {
121                         HttpSession session = AppUtils.getSession(request);
122                         User user = UserUtils.getUserSession(request);
123                         if (session == null || user == null) {
124
125                                 final String authMech = SystemProperties.getProperty(SystemProperties.AUTHENTICATION_MECHANISM);
126                                 String userId = loginStrategy.getUserId(request);
127                                 commandBean.setUserid(userId);
128                                 commandBean = getLoginService().findUser(commandBean,
129                                                 (String) request.getAttribute(MenuProperties.MENU_PROPERTIES_FILENAME_KEY),
130                                                 additionalParamsMap);
131                                 List<RoleFunction> roleFunctionList = roleService.getRoleFunctions(userId);
132                                 if (commandBean.getUser() == null) {
133                                         String loginErrorMessage = (commandBean.getLoginErrorMessage() != null)
134                                                         ? commandBean.getLoginErrorMessage()
135                                                         : SystemProperties.MESSAGE_KEY_LOGIN_ERROR_USER_NOT_FOUND;
136                                         model.put(LoginStrategy.ERROR_MESSAGE_KEY, SystemProperties.getProperty(loginErrorMessage));
137                                         final String redirectUrl = PortalApiProperties.getProperty(PortalApiConstants.ECOMP_REDIRECT_URL)
138                                                         + "?noUserError=Yes";
139                                         logger.debug(EELFLoggerDelegate.debugLogger, "singleSignOnLogin: user is null, redirect URL is {}",
140                                                         redirectUrl);
141                                         return new ModelAndView("redirect:" + redirectUrl);
142                                 } else {
143                                         // store the user's information in the session
144                                         String loginMethod;
145                                         if (null == authMech || "".equals(authMech) || "BOTH".equals(authMech)) {
146                                                 loginMethod = SystemProperties.getProperty(SystemProperties.LOGIN_METHOD_CSP);
147                                         } else if ("CSP".equals(authMech)) {
148                                                 loginMethod = SystemProperties.getProperty(SystemProperties.LOGIN_METHOD_CSP);
149                                         } else {
150                                                 loginMethod = SystemProperties.getProperty(SystemProperties.LOGIN_METHOD_WEB_JUNCTION);
151                                         }
152                                         UserUtils.setUserSession(request, commandBean.getUser(), commandBean.getMenu(),
153                                                         commandBean.getBusinessDirectMenu(), loginMethod, roleFunctionList);
154                                         initateSessionMgtHandler(request);
155                                         logger.debug(EELFLoggerDelegate.debugLogger,
156                                                         "singleSignOnLogin: create new user session for expired user {}; user {} exists in the system",
157                                                         userId, commandBean.getUser().getOrgUserId());
158                                         return new ModelAndView("redirect:" + forwardURL);
159                                 }
160                         } // user is null or session is null
161                         else {
162                                 // both user and session are non-null.
163                                 logger.info(EELFLoggerDelegate.debugLogger, "singleSignOnLogin: redirecting to the forwardURL {}",
164                                                 forwardURL);
165                                 validateDomain(forwardURL);
166                                 return new ModelAndView("redirect:" + forwardURL);
167                         }
168
169                 } else {
170                         /*
171                          * Login cookie not found, or redirect-to-portal parameter was found.
172                          * 
173                          * Redirect the user to the portal with a suitable return URL. The forwardURL
174                          * parameter that arrives as a parameter is a partial (not absolute) request
175                          * path for a page in the application. The challenge here is to compute the
176                          * correct absolute path for the original request so the portal can redirect the
177                          * user back to the right place. If the application sits behind WebJunction, or
178                          * if separate FE-BE hosts are used, then the URL yielded by the request has a
179                          * host name that is not reachable by the user.
180                          */
181                         String returnToAppUrl;
182                         if (SystemProperties.containsProperty(SystemProperties.APP_BASE_URL)) {
183                                 // New feature as of 1610, release 3.3.3:
184                                 // application can publish a base URL in system.properties
185                                 String appUrl = SystemProperties.getProperty(SystemProperties.APP_BASE_URL);
186                                 returnToAppUrl = appUrl + (appUrl.endsWith("/") ? "" : "/") + forwardURL;
187                                 validateDomain(returnToAppUrl);
188                                 logger.debug(EELFLoggerDelegate.debugLogger,
189                                                 "singleSignOnLogin: using app base URL {} and redirectURL {}", appUrl, returnToAppUrl);
190                         } else {
191                                 // Be backward compatible with applications that don't need this
192                                 // feature.
193                                 // This is the controller for the single_signon.htm page, so the
194                                 // replace
195                                 // should always find the specified token.
196                                 returnToAppUrl = request.getRequestURL().toString().replace("single_signon.htm",
197                                                 forwardURL);
198                                 validateDomain(returnToAppUrl);
199                                 logger.debug(EELFLoggerDelegate.debugLogger, "singleSignOnLogin: computed redirectURL {}",
200                                                 returnToAppUrl);
201                         }
202                         final String encodedReturnToAppUrl = URLEncoder.encode(returnToAppUrl, "UTF-8");
203                         // Also send the application's UEB key so Portal can block URL
204                         // reflection attacks.
205                         final String uebAppKey = PortalApiProperties.getProperty(PortalApiConstants.UEB_APP_KEY);
206                         final String url = PortalApiProperties.getProperty(PortalApiConstants.ECOMP_REDIRECT_URL);
207                         final String portalUrl = url.substring(0, url.lastIndexOf('/')) + "/process_csp";
208                         final String redirectUrl = portalUrl + "?uebAppKey=" + uebAppKey + "&redirectUrl=" + encodedReturnToAppUrl;
209                         logger.debug(EELFLoggerDelegate.debugLogger, "singleSignOnLogin: portal-bound redirect URL is {}",
210                                         redirectUrl);
211                         // this line may not be necessary but jsessionid coockie is not getting created in all cases;
212                         // so force the cookie creation
213                         request.getSession(true);
214                         
215                         return new ModelAndView("redirect:" + redirectUrl);
216                 }
217         }
218
219         private void validateDomain(String forwardURL) throws MalformedURLException {
220                 if (StringUtils.isNotBlank(forwardURL)) {
221                         String hostName = new URL(forwardURL).getHost();
222                         if (StringUtils.isNotBlank(hostName) && !hostName.endsWith(SystemProperties.getProperty(SystemProperties.COOKIE_DOMAIN))) {
223                                 logger.debug(EELFLoggerDelegate.debugLogger, "singleSignOnLogin: accessing Unauthorized url",
224                                                 hostName);
225                                 throw new SecurityException("accessing Unauthorized url : " + hostName);
226                         }
227                 }
228         }
229
230         protected void initateSessionMgtHandler(HttpServletRequest request) {
231                 String portalJSessionId = getPortalJSessionId(request);
232                 String jSessionId = getJessionId(request);
233                 PortalTimeoutHandler.sessionCreated(portalJSessionId, jSessionId, AppUtils.getSession(request));
234         }
235
236         public boolean isLoginCookieExist(HttpServletRequest request) {
237                 Cookie ep = WebUtils.getCookie(request, LoginStrategy.EP_SERVICE);
238                 return ep != null;
239         }
240
241         public String getPortalJSessionId(HttpServletRequest request) {
242                 Cookie ep = WebUtils.getCookie(request, LoginStrategy.EP_SERVICE);
243                 return ep.getValue();
244         }
245
246         public String getJessionId(HttpServletRequest request) {
247                 return request.getSession().getId();
248         }
249
250         @Override
251         public String getViewName() {
252                 return viewName;
253         }
254
255         @Override
256         public void setViewName(String viewName) {
257                 this.viewName = viewName;
258         }
259
260         public LoginService getLoginService() {
261                 return loginService;
262         }
263
264         public void setLoginService(LoginService loginService) {
265                 this.loginService = loginService;
266         }
267
268 }