/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */
package org.apache.knox.gateway.provider.federation.jwt.filter;

import org.apache.commons.lang3.StringUtils;
import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.i18n.messages.MessagesFactory;
import org.apache.knox.gateway.provider.federation.jwt.JWTMessages;
import org.apache.knox.gateway.security.PrimaryPrincipal;
import org.apache.knox.gateway.services.security.token.impl.JWT;
import org.apache.knox.gateway.services.security.token.impl.JWTToken;
import org.apache.knox.gateway.util.CertificateUtils;
import org.apache.knox.gateway.util.CookieUtils;
import org.eclipse.jetty.http.MimeTypes;

import javax.security.auth.Subject;
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.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;

public class SSOCookieFederationFilter extends AbstractJWTFilter {
  private static final JWTMessages LOGGER = MessagesFactory.get( JWTMessages.class );

  public static final String XHR_HEADER = "X-Requested-With";
  public static final String XHR_VALUE = "XMLHttpRequest";

  private static final String GATEWAY_PATH = "gateway.path";
  public static final String SSO_COOKIE_NAME = "sso.cookie.name";
  public static final String SSO_EXPECTED_AUDIENCES = "sso.expected.audiences";
  public static final String SSO_AUTHENTICATION_PROVIDER_URL = "sso.authentication.provider.url";
  public static final String SSO_VERIFICATION_PEM = "sso.token.verification.pem";
  public static final String X_FORWARDED_HOST = "X-Forwarded-Host";
  public static final String X_FORWARDED_PORT = "X-Forwarded-Port";
  public static final String X_FORWARDED_PROTO = "X-Forwarded-Proto";

  private static final String ORIGINAL_URL_QUERY_PARAM = "originalUrl=";
  private static final String DEFAULT_SSO_COOKIE_NAME = "hadoop-jwt";

  /* A semicolon separated list of paths that need to bypass authentication */
  private static final String SSO_UNAUTHENTICATED_PATHS_PARAM = "gateway.knox.sso.unauthenticated.path.list";
  private static final String DEFAULT_SSO_UNAUTHENTICATED_PATHS_PARAM = "favicon.ico";
  private String cookieName;
  private String authenticationProviderUrl;
  private String gatewayPath;
  private Set<String> unAuthenticatedPaths = new HashSet(20);

  @Override
  public void init( FilterConfig filterConfig ) throws ServletException {
    super.init(filterConfig);

    // configured cookieName
    cookieName = filterConfig.getInitParameter(SSO_COOKIE_NAME);
    if (cookieName == null) {
      cookieName = DEFAULT_SSO_COOKIE_NAME;
    }

    // expected audiences or null
    String expectedAudiences = filterConfig.getInitParameter(SSO_EXPECTED_AUDIENCES);
    if (expectedAudiences != null) {
      audiences = parseExpectedAudiences(expectedAudiences);
    }

    // url to SSO authentication provider
    authenticationProviderUrl = filterConfig.getInitParameter(SSO_AUTHENTICATION_PROVIDER_URL);
    if (authenticationProviderUrl == null) {
      LOGGER.missingAuthenticationProviderUrlConfiguration();
    }

    // token verification pem
    String verificationPEM = filterConfig.getInitParameter(SSO_VERIFICATION_PEM);
    // setup the public key of the token issuer for verification
    if (verificationPEM != null) {
      publicKey = CertificateUtils.parseRSAPublicKey(verificationPEM);
    }

    /* get unauthenticated paths list */
    String unAuthPathString = filterConfig.getInitParameter(SSO_UNAUTHENTICATED_PATHS_PARAM);
    /* if no list specified use default value */
    if (StringUtils.isBlank(unAuthPathString)) {
      unAuthPathString = DEFAULT_SSO_UNAUTHENTICATED_PATHS_PARAM;
    }

    final StringTokenizer st = new StringTokenizer(unAuthPathString, ";,");
    while (st.hasMoreTokens()) {
      unAuthenticatedPaths.add(st.nextToken());
    }

    // gateway path for deriving an idp url when missing
    setGatewayPath(filterConfig);

    configureExpectedParameters(filterConfig);
  }

