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