/*
 * 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.solr.security;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.invoke.MethodHandles;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.solr.common.SolrException;
import org.apache.solr.common.util.Utils;
import org.jose4j.jwk.HttpsJwks;
import org.jose4j.jwk.JsonWebKey;
import org.jose4j.jwk.JsonWebKeySet;
import org.jose4j.lang.JoseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Holds information about an IdP (issuer), such as issuer ID, JWK url(s), keys etc
 */
public class JWTIssuerConfig {
  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
  static final String PARAM_ISS_NAME = "name";
  @Deprecated // Remove this option at some point
  static final String PARAM_JWK_URL = "jwkUrl";
  static final String PARAM_JWKS_URL = "jwksUrl";
  static final String PARAM_JWK = "jwk";
  static final String PARAM_ISSUER = "iss";
  static final String PARAM_AUDIENCE = "aud";
  static final String PARAM_WELL_KNOWN_URL = "wellKnownUrl";
  static final String PARAM_AUTHORIZATION_ENDPOINT = "authorizationEndpoint";
  static final String PARAM_CLIENT_ID = "clientId";

  private static HttpsJwksFactory httpsJwksFactory =
      new HttpsJwksFactory(3600, 5000);
  private String iss;
  private String aud;
  private JsonWebKeySet jsonWebKeySet;
  private String name;
  private List<String> jwksUrl;
  private List<HttpsJwks> httpsJwks;
  private String wellKnownUrl;
  private WellKnownDiscoveryConfig wellKnownDiscoveryConfig;
  private String clientId;
  private String authorizationEndpoint;
  
  public static boolean ALLOW_OUTBOUND_HTTP = Boolean.parseBoolean(System.getProperty("solr.auth.jwt.allowOutboundHttp", "false"));
  public static final String ALLOW_OUTBOUND_HTTP_ERR_MSG = "HTTPS required for IDP communication. Please use SSL or start your nodes with -Dsolr.auth.jwt.allowOutboundHttp=true to allow HTTP for test purposes.";

  /**
   * Create config for further configuration with setters, builder style.
   * Once all values are set, call {@link #init()} before further use
   *
   * @param name a unique name for this issuer
   */
  public JWTIssuerConfig(String name) {
    this.name = name;
  }

  /**
   * Initialize issuer config from a generic configuration map
   *
   * @param configMap map of configuration keys anv values
   */
  public JWTIssuerConfig(Map<String, Object> configMap) {
    parseConfigMap(configMap);
  }

  /**
   * Call this to validate and initialize an object which is populated with setters.
   * Init will fetch wellKnownUrl if relevant
   * @throws SolrException if issuer is missing
   */
  public void init() {
    if (!isValid()) {
      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Configuration is not valid");
    }
    if (wellKnownUrl != null) {
      wellKnownDiscoveryConfig = fetchWellKnown(wellKnownUrl);
      if (iss == null) {
        iss = wellKnownDiscoveryConfig.getIssuer();
      }
      if (jwksUrl == null) {
        jwksUrl = Collections.singletonList(wellKnownDiscoveryConfig.getJwksUrl());
      }
      if (authorizationEndpoint == null) {
        authorizationEndpoint = wellKnownDiscoveryConfig.getAuthorizationEndpoint();
      }
    }
    if (iss == null && usesHttpsJwk() && !JWTAuthPlugin.PRIMARY_ISSUER.equals(name)) {
      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Missing required config 'iss' for issuer " + getName());
    }
  }

