/*
 * 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.ServiceType;
import org.apache.knox.gateway.services.GatewayServices;
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 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, 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 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() { }
}
