/*
 * 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.pac4j.filter;

import org.apache.commons.lang3.StringUtils;
import org.apache.knox.gateway.i18n.messages.MessagesFactory;
import org.apache.knox.gateway.pac4j.Pac4jMessages;
import org.apache.knox.gateway.pac4j.config.ClientConfigurationDecorator;
import org.apache.knox.gateway.pac4j.config.Pac4jClientConfigurationDecorator;
import org.apache.knox.gateway.pac4j.session.KnoxSessionStore;
import org.apache.knox.gateway.services.GatewayServices;
import org.apache.knox.gateway.services.ServiceType;
import org.apache.knox.gateway.services.security.AliasService;
import org.apache.knox.gateway.services.security.AliasServiceException;
import org.apache.knox.gateway.services.security.CryptoService;
import org.apache.knox.gateway.services.security.KeystoreService;
import org.apache.knox.gateway.services.security.MasterService;
import org.pac4j.config.client.PropertiesConfigFactory;
import org.pac4j.config.client.PropertiesConstants;
import org.pac4j.core.client.Client;
import org.pac4j.core.config.Config;
import org.pac4j.core.context.session.JEESessionStore;
import org.pac4j.core.context.session.SessionStore;
import org.pac4j.core.util.CommonHelper;
import org.pac4j.http.client.indirect.IndirectBasicAuthClient;
import org.pac4j.http.credentials.authenticator.test.SimpleTestUsernamePasswordAuthenticator;
import org.pac4j.jee.filter.CallbackFilter;
import org.pac4j.jee.filter.SecurityFilter;
import org.pac4j.oidc.client.AzureAdClient;
import org.pac4j.saml.client.SAML2Client;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>This is the main filter for the pac4j provider. The pac4j provider module heavily relies on the j2e-pac4j library (https://github.com/pac4j/j2e-pac4j).</p>
 * <p>This filter dispatches the HTTP calls between the j2e-pac4j filters:</p>
 * <ul>
 *     <li>to the {@link CallbackFilter} if the <code>client_name</code> parameter exists: it finishes the authentication process</li>
 *     <li>to the {@link SecurityFilter} otherwise: it starts the authentication process (redirection to the identity provider) if the user is not authenticated</li>
 * </ul>
 * <p>It uses the {@link KnoxSessionStore} to manage session data. The generated cookies are defined on a domain name
 * which can be configured via the domain suffix parameter: <code>pac4j.cookie.domain.suffix</code>.</p>
 * <p>The callback url must be defined to the current protected url (KnoxSSO service for example) via the parameter: <code>pac4j.callbackUrl</code>.</p>
 *
 * @since 0.8.0
 */
public class Pac4jDispatcherFilter implements Filter {
  private static final String ALIAS_PREFIX = "${ALIAS=";
  private static Pac4jMessages log = MessagesFactory.get(Pac4jMessages.class);

  private static final ClientConfigurationDecorator PAC4J_CLIENT_CONFIGURATION_DECORATOR = new Pac4jClientConfigurationDecorator();

  public static final String TEST_BASIC_AUTH = "testBasicAuth";

  public static final String PAC4J_CALLBACK_URL = "pac4j.callbackUrl";

  public static final String PAC4J_CALLBACK_PARAMETER = "pac4jCallback";

  public static final String PAC4J_OICD_TYPE_AZURE = "azure";

  public static final String URL_PATH_SEPARATOR = "/";

  private static final String PAC4J_COOKIE_DOMAIN_SUFFIX_PARAM = "pac4j.cookie.domain.suffix";

  private static final String PAC4J_CONFIG = "pac4j.config";

  private static final String PAC4J_SESSION_STORE = "pac4j.session.store";

  private static final String PAC4J_CLIENT_NAME_PARAM = "clientName";

  private static final String PAC4J_OIDC_TYPE = "oidc.type";

  private CallbackFilter callbackFilter;