  /**
   * Parses configuration for one IssuerConfig and sets all variables found
   * @throws SolrException if unknown parameter names found in config
   */
  protected void parseConfigMap(Map<String, Object> configMap) {
    HashMap<String, Object> conf = new HashMap<>(configMap); // Clone
    setName((String) conf.get(PARAM_ISS_NAME));
    setWellKnownUrl((String) conf.get(PARAM_WELL_KNOWN_URL));
    setIss((String) conf.get(PARAM_ISSUER));
    setClientId((String) conf.get(PARAM_CLIENT_ID));
    setAud((String) conf.get(PARAM_AUDIENCE));
    if (conf.get(PARAM_JWK_URL) != null) {
      log.warn("Configuration uses deprecated key {}. Please use {} instead", PARAM_JWK_URL, PARAM_JWKS_URL);
    }
    Object confJwksUrl = conf.get(PARAM_JWKS_URL) != null ? conf.get(PARAM_JWKS_URL) : conf.get(PARAM_JWK_URL);
    setJwksUrl(confJwksUrl);
    setJsonWebKeySet(conf.get(PARAM_JWK));
    setAuthorizationEndpoint((String) conf.get(PARAM_AUTHORIZATION_ENDPOINT));

    conf.remove(PARAM_WELL_KNOWN_URL);
    conf.remove(PARAM_ISSUER);
    conf.remove(PARAM_ISS_NAME);
    conf.remove(PARAM_CLIENT_ID);
    conf.remove(PARAM_AUDIENCE);
    conf.remove(PARAM_JWKS_URL);
    conf.remove(PARAM_JWK_URL);
    conf.remove(PARAM_JWK);
    conf.remove(PARAM_AUTHORIZATION_ENDPOINT);

    if (!conf.isEmpty()) {
      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Unknown configuration key " + conf.keySet() + " for issuer " + name);
    }
  }

  /**
   * Setter that takes a jwk config object, parses it into a {@link JsonWebKeySet} and sets it
   * @param jwksObject the config object to parse
   */
  @SuppressWarnings("unchecked")
  protected void setJsonWebKeySet(Object jwksObject) {
    try {
      if (jwksObject != null) {
        jsonWebKeySet = parseJwkSet((Map<String, Object>) jwksObject);
      }
    } catch (JoseException e) {
      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Failed parsing parameter 'jwk' for issuer " + getName(), e);
    }
  }

  @SuppressWarnings("unchecked")
  protected static JsonWebKeySet parseJwkSet(Map<String, Object> jwkObj) throws JoseException {
    JsonWebKeySet webKeySet = new JsonWebKeySet();
    if (jwkObj.containsKey("keys")) {
      List<Object> jwkList = (List<Object>) jwkObj.get("keys");
      for (Object jwkO : jwkList) {
        webKeySet.addJsonWebKey(JsonWebKey.Factory.newJwk((Map<String, Object>) jwkO));
      }
    } else {
      webKeySet = new JsonWebKeySet(JsonWebKey.Factory.newJwk(jwkObj));
    }
    return webKeySet;
  }

  private WellKnownDiscoveryConfig fetchWellKnown(String wellKnownUrl) {
    return WellKnownDiscoveryConfig.parse(wellKnownUrl);
  }

  public String getIss() {
    return iss;
  }

  public JWTIssuerConfig setIss(String iss) {
    this.iss = iss;
    return this;
  }

  public String getName() {
    return name;
  }

  public JWTIssuerConfig setName(String name) {
    this.name = name;
    return this;
  }

  public String getWellKnownUrl() {
    return wellKnownUrl;
  }

  public JWTIssuerConfig setWellKnownUrl(String wellKnownUrl) {
    this.wellKnownUrl = wellKnownUrl;
    return this;
  }

  public List<String> getJwksUrls() {
    return jwksUrl;
  }

  public JWTIssuerConfig setJwksUrl(List<String> jwksUrl) {
    this.jwksUrl = jwksUrl;
    return this;
  }

