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