c566e14169dce1cbce6d3fff5dcdc65b75414f92
[aai/sparky-be.git] / src / main / java / org / onap / aai / sparky / security / filter / LoginFilter.java
1 /**
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
4  * ================================================================================
5  * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * Copyright © 2017-2018 Amdocs
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *       http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21 package org.onap.aai.sparky.security.filter;
22
23 import java.io.IOException;
24
25 import javax.servlet.Filter;
26 import javax.servlet.FilterChain;
27 import javax.servlet.FilterConfig;
28 import javax.servlet.ServletException;
29 import javax.servlet.ServletRequest;
30 import javax.servlet.ServletResponse;
31 import javax.servlet.http.Cookie;
32 import javax.servlet.http.HttpServletRequest;
33 import javax.servlet.http.HttpServletResponse;
34 import javax.servlet.http.HttpSession;
35 import javax.ws.rs.core.HttpHeaders;
36
37 import org.onap.aai.cl.api.Logger;
38 import org.onap.aai.cl.eelf.LoggerFactory;
39 import org.onap.aai.sparky.logging.AaiUiMsgs;
40 import org.onap.aai.sparky.security.EcompSso;
41 import org.onap.aai.sparky.security.portal.config.PortalAuthenticationConfig;
42 import org.openecomp.portalsdk.core.onboarding.listener.PortalTimeoutHandler;
43 import org.openecomp.portalsdk.core.onboarding.util.PortalApiConstants;
44 import org.openecomp.portalsdk.core.onboarding.util.PortalApiProperties;
45 import org.openecomp.portalsdk.core.onboarding.util.SSOUtil;
46
47 /**
48  * This filter checks every request for proper ECOMP Portal single sign on initialization. The
49  * possible paths and actions:
50  * <OL>
51  * <LI>User starts at an app page via a bookmark. No ECOMP portal cookie is set. Redirect there to
52  * get one; then continue as below.
53  * <LI>User starts at ECOMP Portal and goes to app. Alternately, the user's session times out and
54  * the user hits refresh. The ECOMP Portal cookie is set, but there is no valid session. Create one
55  * and publish info.
56  * <LI>User has valid ECOMP Portal cookie and session. Reset the max idle in that session.
57  * </OL>
58  * <P>
59  * Notes:
60  * <UL>
61  * <LI>Portal Session should be up prior to App Session</LI>
62  * <LI>If App Session Expires or if EPService cookie is unavailable, we need to redirect to Portal.
63  * <LI>Method {@link #initiateSessionMgtHandler(HttpServletRequest)} should be called for Session
64  * management when the initial session is created
65  * <LI>While redirecting, the cookie "redirectUrl" should also be set so that Portal knows where to
66  * forward the request to once the Portal Session is created and EPService cookie is set.
67  * <LI>Method {@link #resetSessionMaxIdleTimeOut(HttpServletRequest)} should be called for every
68  * request to reset the MaxInactiveInterval to the right value.
69  * </UL>
70  * <P>
71  * This filter incorporates most features of the SDK application's SessionTimeoutInterceptor and
72  * SingleSignOnController classes
73  */
74 public class LoginFilter implements Filter {
75
76   private static final Logger LOG = LoggerFactory.getInstance().getLogger(LoginFilter.class);
77
78   @Override
79   public void init(FilterConfig filterConfig) throws ServletException {
80     // Validate that app has provided useful portal properties
81     if (PortalApiProperties.getProperty(PortalApiConstants.ECOMP_REDIRECT_URL) == null) {
82       throw new ServletException("Failed to find URL in portal.properties");
83     }
84
85     PortalAuthenticationConfig appProperties;
86     try {
87       appProperties = PortalAuthenticationConfig.getInstance();
88     } catch (Exception ex) {
89       throw new ServletException("Failed to get properties", ex);
90     }
91
92     String restUser = appProperties.getUsername();
93     String restPassword = appProperties.getPassword();
94     if (restUser == null || restPassword == null) {
95       throw new ServletException("Failed to find user and/or password from properties");
96     }
97   }
98
99   @Override
100   public void destroy() {
101     // No resources to release
102   }
103
104   /*
105    * (non-Javadoc)
106    *
107    * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse,
108    * javax.servlet.FilterChain)
109    */
110   @Override
111   public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
112       throws ServletException, IOException {
113     HttpServletRequest request = (HttpServletRequest) req;
114     HttpServletResponse response = (HttpServletResponse) res;
115
116     // Choose authentication appropriate for the request.
117     final String restApiURI = request.getContextPath() + PortalApiConstants.API_PREFIX;
118     if (request.getRequestURI().startsWith(restApiURI)) {
119       // REST servlet checks credentials
120       LOG.debug(AaiUiMsgs.LOGIN_FILTER_DEBUG, "doFilter: delegating auth to REST servlet for request " + request.getRequestURI());
121       chain.doFilter(request, response);
122     } else {
123       // All other requests require ECOMP Portal authentication
124       if (EcompSso.validateEcompSso(request) == null) {
125         String redirectURL, logMessage;
126         if (request.getRequestURI().contains("/editAttributes")) {
127           // If request is for Edit Attributes UI, redirect straight to the application.
128           String appPath = request.getRequestURI().substring(request.getContextPath().length() + 1)
129               + (request.getQueryString() != null ? ("?" + request.getQueryString()) : "");
130           redirectURL = SSOUtil.getECOMPSSORedirectURL(request, response, appPath);
131           logMessage = "Unauthenticated Edit Attributes UI login attempt.";
132         } else {
133           // Redirect to Portal UI
134           redirectURL = PortalApiProperties.getProperty(PortalApiConstants.ECOMP_REDIRECT_URL);
135           logMessage = "Unauthorized login attempt.";
136         }
137         
138         LOG.debug(AaiUiMsgs.LOGIN_FILTER_DEBUG,
139             logMessage + 
140             " | Remote IP: " + request.getRemoteAddr() + 
141             " | User agent: " + request.getHeader(HttpHeaders.USER_AGENT) + 
142             " | Request URL: " + request.getRequestURL() +
143             " | Redirecting to: " + redirectURL); 
144         
145         response.sendRedirect(redirectURL);
146       } else {
147         HttpSession session = request.getSession(false);
148         if (session == null) {
149           // New session
150           session = request.getSession(true);
151           LOG.debug(AaiUiMsgs.LOGIN_FILTER_DEBUG, "doFilter: created new session " + session.getId());
152           initiateSessionMgtHandler(request);
153         } else {
154           // Existing session
155           LOG.debug(AaiUiMsgs.LOGIN_FILTER_DEBUG, "doFilter: resetting idle in existing session " + session.getId());
156           resetSessionMaxIdleTimeOut(request);
157         }
158         // Pass request back down the filter chain
159         chain.doFilter(request, response);
160       }
161     }
162   }
163
164   /**
165    * Publishes information about the session.
166    *
167    * @param request
168    */
169   private void initiateSessionMgtHandler(HttpServletRequest request) {
170     String portalJSessionId = getPortalJSessionId(request);
171     String jSessionId = getJessionId(request);
172     storeMaxInactiveTime(request);
173     PortalTimeoutHandler.sessionCreated(portalJSessionId, jSessionId, request.getSession(false));
174   }
175
176   /**
177    * Gets the ECOMP Portal service cookie value.
178    *
179    * @param request
180    * @return Cookie value, or null if not found.
181    */
182   private String getPortalJSessionId(HttpServletRequest request) {
183     Cookie ep = EcompSso.getCookie(request, EcompSso.EP_SERVICE);
184     return ep == null ? null : ep.getValue();
185   }
186
187   /**
188    * Gets the container session ID.
189    *
190    * @param request
191    * @return Session ID, or null if no session.
192    */
193   private String getJessionId(HttpServletRequest request) {
194     HttpSession session = request.getSession();
195     return session == null ? null : session.getId();
196   }
197
198   /**
199    * Sets the global session's max idle time to the session's max inactive interval.
200    *
201    * @param request
202    */
203   private void storeMaxInactiveTime(HttpServletRequest request) {
204     HttpSession session = request.getSession(false);
205     if (session != null
206         && session.getAttribute(PortalApiConstants.GLOBAL_SESSION_MAX_IDLE_TIME) == null) {
207       session.setAttribute(PortalApiConstants.GLOBAL_SESSION_MAX_IDLE_TIME,
208           session.getMaxInactiveInterval());
209     }
210   }
211
212   /**
213    * Sets the session's max inactive interval.
214    *
215    * @param request
216    */
217   private void resetSessionMaxIdleTimeOut(HttpServletRequest request) {
218     try {
219       HttpSession session = request.getSession(false);
220       if (session != null) {
221         final Object maxIdleAttribute = session
222             .getAttribute(PortalApiConstants.GLOBAL_SESSION_MAX_IDLE_TIME);
223         if (maxIdleAttribute != null) {
224           session.setMaxInactiveInterval(Integer.parseInt(maxIdleAttribute.toString()));
225         }
226       }
227     } catch (Exception e) {
228       LOG.info(AaiUiMsgs.LOGIN_FILTER_INFO, "resetSessionMaxIdleTimeOut: failed to set session max inactive interval - " + e.getLocalizedMessage());
229     }
230   }
231
232 }