  /**
   * Setter that converts from String or List into a list
   * @param jwksUrlListOrString object that should be either string or list
   * @return this for builder pattern
   * @throws SolrException if wrong type
   */
  @SuppressWarnings("unchecked")
  public JWTIssuerConfig setJwksUrl(Object jwksUrlListOrString) {
    if (jwksUrlListOrString instanceof String)
      this.jwksUrl = Collections.singletonList((String) jwksUrlListOrString);
    else if (jwksUrlListOrString instanceof List)
      this.jwksUrl = (List<String>) jwksUrlListOrString;
    else if (jwksUrlListOrString != null)
      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Parameter " + PARAM_JWKS_URL + " must be either List or String");
    return this;
  }

  public List<HttpsJwks> getHttpsJwks() {
    if (httpsJwks == null) {
      httpsJwks = httpsJwksFactory.createList(getJwksUrls());
    }
    return httpsJwks;
  }

  /**
   * Set the factory to use when creating HttpsJwks objects
   * @param httpsJwksFactory factory with custom settings
   */
  public static void setHttpsJwksFactory(HttpsJwksFactory httpsJwksFactory) {
    JWTIssuerConfig.httpsJwksFactory = httpsJwksFactory;
  }

  public JsonWebKeySet getJsonWebKeySet() {
    return jsonWebKeySet;
  }

  public JWTIssuerConfig setJsonWebKeySet(JsonWebKeySet jsonWebKeySet) {
    this.jsonWebKeySet = jsonWebKeySet;
    return this;
  }

  /**
   * Check if the issuer is backed by HttpsJwk url(s)
   * @return true if keys are fetched over https
   */
  public boolean usesHttpsJwk() {
    return getJwksUrls() != null && !getJwksUrls().isEmpty();
  }

  public WellKnownDiscoveryConfig getWellKnownDiscoveryConfig() {
    return wellKnownDiscoveryConfig;
  }

  public String getAud() {
    return aud;
  }

  public JWTIssuerConfig setAud(String aud) {
    this.aud = aud;
    return this;
  }

  public String getClientId() {
    return clientId;
  }

  public JWTIssuerConfig setClientId(String clientId) {
    this.clientId = clientId;
    return this;
  }

  public String getAuthorizationEndpoint() {
    return authorizationEndpoint;
  }

  public JWTIssuerConfig setAuthorizationEndpoint(String authorizationEndpoint) {
    this.authorizationEndpoint = authorizationEndpoint;
    return this;
  }

  public Map<String,Object> asConfig() {
    HashMap<String,Object> config = new HashMap<>();
    putIfNotNull(config, PARAM_ISS_NAME, name);
    putIfNotNull(config, PARAM_ISSUER, iss);
    putIfNotNull(config, PARAM_AUDIENCE, aud);
    putIfNotNull(config, PARAM_JWKS_URL, jwksUrl);
    putIfNotNull(config, PARAM_WELL_KNOWN_URL, wellKnownUrl);
    putIfNotNull(config, PARAM_CLIENT_ID, clientId);
    putIfNotNull(config, PARAM_AUTHORIZATION_ENDPOINT, authorizationEndpoint);
    if (jsonWebKeySet != null) {
      putIfNotNull(config, PARAM_JWK, jsonWebKeySet.getJsonWebKeys());
    }
    return config;
  }

  private void putIfNotNull(HashMap<String, Object> config, String paramName, Object value) {
    if (value != null) {
      config.put(paramName, value);
    }
  }

