d04acc8df762e78fb42f1e94399e4977a9a42ad1
[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  * 
37  */
38 package org.onap.portalapp.controller.core;
39
40 import java.io.IOException;
41 import java.net.MalformedURLException;
42 import java.net.URL;
43 import java.net.URLDecoder;
44 import java.net.URLEncoder;
45 import java.util.HashMap;
46 import java.util.List;
47 import java.util.Map;
48
49 import javax.servlet.http.Cookie;
50 import javax.servlet.http.HttpServletRequest;
51 import javax.servlet.http.HttpSession;
52
53 import org.apache.commons.lang.StringUtils;
54 import org.onap.portalapp.model.EPServiceCookie;
55 import org.onap.portalsdk.core.auth.LoginStrategy;
56 import org.onap.portalsdk.core.command.LoginBean;
57 import org.onap.portalsdk.core.controller.UnRestrictedBaseController;
58 import org.onap.portalsdk.core.domain.RoleFunction;
59 import org.onap.portalsdk.core.domain.User;
60 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
61 import org.onap.portalsdk.core.menu.MenuProperties;
62 import org.onap.portalsdk.core.onboarding.listener.PortalTimeoutHandler;
63 import org.onap.portalsdk.core.onboarding.util.PortalApiConstants;
64 import org.onap.portalsdk.core.onboarding.util.PortalApiProperties;
65 import org.onap.portalsdk.core.service.LoginService;
66 import org.onap.portalsdk.core.service.RoleService;
67 import org.onap.portalsdk.core.util.SystemProperties;
68 import org.onap.portalsdk.core.web.support.AppUtils;
69 import org.onap.portalsdk.core.web.support.UserUtils;
70 import org.springframework.beans.factory.annotation.Autowired;
71 import org.springframework.stereotype.Controller;
72 import org.springframework.web.bind.annotation.RequestMapping;
73 import org.springframework.web.bind.annotation.RequestMethod;
74 import org.springframework.web.client.RestTemplate;
75 import org.springframework.web.servlet.ModelAndView;
76 import org.springframework.web.util.WebUtils;
77
78 import com.fasterxml.jackson.core.JsonParseException;
79 import com.fasterxml.jackson.databind.JsonMappingException;
80 import com.fasterxml.jackson.databind.ObjectMapper;
81
82 @Controller
83 @RequestMapping("/")
84 public class SingleSignOnController extends UnRestrictedBaseController {
85
86         private static final EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(SingleSignOnController.class);
87
88         @Autowired
89         private LoginService loginService;
90
91         @Autowired
92         private LoginStrategy loginStrategy;
93
94         @Autowired
95         private RoleService roleService;
96         
97         
98         private RestTemplate restTemplate = new RestTemplate();
99
100         private String viewName;
101         private String welcomeView;
102
103         public String getWelcomeView() {
104                 return welcomeView;
105         }
106
107         public void setWelcomeView(String welcomeView) {
108                 this.welcomeView = welcomeView;
109         }
110
111         /**
112          * Handles requests directed to the single sign-on page by the session timeout
113          * interceptor.
114          * 
115          * @param request
116          * @return Redirect to an appropriate address
117          * @throws Exception
118          */
119         @RequestMapping(value = { "/single_signon.htm" }, method = RequestMethod.GET)
120         public ModelAndView singleSignOnLogin(HttpServletRequest request) throws Exception {
121
122                 Map<String, String> model = new HashMap<>();
123                 HashMap<String, String> additionalParamsMap = new HashMap<>();
124                 LoginBean commandBean = new LoginBean();
125
126                 // SessionTimeoutInterceptor sets these parameters
127                 String forwardURL = URLDecoder.decode(request.getParameter("forwardURL"), "UTF-8");
128                 String redirectToPortal = request.getParameter("redirectToPortal");
129
130                 if (isLoginCookieExist(request) && redirectToPortal == null) {
131                         HttpSession session = AppUtils.getSession(request);
132                         User user = UserUtils.getUserSession(request);
133                         if (session == null || user == null) {
134
135                                 final String authMech = SystemProperties.getProperty(SystemProperties.AUTHENTICATION_MECHANISM);
136                                 String userId = loginStrategy.getUserId(request);
137                                 commandBean.setUserid(userId);
138                                 commandBean = getLoginService().findUser(commandBean,
139                                                 (String) request.getAttribute(MenuProperties.MENU_PROPERTIES_FILENAME_KEY),
140                                                 additionalParamsMap);
141                                 List<RoleFunction> roleFunctionList = roleService.getRoleFunctions(userId);
142                                 if (commandBean.getUser() == null) {
143                                         String loginErrorMessage = (commandBean.getLoginErrorMessage() != null)
144                                                         ? commandBean.getLoginErrorMessage()
145                                                         : SystemProperties.MESSAGE_KEY_LOGIN_ERROR_USER_NOT_FOUND;
146                                         model.put(LoginStrategy.ERROR_MESSAGE_KEY, SystemProperties.getProperty(loginErrorMessage));
147                                         final String redirectUrl = PortalApiProperties.getProperty(PortalApiConstants.ECOMP_REDIRECT_URL)
148                                                         + "?noUserError=Yes";
149                                         logger.debug(EELFLoggerDelegate.debugLogger, "singleSignOnLogin: user is null, redirect URL is {}",
150                                                         redirectUrl);
151                                         return new ModelAndView("redirect:" + redirectUrl);
152                                 } else {
153                                         // store the user's information in the session
154                                         String loginMethod;
155                                         if (null == authMech || "".equals(authMech) || "BOTH".equals(authMech)) {
156                                                 loginMethod = SystemProperties.getProperty(SystemProperties.LOGIN_METHOD_CSP);
157                                         } else if ("CSP".equals(authMech)) {
158                                                 loginMethod = SystemProperties.getProperty(SystemProperties.LOGIN_METHOD_CSP);
159                                         } else {
160                                                 loginMethod = SystemProperties.getProperty(SystemProperties.LOGIN_METHOD_WEB_JUNCTION);
161                                         }
162                                         UserUtils.setUserSession(request, commandBean.getUser(), commandBean.getMenu(),
163                                                         commandBean.getBusinessDirectMenu(), loginMethod, roleFunctionList);
164                                         initateSessionMgtHandler(request);
165                                         logger.debug(EELFLoggerDelegate.debugLogger,
166                                                         "singleSignOnLogin: create new user session for expired user {}; user {} exists in the system",
167                                                         userId, commandBean.getUser().getOrgUserId());
168                                         return new ModelAndView("redirect:" + forwardURL);
169                                 }
170                         } // user is null or session is null
171                         else {
172                                 // both user and session are non-null.
173                                 logger.info(EELFLoggerDelegate.debugLogger, "singleSignOnLogin: redirecting to the forwardURL {}",
174                                                 forwardURL);
175                                 validateDomain(forwardURL);
176                                 return new ModelAndView("redirect:" + forwardURL);
177                         }
178
179                 } else {
180                         /*
181                          * Login cookie not found, or redirect-to-portal parameter was found.
182                          * 
183                          * Redirect the user to the portal with a suitable return URL. The forwardURL
184                          * parameter that arrives as a parameter is a partial (not absolute) request
185                          * path for a page in the application. The challenge here is to compute the
186                          * correct absolute path for the original request so the portal can redirect the
187                          * user back to the right place. If the application sits behind WebJunction, or
188                          * if separate FE-BE hosts are used, then the URL yielded by the request has a
189                          * host name that is not reachable by the user.
190                          */
191                         String returnToAppUrl;
192                         if (SystemProperties.containsProperty(SystemProperties.APP_BASE_URL)) {
193                                 // New feature as of 1610, release 3.3.3:
194                                 // application can publish a base URL in system.properties
195                                 String appUrl = SystemProperties.getProperty(SystemProperties.APP_BASE_URL);
196                                 returnToAppUrl = appUrl + (appUrl.endsWith("/") ? "" : "/") + forwardURL;
197                                 validateDomain(returnToAppUrl);
198                                 logger.debug(EELFLoggerDelegate.debugLogger,
199                                                 "singleSignOnLogin: using app base URL {} and redirectURL {}", appUrl, returnToAppUrl);
200                         } else {
201                                 // Be backward compatible with applications that don't need this
202                                 // feature.
203                                 // This is the controller for the single_signon.htm page, so the
204                                 // replace
205                                 // should always find the specified token.
206                                 returnToAppUrl = request.getRequestURL().toString().replace("single_signon.htm",
207                                                 forwardURL);
208                                 validateDomain(returnToAppUrl);
209                                 logger.debug(EELFLoggerDelegate.debugLogger, "singleSignOnLogin: computed redirectURL {}",
210                                                 returnToAppUrl);
211                         }
212                         final String encodedReturnToAppUrl = URLEncoder.encode(returnToAppUrl, "UTF-8");
213                         // Also send the application's UEB key so Portal can block URL
214                         // reflection attacks.
215                         final String uebAppKey = PortalApiProperties.getProperty(PortalApiConstants.UEB_APP_KEY);
216                         final String url = PortalApiProperties.getProperty(PortalApiConstants.ECOMP_REDIRECT_URL);
217                         final String portalUrl = url.substring(0, url.lastIndexOf('/')) + "/process_csp";
218                         final String redirectUrl = portalUrl + "?uebAppKey=" + uebAppKey + "&redirectUrl=" + encodedReturnToAppUrl;
219                         logger.debug(EELFLoggerDelegate.debugLogger, "singleSignOnLogin: portal-bound redirect URL is {}",
220                                         redirectUrl);
221                         // this line may not be necessary but jsessionid coockie is not getting created in all cases;
222                         // so force the cookie creation
223                         request.getSession(true);
224                         
225                         return new ModelAndView("redirect:" + redirectUrl);
226                 }
227         }
228
229         private void validateDomain(String forwardURL) throws MalformedURLException {
230                 if (StringUtils.isNotBlank(forwardURL)) {
231                         String hostName = new URL(forwardURL).getHost();
232                         if (StringUtils.isNotBlank(hostName) && !hostName.endsWith(SystemProperties.getProperty(SystemProperties.COOKIE_DOMAIN))) {
233                                 logger.debug(EELFLoggerDelegate.debugLogger, "singleSignOnLogin: accessing Unauthorized url",
234                                                 hostName);
235                                 throw new SecurityException("accessing Unauthorized url : " + hostName);
236                         }
237                 }
238         }
239
240         protected void initateSessionMgtHandler(HttpServletRequest request) {
241                 String portalJSessionId = getPortalJSessionId(request);
242                 String jSessionId = getJessionId(request);
243                 PortalTimeoutHandler.sessionCreated(portalJSessionId, jSessionId, AppUtils.getSession(request));
244         }
245
246         public boolean isLoginCookieExist(HttpServletRequest request) throws JsonParseException, JsonMappingException, IOException {
247                 Cookie ep = WebUtils.getCookie(request, LoginStrategy.EP_SERVICE);
248                 if(ep!=null) {
249                         return validateEPServiceCookie(ep.getValue());
250                 }
251                 return false;
252         }
253         
254         //This method is validating EPService cookie in portal 
255         public boolean validateEPServiceCookie(String cookieValue) throws JsonParseException, JsonMappingException, IOException{
256            Boolean result = false;
257            try{
258                     //Create json Request for REST call
259                     final String uri = PortalApiProperties.getProperty(PortalApiConstants.ECOMP_REST_URL);
260                         ObjectMapper mapper = new ObjectMapper();
261                         Map<String,String> valueMap = mapper.readValue(URLDecoder.decode(cookieValue, "UTF-8"),HashMap.class);
262                  
263                     EPServiceCookie epServiceCookie = new EPServiceCookie();
264                     epServiceCookie.setValue(valueMap);
265                     //Call portal service to validate
266                     result = restTemplate.postForObject( uri+"/v3/validateCookie", epServiceCookie, Boolean.class);
267                     logger.info(EELFLoggerDelegate.applicationLogger,"Epservice cookie validation result:: "+result);
268             }catch(Exception e){
269                 logger.error(EELFLoggerDelegate.errorLogger,"Error in calling service :: "+e.getMessage());
270             }
271          
272             return result;
273         }
274
275         public String getPortalJSessionId(HttpServletRequest request) {
276                 Cookie ep = WebUtils.getCookie(request, LoginStrategy.EP_SERVICE);
277                 return ep.getValue();
278         }
279
280         public String getJessionId(HttpServletRequest request) {
281                 return request.getSession().getId();
282         }
283
284         @Override
285         public String getViewName() {
286                 return viewName;
287         }
288
289         @Override
290         public void setViewName(String viewName) {
291                 this.viewName = viewName;
292         }
293
294         public LoginService getLoginService() {
295                 return loginService;
296         }
297
298         public void setLoginService(LoginService loginService) {
299                 this.loginService = loginService;
300         }
301
302 }