/** * ============LICENSE_START=================================================== * SPARKY (AAI UI service) * ============================================================================ * Copyright © 2017 AT&T Intellectual Property. * Copyright © 2017 Amdocs * All rights reserved. * ============================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============LICENSE_END===================================================== * * ECOMP and OpenECOMP are trademarks * and service marks of AT&T Intellectual Property. */ package org.openecomp.sparky.security.filter; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.InetAddress; import java.net.URLDecoder; import java.net.URLEncoder; import java.net.UnknownHostException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Properties; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.openecomp.cl.api.Logger; import org.openecomp.cl.eelf.LoggerFactory; import org.openecomp.sparky.logging.AaiUiMsgs; import org.openecomp.sparky.util.NodeUtils; import org.openecomp.sparky.viewandinspect.config.TierSupportUiConstants; import org.openecomp.cl.mdc.MdcContext; // import esGateKeeper.esGateKeeper; /** * Redirects to the AT&T global login page if the user is not authenticated.
* Filter properties need to be configured in: csp-cookie-filter.properties */ public class CspCookieFilter implements Filter { /** Redirect URL for the login page. */ private String globalLoginUrl; /** Application identifier. */ private String applicationId; /** Gatekeeper environment setting (development or production). */ private String gateKeeperEnvironment; private static final String FILTER_PARAMETER_CONFIG = "config"; private static final String PROPERTY_GLOBAL_LOGIN_URL = "global.login.url"; private static final String PROPERTY_APPLICATION_ID = "application.id"; private static final String PROPERTY_GATEKEEPER_ENVIRONMENT = "gatekeeper.environment"; // valid open redirect domains private List redirectDomains = new ArrayList<>(); private static final String PROPERTY_REDIRECT_DOMAINS = "redirect-domain"; /** Needed by esGateKeeper, does not accept any other value. */ private static final String GATEKEEPER_ACCOUNT_NAME = "CSP"; private static final Logger LOG = LoggerFactory.getInstance().getLogger(CspCookieFilter.class); /* (non-Javadoc) * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) */ @Override public void init(FilterConfig filterConfig) throws ServletException { String txnID = NodeUtils.getRandomTxnId(); MdcContext.initialize(txnID, "CspCookieFilter", "", "Init", ""); try { setConfigurationProperties(filterConfig); } catch (IOException exc) { LOG.error(AaiUiMsgs.ERROR_CSP_CONFIG_FILE); throw new ServletException(exc); } } /* (non-Javadoc) * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain) */ @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; Cookie[] cookies = request.getCookies(); if ((cookies == null) || (cookies.length == 0)) { doLogin(request, response); return; } /* * String attEsSec = getSecurityCookie(cookies); * * if (attESSec == null || attESSec.length() == 0) { doLogin(request, response); return; } * * String attESSecUnEncrypted = esGateKeeper.esGateKeeper(attESSec, GATEKEEPER_ACCOUNT_NAME, * gateKeeperEnvironment); if (attESSecUnEncrypted == null) { doLogin(request, response); } else * { */ // LOG.info("User has valid cookie"); chain.doFilter(request, response); // } } /* (non-Javadoc) * @see javax.servlet.Filter#destroy() */ @Override public void destroy() {} /** * Sets all required properties needed by this filter. * * @param filterConfig the filter configuration defined in the application web.xml * @throws IOException if the properties failed to load. */ private void setConfigurationProperties(FilterConfig filterConfig) throws IOException { InputStream inputStream = new FileInputStream(TierSupportUiConstants.STATIC_CONFIG_APP_LOCATION + filterConfig.getInitParameter(FILTER_PARAMETER_CONFIG)); Properties cspProperties = new Properties(); cspProperties.load(inputStream); globalLoginUrl = cspProperties.getProperty(PROPERTY_GLOBAL_LOGIN_URL); applicationId = cspProperties.getProperty(PROPERTY_APPLICATION_ID); gateKeeperEnvironment = cspProperties.getProperty(PROPERTY_GATEKEEPER_ENVIRONMENT); redirectDomains = Arrays.asList(cspProperties.getProperty(PROPERTY_REDIRECT_DOMAINS).split(",")); } /** * Returns the attESSec cookie if found in the client. * * @param cookies the cookies available in the client * @return the attESSec authentication cookie generated by the login page. */ private String getSecurityCookie(Cookie[] cookies) { String attEsSec = null; for (int i = 0; i < cookies.length; i++) { Cookie thisCookie = cookies[i]; String cookieName = thisCookie.getName(); if ("attESSec".equals(cookieName)) { attEsSec = thisCookie.getValue(); break; } } return attEsSec; } /** * Redirects to the AT&T global login page. If this is an AJAX request it returns an unauthorized * HTTP error in the response. * * @param request the filter request object * @param response the filter response object * @throws IOException if there is an error setting the error response */ private void doLogin(HttpServletRequest request, HttpServletResponse response) throws IOException { if (isAjaxRequest(request)) { response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "User is not authorized. Please login to application"); } else { // Fix for Safari 7.0.2 onwards to avoid login page cache response.addHeader("Cache-Control", "no-cache, no-store"); String redirectURL = createRedirectUrl(request); if (this.isValidRedirectURL(redirectURL)){ response.sendRedirect(redirectURL); LOG.debug(AaiUiMsgs.VALID_REDIRECT_URL, redirectURL); } else{ response.sendError(400, "Bad redirect URL: " + redirectURL); LOG.error(AaiUiMsgs.INVALID_REDIRECT_URL, redirectURL); } } } /** * Checks if a redirect url is valid * @param url URL to validate * @return true if URL is a valid redirect URL, false otherwise */ private boolean isValidRedirectURL (String url){ String redirectTo = url.substring(url.indexOf("?retURL=")+ "?retURL=".length()); try { redirectTo = URLDecoder.decode(redirectTo, StandardCharsets.UTF_8.toString()); } catch (UnsupportedEncodingException e) { LOG.error(AaiUiMsgs.UNSUPPORTED_URL_ENCODING, e.getLocalizedMessage()); return false; } for (String domain: this.redirectDomains){ if (redirectTo.endsWith(domain)) return true; } return false; } /** * Returns true if the request is an AJAX request. * * @param request the filter request object * @return true if the request is an AJAX request. */ private boolean isAjaxRequest(HttpServletRequest request) { String headerValue = request.getHeader("X-Requested-With"); if ("XMLHttpRequest".equals(headerValue)) { return true; } return false; } /** * Returns the redirection URL to the AT&T Global login page. * * @param request the request * @return the string * @throws UnsupportedEncodingException the unsupported encoding exception */ private String createRedirectUrl(HttpServletRequest request) throws UnsupportedEncodingException { String returnUrl = getReturnUrl(request); return globalLoginUrl + "?retURL=" + returnUrl + "&sysName=" + applicationId; } /** * Gets the URL encoded return URL. * * @param request the HTTP request * @return an encoded URL to return to following login * @throws UnsupportedEncodingException the unsupported encoding exception */ private String getReturnUrl(HttpServletRequest request) throws UnsupportedEncodingException { StringBuffer retUrl = request.getRequestURL(); String urlParams = request.getQueryString(); if (urlParams != null) { retUrl.append("?" + urlParams); } return URLEncoder.encode(retUrl.toString(), StandardCharsets.UTF_8.toString()); } }