  /**
   * Validates that this config has a name and either jwksUrl, wellkKownUrl or jwk
   * @return true if a configuration is found and is valid, otherwise false
   * @throws SolrException if configuration is present but wrong
   */
  public boolean isValid() {
    int jwkConfigured = wellKnownUrl != null ? 1 : 0;
    jwkConfigured += jwksUrl != null ? 2 : 0;
    jwkConfigured += jsonWebKeySet != null ? 2 : 0;
    if (jwkConfigured > 3) {
      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "JWTAuthPlugin needs to configure exactly one of " +
          PARAM_WELL_KNOWN_URL + ", " + PARAM_JWKS_URL + " and " + PARAM_JWK);
    }
    if (jwkConfigured > 0 && name == null) {
      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
          "Parameter 'name' is required for issuer configurations");
    }
    return jwkConfigured > 0;
  }

  /**
   *
   */
  static class HttpsJwksFactory {
    private final long jwkCacheDuration;
    private final long refreshReprieveThreshold;

    public HttpsJwksFactory(long jwkCacheDuration, long refreshReprieveThreshold) {
      this.jwkCacheDuration = jwkCacheDuration;
      this.refreshReprieveThreshold = refreshReprieveThreshold;
    }
    
    /**
     * While the class name is HttpsJwks, it actually works with plain http formatted url as well.
     * @param url the Url to connect to for JWK details.
     */
    private HttpsJwks create(String url) {
      try {
        URL jwksUrl = new URL(url);
        checkAllowOutboundHttpConnections(PARAM_JWKS_URL, jwksUrl);
        
      } catch (MalformedURLException e) {
        throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Url " + url + " configured in " + PARAM_JWKS_URL + " is not a valid URL");
      }
      HttpsJwks httpsJkws = new HttpsJwks(url);
      httpsJkws.setDefaultCacheDuration(jwkCacheDuration);
      httpsJkws.setRefreshReprieveThreshold(refreshReprieveThreshold);
      return httpsJkws;
    }

    public List<HttpsJwks> createList(List<String> jwkUrls) {
      return jwkUrls.stream().map(this::create).collect(Collectors.toList());
    }
  }

  /**
   * Config object for a OpenId Connect well-known config
   * Typically exposed through /.well-known/openid-configuration endpoint
   */
  public static class WellKnownDiscoveryConfig {
    private Map<String, Object> securityConf;

    WellKnownDiscoveryConfig(Map<String, Object> securityConf) {
      this.securityConf = securityConf;
    }

    public static WellKnownDiscoveryConfig parse(String urlString) {
      try {
        URL url = new URL(urlString);
        if (!Arrays.asList("https", "file", "http").contains(url.getProtocol())) {
          throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Well-known config URL must be one of HTTPS or HTTP or file");          
        }
        checkAllowOutboundHttpConnections(PARAM_WELL_KNOWN_URL, url);

        return parse(url.openStream());
      } catch (MalformedURLException e) {
        throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Well-known config URL " + urlString + " is malformed", e);
      } catch (IOException e) {
        throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Well-known config could not be read from url " + urlString, e);
      }
    }

    public static WellKnownDiscoveryConfig parse(String json, Charset charset) {
      return parse(new ByteArrayInputStream(json.getBytes(charset)));
    }

    @SuppressWarnings("unchecked")
    public static WellKnownDiscoveryConfig parse(InputStream configStream) {
      return new WellKnownDiscoveryConfig((Map<String, Object>) Utils.fromJSON(configStream));
    }


    public String getJwksUrl() {
      return (String) securityConf.get("jwks_uri");
    }

    public String getIssuer() {
      return (String) securityConf.get("issuer");
    }

    public String getAuthorizationEndpoint() {
      return (String) securityConf.get("authorization_endpoint");
    }

    public String getUserInfoEndpoint() {
      return (String) securityConf.get("userinfo_endpoint");
    }

    public String getTokenEndpoint() {
      return (String) securityConf.get("token_endpoint");
    }

    @SuppressWarnings("unchecked")
    public List<String> getScopesSupported() {
      return (List<String>) securityConf.get("scopes_supported");
    }

    @SuppressWarnings("unchecked")
    public List<String> getResponseTypesSupported() {
      return (List<String>) securityConf.get("response_types_supported");
    }
  }

  public static void checkAllowOutboundHttpConnections(String parameterName, URL url) {
    if ("http".equalsIgnoreCase(url.getProtocol())) {
      if (!ALLOW_OUTBOUND_HTTP) {
        throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, parameterName + " is using http protocol. " + ALLOW_OUTBOUND_HTTP_ERR_MSG);
      }
    }
  }
 
}
