2 * ============LICENSE_START===================================================
3 * SPARKY (AAI UI service)
4 * ============================================================================
5 * Copyright © 2017 AT&T Intellectual Property.
6 * Copyright © 2017 Amdocs
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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=====================================================
22 * ECOMP and OpenECOMP are trademarks
23 * and service marks of AT&T Intellectual Property.
25 package org.onap.aai.sparky.security.filter;
27 import java.io.FileInputStream;
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.io.UnsupportedEncodingException;
31 import java.net.URLDecoder;
32 import java.net.URLEncoder;
33 import java.nio.charset.StandardCharsets;
34 import java.util.ArrayList;
35 import java.util.Arrays;
36 import java.util.List;
37 import java.util.Properties;
39 import javax.servlet.Filter;
40 import javax.servlet.FilterChain;
41 import javax.servlet.FilterConfig;
42 import javax.servlet.ServletException;
43 import javax.servlet.ServletRequest;
44 import javax.servlet.ServletResponse;
45 import javax.servlet.http.Cookie;
46 import javax.servlet.http.HttpServletRequest;
47 import javax.servlet.http.HttpServletResponse;
49 import org.onap.aai.cl.api.Logger;
50 import org.onap.aai.cl.eelf.LoggerFactory;
51 import org.onap.aai.cl.mdc.MdcContext;
52 import org.onap.aai.sparky.logging.AaiUiMsgs;
53 import org.onap.aai.sparky.util.NodeUtils;
54 import org.onap.aai.sparky.viewandinspect.config.SparkyConstants;
56 // import esGateKeeper.esGateKeeper;
59 * Redirects to the AT&T global login page if the user is not authenticated.<br>
60 * Filter properties need to be configured in: csp-cookie-filter.properties
62 public class CspCookieFilter implements Filter {
64 /** Redirect URL for the login page. */
65 private String globalLoginUrl;
67 /** Application identifier. */
68 private String applicationId;
70 /** Gatekeeper environment setting (development or production). */
71 private String gateKeeperEnvironment;
73 private static final String FILTER_PARAMETER_CONFIG = "config";
74 private static final String PROPERTY_GLOBAL_LOGIN_URL = "global.login.url";
75 private static final String PROPERTY_APPLICATION_ID = "application.id";
76 private static final String PROPERTY_GATEKEEPER_ENVIRONMENT = "gatekeeper.environment";
77 // valid open redirect domains
78 private List<String> redirectDomains = new ArrayList<>();
79 private static final String PROPERTY_REDIRECT_DOMAINS = "redirect-domain";
81 /** Needed by esGateKeeper, does not accept any other value. */
82 private static final String GATEKEEPER_ACCOUNT_NAME = "CSP";
84 private static final Logger LOG = LoggerFactory.getInstance().getLogger(CspCookieFilter.class);
88 * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
91 public void init(FilterConfig filterConfig) throws ServletException {
92 String txnID = NodeUtils.getRandomTxnId();
93 MdcContext.initialize(txnID, "CspCookieFilter", "", "Init", "");
96 setConfigurationProperties(filterConfig);
97 } catch (IOException exc) {
98 LOG.error(AaiUiMsgs.ERROR_CSP_CONFIG_FILE);
99 throw new ServletException(exc);
105 * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
108 public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
109 throws IOException, ServletException {
110 HttpServletRequest request = (HttpServletRequest) req;
111 HttpServletResponse response = (HttpServletResponse) res;
113 Cookie[] cookies = request.getCookies();
114 if ((cookies == null) || (cookies.length == 0)) {
115 doLogin(request, response);
120 * String attEsSec = getSecurityCookie(cookies);
122 * if (attESSec == null || attESSec.length() == 0) { doLogin(request, response); return; }
124 * String attESSecUnEncrypted = esGateKeeper.esGateKeeper(attESSec, GATEKEEPER_ACCOUNT_NAME,
125 * gateKeeperEnvironment); if (attESSecUnEncrypted == null) { doLogin(request, response); } else
128 // LOG.info("User has valid cookie");
129 chain.doFilter(request, response);
135 * @see javax.servlet.Filter#destroy()
138 public void destroy() {}
141 * Sets all required properties needed by this filter.
143 * @param filterConfig the filter configuration defined in the application web.xml
144 * @throws IOException if the properties failed to load.
146 private void setConfigurationProperties(FilterConfig filterConfig) throws IOException {
147 InputStream inputStream = new FileInputStream(SparkyConstants.CONFIG_HOME
148 + filterConfig.getInitParameter(FILTER_PARAMETER_CONFIG));
149 Properties cspProperties = new Properties();
150 cspProperties.load(inputStream);
151 globalLoginUrl = cspProperties.getProperty(PROPERTY_GLOBAL_LOGIN_URL);
152 applicationId = cspProperties.getProperty(PROPERTY_APPLICATION_ID);
153 gateKeeperEnvironment = cspProperties.getProperty(PROPERTY_GATEKEEPER_ENVIRONMENT);
154 redirectDomains = Arrays.asList(cspProperties.getProperty(PROPERTY_REDIRECT_DOMAINS).split(","));
158 * Returns the attESSec cookie if found in the client.
160 * @param cookies the cookies available in the client
161 * @return the attESSec authentication cookie generated by the login page.
163 private String getSecurityCookie(Cookie[] cookies) {
164 String attEsSec = null;
165 for (int i = 0; i < cookies.length; i++) {
166 Cookie thisCookie = cookies[i];
167 String cookieName = thisCookie.getName();
169 if ("attESSec".equals(cookieName)) {
170 attEsSec = thisCookie.getValue();
178 * Redirects to the AT&T global login page. If this is an AJAX request it returns an unauthorized
179 * HTTP error in the response.
181 * @param request the filter request object
182 * @param response the filter response object
183 * @throws IOException if there is an error setting the error response
185 private void doLogin(HttpServletRequest request, HttpServletResponse response)
187 if (isAjaxRequest(request)) {
188 response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
189 "User is not authorized. Please login to application");
191 // Fix for Safari 7.0.2 onwards to avoid login page cache
192 response.addHeader("Cache-Control", "no-cache, no-store");
193 String redirectURL = createRedirectUrl(request);
194 if (this.isValidRedirectURL(redirectURL)){
195 response.sendRedirect(redirectURL);
196 LOG.debug(AaiUiMsgs.VALID_REDIRECT_URL, redirectURL);
198 response.sendError(400, "Bad redirect URL");
199 LOG.error(AaiUiMsgs.INVALID_REDIRECT_URL, redirectURL);
205 * Checks if a redirect url is valid
206 * @param url URL to validate
207 * @return true if URL is a valid redirect URL, false otherwise
209 private boolean isValidRedirectURL (String url){
210 String redirectTo = url.substring(url.indexOf("?retURL=")+ "?retURL=".length());
212 redirectTo = URLDecoder.decode(redirectTo, StandardCharsets.UTF_8.toString());
213 } catch (UnsupportedEncodingException e) {
214 LOG.error(AaiUiMsgs.UNSUPPORTED_URL_ENCODING, e.getLocalizedMessage());
217 for (String domain: this.redirectDomains){
218 if (redirectTo.endsWith(domain))
226 * Returns <code>true</code> if the request is an AJAX request.
228 * @param request the filter request object
229 * @return <code>true</code> if the request is an AJAX request.
231 private boolean isAjaxRequest(HttpServletRequest request) {
232 String headerValue = request.getHeader("X-Requested-With");
233 if ("XMLHttpRequest".equals(headerValue)) {
240 * Returns the redirection URL to the AT&T Global login page.
242 * @param request the request
244 * @throws UnsupportedEncodingException the unsupported encoding exception
246 private String createRedirectUrl(HttpServletRequest request) throws UnsupportedEncodingException {
247 String returnUrl = getReturnUrl(request);
249 return globalLoginUrl + "?retURL=" + returnUrl + "&sysName=" + applicationId;
253 * Gets the URL encoded return URL.
255 * @param request the HTTP request
256 * @return an encoded URL to return to following login
257 * @throws UnsupportedEncodingException the unsupported encoding exception
259 private String getReturnUrl(HttpServletRequest request) throws UnsupportedEncodingException {
260 StringBuffer retUrl = request.getRequestURL();
261 String urlParams = request.getQueryString();
262 if (urlParams != null) {
263 retUrl.append("?" + urlParams);
265 return URLEncoder.encode(retUrl.toString(), StandardCharsets.UTF_8.toString());