  private void setGatewayPath(FilterConfig filterConfig) {
    gatewayPath = filterConfig.getInitParameter(GATEWAY_PATH);
    if (gatewayPath == null || gatewayPath.isEmpty()) {
      final GatewayConfig gatewayConfig = filterConfig.getServletContext() == null ? null
          : (GatewayConfig) filterConfig.getServletContext().getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE);
      if (gatewayConfig != null) {
        gatewayPath = gatewayConfig.getGatewayPath();
      }
    }
  }

  @Override
  public void destroy() {
  }

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse res = (HttpServletResponse) response;

    List<Cookie> ssoCookies = CookieUtils.getCookiesForName(req, cookieName);
    if (ssoCookies.isEmpty()) {
      /* check for unauthenticated paths to bypass */
      for (final String path : unAuthenticatedPaths) {
        if (req.getRequestURI().contains(path)) {
          /* This path is configured as an unauthenticated path let the request through */
          final Subject sub = new Subject();
          sub.getPrincipals().add(new PrimaryPrincipal("anonymous"));
          LOGGER.unauthenticatedPathBypass(path, req.getRequestURI());
          continueWithEstablishedSecurityContext(sub, req, res, chain);
        }
      }

      if ("OPTIONS".equals(req.getMethod())) {
        // CORS preflight requests to determine allowed origins and related config
        // must be able to continue without being redirected
        Subject sub = new Subject();
        sub.getPrincipals().add(new PrimaryPrincipal("anonymous"));
        continueWithEstablishedSecurityContext(sub, req, res, chain);
      } else {
        sendRedirectToLoginURL(req, res);
      }
    } else {
      for(Cookie ssoCookie : ssoCookies) {
        String wireToken = ssoCookie.getValue();
        try {
          JWT token = new JWTToken(wireToken);
          if (validateToken(req, res, chain, token)) {
            Subject subject = createSubjectFromToken(token);
            continueWithEstablishedSecurityContext(subject, req, res, chain);

            // we found a valid cookie we don't need to keep checking anymore
            return;
          }
        } catch (ParseException ignore) {
          // Ignore the error since cookie was invalid
          // Fall through to keep checking if there are more cookies
        }
      }

      // There were no valid cookies found so redirect to login url
      if(res != null && !res.isCommitted()) {
        sendRedirectToLoginURL(req, res);
      }
    }
  }

  private void sendRedirectToLoginURL(HttpServletRequest request, HttpServletResponse response)
      throws IOException {
    String loginURL = constructLoginURL(request);
    LOGGER.sendRedirectToLoginURL(loginURL);
    response.sendRedirect(loginURL);
  }

  @Override
  protected void handleValidationError(HttpServletRequest request, HttpServletResponse response,
                                       int status, String error) throws IOException {
    /* We don't need redirect if this is a XHR request */
    if (request.getHeader(XHR_HEADER) != null &&
            request.getHeader(XHR_HEADER).equalsIgnoreCase(XHR_VALUE)) {
      response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
      response.setContentType(MimeTypes.Type.TEXT_PLAIN.toString());
      if(error != null && !error.isEmpty()) {
        final byte[] data = error.getBytes(StandardCharsets.UTF_8);
        response.setContentLength(data.length);
        response.getOutputStream().write(data);
      }
    } else {
      String loginURL = constructLoginURL(request);
      response.sendRedirect(loginURL);
    }
  }

  /**
   * Create the URL to be used for authentication of the user in the absence of
   * a JWT token within the incoming request.
   *
   * @param request for getting the original request URL
   * @return url to use as login url for redirect
   */
  protected String constructLoginURL(HttpServletRequest request) {
    String delimiter = "?";
    if (authenticationProviderUrl == null) {
      authenticationProviderUrl = deriveDefaultAuthenticationProviderUrl(request);
    }
    if (authenticationProviderUrl.contains("?")) {
      delimiter = "&";
    }
    return authenticationProviderUrl + delimiter
        + ORIGINAL_URL_QUERY_PARAM
        + request.getRequestURL().append(getOriginalQueryString(request));
  }

  /**
   * Derive a provider URL from the request assuming that the
   * KnoxSSO endpoint is local to the endpoint serving this request.
   * @param request origin request
   * @return url that is based on KnoxSSO endpoint
   */
  public String deriveDefaultAuthenticationProviderUrl(HttpServletRequest request) {
    String scheme;
    String host;
    int port;
    if (!beingProxied(request)) {
      scheme = request.getScheme();
      host = request.getServerName();
      port = request.getServerPort();
    }
    else {
      scheme = request.getHeader(X_FORWARDED_PROTO);
      host = request.getHeader(X_FORWARDED_HOST);
      port = Integer.parseInt(request.getHeader(X_FORWARDED_PORT));
    }
    StringBuilder sb = new StringBuilder(scheme);
    sb.append("://").append(host);
    if (!host.contains(":")) {
      sb.append(':').append(port);
    }
    sb.append('/').append(gatewayPath).append("/knoxsso/api/v1/websso");

    return sb.toString();
  }

  private boolean beingProxied(HttpServletRequest request) {
    return (request.getHeader(X_FORWARDED_HOST) != null);
  }

  private String getOriginalQueryString(HttpServletRequest request) {
    String originalQueryString = request.getQueryString();
    return (originalQueryString == null) ? "" : "?" + originalQueryString;
  }
}
