summaryrefslogtreecommitdiffstats
path: root/security-util-lib/src/main/java/org/onap/sdc/security/filters/SessionValidationFilter.java
diff options
context:
space:
mode:
Diffstat (limited to 'security-util-lib/src/main/java/org/onap/sdc/security/filters/SessionValidationFilter.java')
-rw-r--r--security-util-lib/src/main/java/org/onap/sdc/security/filters/SessionValidationFilter.java217
1 files changed, 217 insertions, 0 deletions
diff --git a/security-util-lib/src/main/java/org/onap/sdc/security/filters/SessionValidationFilter.java b/security-util-lib/src/main/java/org/onap/sdc/security/filters/SessionValidationFilter.java
new file mode 100644
index 0000000..87780ae
--- /dev/null
+++ b/security-util-lib/src/main/java/org/onap/sdc/security/filters/SessionValidationFilter.java
@@ -0,0 +1,217 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. 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=========================================================
+ */
+
+package org.onap.sdc.security.filters;
+
+import org.onap.sdc.security.*;
+import org.onap.sdc.security.logging.elements.ErrorLogOptionalData;
+import org.onap.sdc.security.logging.elements.LogFieldsMdcHandler;
+import org.onap.sdc.security.logging.enums.EcompLoggerErrorCode;
+import org.onap.sdc.security.logging.wrappers.Logger;
+
+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 java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+public abstract class SessionValidationFilter implements Filter {
+ private static final Logger log = Logger.getLogger(SessionValidationFilter.class.getName());
+ private ISessionValidationFilterConfiguration filterConfiguration;
+ private List<String> excludedUrls;
+
+ public abstract ISessionValidationFilterConfiguration getFilterConfiguration();
+ protected abstract Cookie addRoleToCookie(Cookie updatedCookie) throws RedirectException;
+ protected abstract void authorizeUserOnSessionExpiration(AuthenticationCookie authenticationCookie, Cookie[] cookies) throws RedirectException;
+ protected abstract void handleRedirectException(HttpServletResponse httpResponse) throws IOException;
+
+ @Override
+ public final void init(FilterConfig filterConfig) {
+ filterConfiguration = getFilterConfiguration();
+ excludedUrls = filterConfiguration.getExcludedUrls();
+ }
+
+ @Override
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
+ final HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
+ final HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
+
+ long starTime = System.nanoTime();
+ if (log.isDebugEnabled()) {
+ log.debug("SessionValidationFilter: Validation started, received request with URL {}", httpRequest.getRequestURL());
+ }
+
+ try {
+ if (isValidationRequired(servletRequest, servletResponse, filterChain, httpRequest)){
+ List<Cookie> cookies = extractAuthenticationCookies(httpRequest.getCookies());
+ if (log.isDebugEnabled()) {
+ log.debug("doFilter: the cookies we received from extractAuthenticationCookies, before processRequest: {}", cookies);
+ }
+
+ Cookie extractedCookie = cookies.get(0);
+ processRequest(httpRequest, extractedCookie);
+
+ // response processing
+ if (log.isDebugEnabled()) {
+ log.debug("SessionValidationFilter: Cookie from request {} is valid, passing request to session extension ...", httpRequest.getRequestURL());
+ }
+ Cookie updatedCookie = processResponse(extractedCookie);
+
+ cleanResponseFromLeftoverCookies(httpResponse, cookies);
+
+ if (log.isDebugEnabled()) {
+ log.debug("SessionValidationFilter: request {} passed all validations, passing request to endpoint ...", httpRequest.getRequestURL());
+ }
+ httpResponse.addCookie(updatedCookie);
+ filterChain.doFilter(servletRequest, httpResponse);
+ }
+ } catch (RedirectException e) {
+ log.error(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR, LogFieldsMdcHandler.getInstance().getServiceName(), new ErrorLogOptionalData(),"Exception is thrown while authenticating cookie: {}", e.getMessage());
+ handleRedirectException(httpResponse);
+ }
+ long durationSec = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - starTime);
+ long durationMil = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - starTime);
+ if (log.isDebugEnabled()) {
+ log.debug("SessionValidationFilter: Validation ended, running time for URL {} is: {} seconds {} milliseconds", httpRequest.getPathInfo(), durationSec, durationMil);
+ }
+ }
+
+
+ private boolean isValidationRequired(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain, HttpServletRequest httpRequest) throws IOException, ServletException, RedirectException {
+ if (isUrlFromWhiteList(httpRequest)) {
+ log.debug("SessionValidationFilter: URL {} excluded from access validation , passing request to endpoint ... ", httpRequest.getRequestURL());
+ filterChain.doFilter(servletRequest, servletResponse);
+ return false;
+
+ } else if (!isCookiePresent(httpRequest.getCookies())) {
+ //redirect to portal app
+ log.debug("SessionValidationFilter: Cookie from request {} is not valid, redirecting request to portal", httpRequest.getRequestURL());
+ throw new RedirectException(String.format("Cookie from request %s is not valid", httpRequest.getRequestURL() ));
+ }
+ return true;
+ }
+
+ private void processRequest(HttpServletRequest httpRequest, Cookie cookie) throws RedirectException {
+ AuthenticationCookie authenticationCookie;
+ try {
+ authenticationCookie = AuthenticationCookieUtils.getAuthenticationCookie(cookie, filterConfiguration);
+ }
+ catch (CipherUtilException e) {
+ log.error(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR, LogFieldsMdcHandler.getInstance().getServiceName(), new ErrorLogOptionalData(),"SessionValidationFilter: Cookie decryption error : {}", e.getMessage());
+ throw new RedirectException("Cookie decryption error");
+ }
+ if (AuthenticationCookieUtils.isSessionExpired(authenticationCookie, filterConfiguration)) {
+ if (log.isDebugEnabled()) {
+ log.debug("SessionValidationFilter:session is expired for URL {}", httpRequest.getRequestURL());
+ }
+ authorizeUserOnSessionExpiration(authenticationCookie, httpRequest.getCookies());
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("SessionValidationFilter: Role is valid");
+ }
+ }
+
+ private Cookie processResponse(Cookie cookie) throws IOException, RedirectException {
+ Cookie updatedCookie;
+ try {
+ updatedCookie = AuthenticationCookieUtils.updateSessionTime(cookie, filterConfiguration);
+ } catch (CipherUtilException e) {
+ log.error(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR, LogFieldsMdcHandler.getInstance().getServiceName(), new ErrorLogOptionalData(),"SessionValidationFilter: Cookie cipher error {}", e.getMessage());
+ if (log.isDebugEnabled()) {
+ log.debug("SessionValidationFilter: Cookie cipher error : {}", e.getMessage(), e);
+ }
+ throw new RedirectException(e);
+ }
+ return addRoleToCookie(updatedCookie);
+ }
+
+ private boolean isCookiePresent(Cookie[] cookies) {
+ if (cookies == null) {
+ return false;
+ }
+ String actualCookieName = filterConfiguration.getCookieName();
+ boolean isPresent = Arrays.stream(cookies).anyMatch(c -> isCookieNameMatch(actualCookieName, c));
+ if (!isPresent) {
+ log.error(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR, LogFieldsMdcHandler.getInstance().getServiceName(), new ErrorLogOptionalData(),"SessionValidationFilter: Session Validation Cookie missing ");
+ return false;
+ }
+ return true;
+ }
+
+ private List<Cookie> extractAuthenticationCookies(Cookie[] cookies) {
+ String actualCookieName = filterConfiguration.getCookieName();
+ if (log.isDebugEnabled()) {
+ Arrays.stream(cookies).forEach(c->log.debug("SessionValidationFilter: Cookie name {}", c.getName()));
+ log.debug("SessionValidationFilter: Extracting authentication cookies, {} cookies in request", cookies.length);
+ }
+ List<Cookie> authenticationCookies = Arrays.stream(cookies).filter(c -> isCookieNameMatch(actualCookieName, c)).collect(Collectors.toList());
+ if (log.isDebugEnabled()) {
+ log.debug("SessionValidationFilter: Extracted {} authentication cookies from request", authenticationCookies.size());
+ }
+ if( authenticationCookies.size() > 1 && log.isDebugEnabled()) {
+ authenticationCookies.forEach( cookie -> log.debug("SessionValidationFilter: Multiple cookies found cookie name, {} cookie value {}", cookie.getName(), cookie.getValue()));
+ }
+ return authenticationCookies;
+ }
+
+
+ // use contains for matching due issue with ecomp portal ( change cookie name, add prefix ), temp solution
+ private boolean isCookieNameMatch(String actualCookieName, Cookie c) {
+ return c.getName().contains(actualCookieName);
+ }
+
+ private boolean isUrlFromWhiteList(HttpServletRequest httpRequest) {
+ if (httpRequest.getPathInfo() == null){
+ final String servletPath = httpRequest.getServletPath().toLowerCase();
+ log.debug("SessionValidationFilter: pathInfo is null, trying to check by servlet path white list validation -> ServletPath: {} ", servletPath);
+ return excludedUrls.stream().
+ anyMatch(servletPath::matches);
+ }
+ String pathInfo = httpRequest.getPathInfo().toLowerCase();
+ log.debug("SessionValidationFilter: white list validation -> PathInfo: {} ", pathInfo);
+ return excludedUrls.stream().
+ anyMatch(pathInfo::matches);
+ }
+
+ private void cleanResponseFromLeftoverCookies(HttpServletResponse httpResponse, List<Cookie> cookiesList) {
+ for (Cookie cookie:cookiesList){
+ Cookie cleanCookie = AuthenticationCookieUtils.createUpdatedCookie(cookie, null, filterConfiguration);
+ cleanCookie.setMaxAge(0);
+ if (log.isDebugEnabled()) {
+ log.debug("SessionValidationFilter Cleaning Cookie cookie name: {} added to response", cleanCookie.getName());
+ }
+ httpResponse.addCookie(cleanCookie);
+ }
+ }
+
+ @Override
+ public void destroy() {
+
+ }
+}