  private SecurityFilter securityFilter;
  private MasterService masterService;
  private KeystoreService keystoreService;
  private AliasService aliasService;

  @Override
  public void init( FilterConfig filterConfig ) throws ServletException {
    // JWT service
    final ServletContext context = filterConfig.getServletContext();
    CryptoService cryptoService = null;
    String clusterName = null;
    if (context != null) {
      GatewayServices services = (GatewayServices) context.getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
      clusterName = (String) context.getAttribute(GatewayServices.GATEWAY_CLUSTER_ATTRIBUTE);
      if (services != null) {
        keystoreService = services.getService(ServiceType.KEYSTORE_SERVICE);
        cryptoService = services.getService(ServiceType.CRYPTO_SERVICE);
        aliasService = services.getService(ServiceType.ALIAS_SERVICE);
        masterService = services.getService(ServiceType.MASTER_SERVICE);
      }
    }
    // crypto service, alias service and cluster name are mandatory
    if (cryptoService == null || aliasService == null || clusterName == null) {
      log.cryptoServiceAndAliasServiceAndClusterNameRequired();
      throw new ServletException("The crypto service, alias service and cluster name are required.");
    }
    try {
      aliasService.getPasswordFromAliasForCluster(clusterName, KnoxSessionStore.PAC4J_PASSWORD, true);
    } catch (AliasServiceException e) {
      log.unableToGenerateAPasswordForEncryption(e);
      throw new ServletException("Unable to generate a password for encryption.");
    }

    // url to SSO authentication provider
    String pac4jCallbackUrl = filterConfig.getInitParameter(PAC4J_CALLBACK_URL);
    if (pac4jCallbackUrl == null) {
      log.ssoAuthenticationProviderUrlRequired();
      throw new ServletException("Required pac4j callback URL is missing.");
    }

    // client name from servlet parameter (mandatory)
    final String clientNameParameter = filterConfig.getInitParameter(PAC4J_CLIENT_NAME_PARAM);
    if (clientNameParameter == null) {
      log.clientNameParameterRequired();
      throw new ServletException("Required pac4j clientName parameter is missing.");
    }

    final String oidcType = filterConfig.getInitParameter(PAC4J_OIDC_TYPE);
    /*
       add the callback parameter to know it's a callback,
       Azure AD does not honor query param so we add callback param as path element.
    */
    if (AzureAdClient.class.getSimpleName().equals(clientNameParameter) || (
        !StringUtils.isBlank(oidcType) && PAC4J_OICD_TYPE_AZURE
            .equals(oidcType))) {
      pac4jCallbackUrl = pac4jCallbackUrl + URL_PATH_SEPARATOR + PAC4J_CALLBACK_PARAMETER;
    } else {
      pac4jCallbackUrl = CommonHelper.addParameter(pac4jCallbackUrl, PAC4J_CALLBACK_PARAMETER, "true");
    }

    final Config config;
    final String clientName;

    if (TEST_BASIC_AUTH.equalsIgnoreCase(clientNameParameter)) {
      // test configuration
      final IndirectBasicAuthClient indirectBasicAuthClient = new IndirectBasicAuthClient(new SimpleTestUsernamePasswordAuthenticator());
      indirectBasicAuthClient.setRealmName("Knox TEST");
      config = new Config(pac4jCallbackUrl, indirectBasicAuthClient);
      clientName = "IndirectBasicAuthClient";
    } else {
      // get clients from the init parameters
      final Map<String, String> properties = new HashMap<>();
      final Enumeration<String> names = filterConfig.getInitParameterNames();
      addDefaultConfig(clientNameParameter, properties);
      while (names.hasMoreElements()) {
        final String key = names.nextElement();
        properties.put(key, resolveAlias(clusterName, key, filterConfig.getInitParameter(key)));
      }
      final PropertiesConfigFactory propertiesConfigFactory = new PropertiesConfigFactory(pac4jCallbackUrl, properties);
      config = propertiesConfigFactory.build();
      final List<Client> clients = config.getClients().getClients();
      if (clients == null || clients.isEmpty()) {
        log.atLeastOnePac4jClientMustBeDefined();
        throw new ServletException("At least one pac4j client must be defined.");
      }

      clientName = CommonHelper.isBlank(clientNameParameter) ? clients.get(0).getName() : clientNameParameter;

      //decorating client configuration (if needed)
      PAC4J_CLIENT_CONFIGURATION_DECORATOR.decorateClients(clients, properties);
    }


    callbackFilter = new CallbackFilter();
    callbackFilter.init(filterConfig);
    callbackFilter.setConfigOnly(config);
    securityFilter = new SecurityFilter();
    securityFilter.setClients(clientName);
    securityFilter.setConfigOnly(config);

    final String domainSuffix = filterConfig.getInitParameter(PAC4J_COOKIE_DOMAIN_SUFFIX_PARAM);
    final String sessionStoreVar = filterConfig.getInitParameter(PAC4J_SESSION_STORE);

    SessionStore sessionStore;

    if(!StringUtils.isBlank(sessionStoreVar) && JEESessionStore.class.getName().contains(sessionStoreVar) ) {
      sessionStore = new JEESessionStore();
    } else {
      sessionStore = new KnoxSessionStore(cryptoService, clusterName, domainSuffix);
    }

    config.setSessionStore(sessionStore);

  }

