Update license and poms
[aai/sparky-be.git] / sparkybe-onap-service / src / main / java / org / onap / aai / sparky / security / filter / CspCookieFilter.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.FileInputStream;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.UnsupportedEncodingException;
27 import java.net.URLDecoder;
28 import java.net.URLEncoder;
29 import java.nio.charset.StandardCharsets;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 import java.util.List;
33 import java.util.Properties;
34
35 import javax.servlet.Filter;
36 import javax.servlet.FilterChain;
37 import javax.servlet.FilterConfig;
38 import javax.servlet.ServletException;
39 import javax.servlet.ServletRequest;
40 import javax.servlet.ServletResponse;
41 import javax.servlet.http.Cookie;
42 import javax.servlet.http.HttpServletRequest;
43 import javax.servlet.http.HttpServletResponse;
44
45 import org.onap.aai.cl.api.Logger;
46 import org.onap.aai.cl.eelf.LoggerFactory;
47 import org.onap.aai.cl.mdc.MdcContext;
48 import org.onap.aai.sparky.logging.AaiUiMsgs;
49 import org.onap.aai.sparky.util.NodeUtils;
50 import org.onap.aai.sparky.viewandinspect.config.SparkyConstants;
51
52 // import esGateKeeper.esGateKeeper;
53
54 /**
55  * Redirects to the AT&T global login page if the user is not authenticated.<br>
56  * Filter properties need to be configured in: csp-cookie-filter.properties
57  */
58 public class CspCookieFilter implements Filter {
59
60   /** Redirect URL for the login page. */
61   private String globalLoginUrl;
62
63   /** Application identifier. */
64   private String applicationId;
65
66   /** Gatekeeper environment setting (development or production). */
67   private String gateKeeperEnvironment;
68
69   private static final String FILTER_PARAMETER_CONFIG = "config";
70   private static final String PROPERTY_GLOBAL_LOGIN_URL = "global.login.url";
71   private static final String PROPERTY_APPLICATION_ID = "application.id";
72   private static final String PROPERTY_GATEKEEPER_ENVIRONMENT = "gatekeeper.environment";
73   // valid open redirect domains
74   private List<String> redirectDomains = new ArrayList<>();
75   private static final String PROPERTY_REDIRECT_DOMAINS = "redirect-domain";
76
77   /** Needed by esGateKeeper, does not accept any other value. */
78   private static final String GATEKEEPER_ACCOUNT_NAME = "CSP";
79
80   private static final Logger LOG = LoggerFactory.getInstance().getLogger(CspCookieFilter.class);
81
82
83   /* (non-Javadoc)
84    * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
85    */
86   @Override
87   public void init(FilterConfig filterConfig) throws ServletException {
88         String txnID = NodeUtils.getRandomTxnId();
89         MdcContext.initialize(txnID, "CspCookieFilter", "", "Init", "");
90         
91         try {
92       setConfigurationProperties(filterConfig);
93     } catch (IOException exc) {
94       LOG.error(AaiUiMsgs.ERROR_CSP_CONFIG_FILE);
95       throw new ServletException(exc);
96     }
97   }
98
99
100   /* (non-Javadoc)
101    * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
102    */
103   @Override
104   public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
105       throws IOException, ServletException {
106     HttpServletRequest request = (HttpServletRequest) req;
107     HttpServletResponse response = (HttpServletResponse) res;
108
109     Cookie[] cookies = request.getCookies();
110     if ((cookies == null) || (cookies.length == 0)) {
111       doLogin(request, response);
112       return;
113     }
114
115     /*
116      * String attEsSec = getSecurityCookie(cookies);
117      * 
118      * if (attESSec == null || attESSec.length() == 0) { doLogin(request, response); return; }
119      * 
120      * String attESSecUnEncrypted = esGateKeeper.esGateKeeper(attESSec, GATEKEEPER_ACCOUNT_NAME,
121      * gateKeeperEnvironment); if (attESSecUnEncrypted == null) { doLogin(request, response); } else
122      * {
123      */
124     // LOG.info("User has valid cookie");
125     chain.doFilter(request, response);
126     // }
127   }
128
129
130   /* (non-Javadoc)
131    * @see javax.servlet.Filter#destroy()
132    */
133   @Override
134   public void destroy() {}
135
136   /**
137    * Sets all required properties needed by this filter.
138    *
139    * @param filterConfig the filter configuration defined in the application web.xml
140    * @throws IOException if the properties failed to load.
141    */
142   private void setConfigurationProperties(FilterConfig filterConfig) throws IOException {
143     InputStream inputStream = new FileInputStream(SparkyConstants.CONFIG_HOME
144         + filterConfig.getInitParameter(FILTER_PARAMETER_CONFIG));
145     Properties cspProperties = new Properties();
146     cspProperties.load(inputStream);
147     globalLoginUrl = cspProperties.getProperty(PROPERTY_GLOBAL_LOGIN_URL);
148     applicationId = cspProperties.getProperty(PROPERTY_APPLICATION_ID);
149     gateKeeperEnvironment = cspProperties.getProperty(PROPERTY_GATEKEEPER_ENVIRONMENT);
150     redirectDomains = Arrays.asList(cspProperties.getProperty(PROPERTY_REDIRECT_DOMAINS).split(","));
151   }
152
153   /**
154    * Returns the attESSec cookie if found in the client.
155    *
156    * @param cookies the cookies available in the client
157    * @return the attESSec authentication cookie generated by the login page.
158    */
159   private String getSecurityCookie(Cookie[] cookies) {
160     String attEsSec = null;
161     for (int i = 0; i < cookies.length; i++) {
162       Cookie thisCookie = cookies[i];
163       String cookieName = thisCookie.getName();
164
165       if ("attESSec".equals(cookieName)) {
166         attEsSec = thisCookie.getValue();
167         break;
168       }
169     }
170     return attEsSec;
171   }
172
173   /**
174    * Redirects to the AT&T global login page. If this is an AJAX request it returns an unauthorized
175    * HTTP error in the response.
176    *
177    * @param request the filter request object
178    * @param response the filter response object
179    * @throws IOException if there is an error setting the error response
180    */
181   private void doLogin(HttpServletRequest request, HttpServletResponse response)
182       throws IOException {
183     if (isAjaxRequest(request)) {
184       response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
185           "User is not authorized. Please login to application");
186     } else {
187       // Fix for Safari 7.0.2 onwards to avoid login page cache
188       response.addHeader("Cache-Control", "no-cache, no-store");
189       String redirectURL = createRedirectUrl(request);
190       if (this.isValidRedirectURL(redirectURL)){
191           response.sendRedirect(redirectURL);
192           LOG.debug(AaiUiMsgs.VALID_REDIRECT_URL, redirectURL);
193       } else{ 
194           response.sendError(400, "Bad redirect URL");
195           LOG.error(AaiUiMsgs.INVALID_REDIRECT_URL, redirectURL);
196       }
197     }
198   }
199   
200   /**
201    * Checks if a redirect url is valid
202    * @param url URL to validate
203    * @return true if URL is a valid redirect URL, false otherwise
204    */
205   private boolean isValidRedirectURL (String url){
206       String redirectTo = url.substring(url.indexOf("?retURL=")+ "?retURL=".length());
207       try {
208           redirectTo = URLDecoder.decode(redirectTo, StandardCharsets.UTF_8.toString());
209       } catch (UnsupportedEncodingException e) {
210           LOG.error(AaiUiMsgs.UNSUPPORTED_URL_ENCODING, e.getLocalizedMessage());
211           return false;
212       }
213       for (String domain: this.redirectDomains){
214           if (redirectTo.endsWith(domain))
215               return true;
216       }
217       return false;
218   }
219   
220
221   /**
222    * Returns <code>true</code> if the request is an AJAX request.
223    *
224    * @param request the filter request object
225    * @return <code>true</code> if the request is an AJAX request.
226    */
227   private boolean isAjaxRequest(HttpServletRequest request) {
228     String headerValue = request.getHeader("X-Requested-With");
229     if ("XMLHttpRequest".equals(headerValue)) {
230       return true;
231     }
232     return false;
233   }
234
235   /**
236    * Returns the redirection URL to the AT&T Global login page.
237    *
238    * @param request the request
239    * @return the string
240    * @throws UnsupportedEncodingException the unsupported encoding exception
241    */
242   private String createRedirectUrl(HttpServletRequest request) throws UnsupportedEncodingException {
243     String returnUrl = getReturnUrl(request);
244
245     return globalLoginUrl + "?retURL=" + returnUrl + "&sysName=" + applicationId;
246   }
247
248   /**
249    * Gets the URL encoded return URL.
250    *
251    * @param request the HTTP request
252    * @return an encoded URL to return to following login
253    * @throws UnsupportedEncodingException the unsupported encoding exception
254    */
255   private String getReturnUrl(HttpServletRequest request) throws UnsupportedEncodingException {
256     StringBuffer retUrl = request.getRequestURL();
257     String urlParams = request.getQueryString();
258     if (urlParams != null) {
259       retUrl.append("?" + urlParams);
260     }
261     return URLEncoder.encode(retUrl.toString(), StandardCharsets.UTF_8.toString());
262   }
263 }