  private String resolveAlias(String clusterName, String key, String value) throws ServletException {
    if (value.startsWith(ALIAS_PREFIX) && value.endsWith("}")) {
      String alias = value.substring(ALIAS_PREFIX.length(), value.length() - 1);
      try {
        return new String(aliasService.getPasswordFromAliasForCluster(clusterName, alias));
      } catch (AliasServiceException e) {
        throw new ServletException("Unable to retrieve alias for config: " + key, e);
      }
    }
    return value;
  }

  private void addDefaultConfig(String clientNameParameter, Map<String, String> properties) {
    // add default saml params
    if (clientNameParameter.contains(SAML2Client.class.getSimpleName())) {
      properties.put(PropertiesConstants.SAML_KEYSTORE_PATH,
          keystoreService.getKeystorePath());

      // check for provisioned alias for keystore password
      char[] giksp = null;
      try {
        giksp = aliasService.getGatewayIdentityKeystorePassword();
      } catch (AliasServiceException e) {
        log.noKeystorePasswordProvisioned(e);
      }
      if (giksp == null) {
        // no alias provisioned then use the master
        giksp = masterService.getMasterSecret();
      }
      properties.put(PropertiesConstants.SAML_KEYSTORE_PASSWORD, new String(giksp));

      // check for provisioned alias for private key
      char[] gip = null;
      try {
        gip = aliasService.getGatewayIdentityPassphrase();
      }
      catch(AliasServiceException ase) {
        log.noPrivateKeyPasshraseProvisioned(ase);
      }
      if (gip == null) {
        // no alias provisioned then use the master
        gip = masterService.getMasterSecret();
      }
      properties.put(PropertiesConstants.SAML_PRIVATE_KEY_PASSWORD, new String(gip));
    }
  }

  @Override
  public void doFilter( ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

    final HttpServletRequest request = (HttpServletRequest) servletRequest;
    request.setAttribute(PAC4J_CONFIG, securityFilter.getSharedConfig());

    // it's a callback from an identity provider
    if (request.getParameter(PAC4J_CALLBACK_PARAMETER) != null || (
        request.getContextPath() != null && request.getRequestURI()
            .contains(PAC4J_CALLBACK_PARAMETER))) {
      // apply CallbackFilter
      callbackFilter.doFilter(servletRequest, servletResponse, filterChain);
    } else {
      // otherwise just apply security and requires authentication
      // apply RequiresAuthenticationFilter
      securityFilter.doFilter(servletRequest, servletResponse, filterChain);
    }
  }

  @Override
  public void destroy() { }
}
