/*
 * 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.service.knoxtoken;

import java.nio.charset.StandardCharsets;
import java.security.AccessController;
import java.security.KeyStoreException;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.text.ParseException;
import java.time.Duration;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import java.util.UUID;
import java.util.stream.Collectors;

import javax.annotation.PostConstruct;
import javax.inject.Singleton;
import javax.security.auth.Subject;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.KeyLengthException;
import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jose.util.ByteUtils;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.security.authorize.AuthorizationException;
import org.apache.hadoop.security.authorize.ProxyUsers;
import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.i18n.messages.MessagesFactory;
import org.apache.knox.gateway.security.GroupPrincipal;
import org.apache.knox.gateway.security.SubjectUtils;
import org.apache.knox.gateway.services.ServiceType;
import org.apache.knox.gateway.services.GatewayServices;
import org.apache.knox.gateway.services.ServiceLifecycleException;
import org.apache.knox.gateway.services.security.AliasService;
import org.apache.knox.gateway.services.security.AliasServiceException;
import org.apache.knox.gateway.services.security.KeystoreService;
import org.apache.knox.gateway.services.security.KeystoreServiceException;
import org.apache.knox.gateway.services.security.token.JWTokenAttributes;
import org.apache.knox.gateway.services.security.token.JWTokenAttributesBuilder;
import org.apache.knox.gateway.services.security.token.JWTokenAuthority;
import org.apache.knox.gateway.services.security.token.KnoxToken;
import org.apache.knox.gateway.services.security.token.PersistentTokenStateService;
import org.apache.knox.gateway.services.security.token.TokenMetadata;
import org.apache.knox.gateway.services.security.token.TokenServiceException;
import org.apache.knox.gateway.services.security.token.TokenStateService;
import org.apache.knox.gateway.services.security.token.TokenUtils;
import org.apache.knox.gateway.services.security.token.UnknownTokenException;
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.services.security.token.impl.TokenMAC;
import org.apache.knox.gateway.util.AuthFilterUtils;
import org.apache.knox.gateway.util.JsonUtils;
import org.apache.knox.gateway.util.Tokens;

import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static javax.ws.rs.core.MediaType.APPLICATION_XML;

@Singleton
@Path(TokenResource.RESOURCE_PATH)
public class TokenResource {
  static final String LIFESPAN = "lifespan";
  static final String COMMENT = "comment";
  private static final String EXPIRES_IN = "expires_in";
  private static final String TOKEN_TYPE = "token_type";
  private static final String ACCESS_TOKEN = "access_token";
  private static final String TOKEN_ID = "token_id";
  static final String PASSCODE = "passcode";
  private static final String MANAGED_TOKEN = "managed";
  private static final String TARGET_URL = "target_url";
  private static final String ENDPOINT_PUBLIC_CERT = "endpoint_public_cert";
  private static final String BEARER = "Bearer";
  private static final String TOKEN_PARAM_PREFIX = "knox.token.";
  private static final String TOKEN_TTL_PARAM = TOKEN_PARAM_PREFIX + "ttl";
  private static final String TOKEN_TYPE_PARAM = TOKEN_PARAM_PREFIX + "type";
  private static final String TOKEN_AUDIENCES_PARAM = TOKEN_PARAM_PREFIX + "audiences";
  public static final String TOKEN_INCLUDE_GROUPS_IN_JWT_ALLOWED = TOKEN_PARAM_PREFIX + "include.groups.allowed";
  private static final String TOKEN_TARGET_URL = TOKEN_PARAM_PREFIX + "target.url";
  static final String TOKEN_CLIENT_DATA = TOKEN_PARAM_PREFIX + "client.data";
  private static final String TOKEN_CLIENT_CERT_REQUIRED = TOKEN_PARAM_PREFIX + "client.cert.required";
  private static final String TOKEN_ALLOWED_PRINCIPALS = TOKEN_PARAM_PREFIX + "allowed.principals";
  private static final String TOKEN_SIG_ALG = TOKEN_PARAM_PREFIX + "sigalg";
  private static final String TOKEN_EXP_RENEWAL_INTERVAL = TOKEN_PARAM_PREFIX + "exp.renew-interval";
  private static final String TOKEN_EXP_RENEWAL_MAX_LIFETIME = TOKEN_PARAM_PREFIX + "exp.max-lifetime";
  private static final String TOKEN_EXP_TOKENGEN_ALLOWED_TSS_BACKENDS = TOKEN_PARAM_PREFIX + "exp.tokengen.allowed.tss.backends";
  private static final String TOKEN_RENEWER_WHITELIST = TOKEN_PARAM_PREFIX + "renewer.whitelist";
  private static final String TSS_STATUS_IS_MANAGEMENT_ENABLED = "tokenManagementEnabled";
  private static final String TSS_STATUS_CONFIFURED_BACKEND = "configuredTssBackend";
  private static final String TSS_STATUS_ACTUAL_BACKEND = "actualTssBackend";
  private static final String TSS_ALLOWED_BACKEND_FOR_TOKENGEN = "allowedTssForTokengen";
  private static final String TSS_MAXIMUM_LIFETIME_SECONDS = "maximumLifetimeSeconds";
  private static final String TSS_MAXIMUM_LIFETIME_TEXT = "maximumLifetimeText";
  private static final String LIFESPAN_INPUT_ENABLED_PARAM = TOKEN_PARAM_PREFIX + "lifespan.input.enabled";
  private static final String LIFESPAN_INPUT_ENABLED_TEXT = "lifespanInputEnabled";
  static final String KNOX_TOKEN_USER_LIMIT_EXCEEDED_ACTION = TOKEN_PARAM_PREFIX + "user.limit.exceeded.action";
  private static final String METADATA_QUERY_PARAM_PREFIX = "md_";
  private static final long TOKEN_TTL_DEFAULT = 30000L;
  static final String TOKEN_API_PATH = "knoxtoken/api/v1";
  static final String RESOURCE_PATH = TOKEN_API_PATH + "/token";
  static final String GET_USER_TOKENS = "/getUserTokens";
  static final String GET_TSS_STATUS_PATH = "/getTssStatus";
  static final String RENEW_PATH = "/renew";
  static final String REVOKE_PATH = "/revoke";
  static final String ENABLE_PATH = "/enable";
  static final String DISABLE_PATH = "/disable";
  private static final String TARGET_ENDPOINT_PULIC_CERT_PEM = TOKEN_PARAM_PREFIX + "target.endpoint.cert.pem";
  static final String QUERY_PARAMETER_DOAS = "doAs";
  static final String PROXYUSER_PREFIX = TOKEN_PARAM_PREFIX + "proxyuser";
  static final String IMPERSONATION_ENABLED_PARAM = TOKEN_PARAM_PREFIX + "impersonation.enabled";
  private static final String IMPERSONATION_ENABLED_TEXT = "impersonationEnabled";
  public static final String KNOX_TOKEN_INCLUDE_GROUPS = TOKEN_PARAM_PREFIX + "include.groups";
  public static final String KNOX_TOKEN_ISSUER = TOKEN_PARAM_PREFIX + "issuer";
  private static TokenServiceMessages log = MessagesFactory.get(TokenServiceMessages.class);
  private long tokenTTL = TOKEN_TTL_DEFAULT;
  private String tokenType;
  private String tokenTTLAsText;
  private List<String> targetAudiences = new ArrayList<>();
  private String tokenTargetUrl;
  private Map<String, Object> tokenClientDataMap;
  private List<String> allowedDNs = new ArrayList<>();
  private boolean clientCertRequired;
  private String signatureAlgorithm;
  private String endpointPublicCert;

  // Optional token store service
  private TokenStateService tokenStateService;
  private TokenMAC tokenMAC;
  private final Map<String, String> tokenStateServiceStatusMap = new HashMap<>();

  private Optional<Long> renewInterval = Optional.empty();

  private Optional<Long> maxTokenLifetime = Optional.empty();

  private int tokenLimitPerUser;
  private boolean includeGroupsInTokenAllowed;
  private String tokenIssuer;
  private boolean impersonationEnabled;

  enum UserLimitExceededAction {REMOVE_OLDEST, RETURN_ERROR};
  private UserLimitExceededAction userLimitExceededAction = UserLimitExceededAction.RETURN_ERROR;

  private List<String> allowedRenewers;

  @Context
  HttpServletRequest request;

  @Context
  ServletContext context;

  public enum ErrorCode {
    UNKNOWN(0),
    CONFIGURATION_ERROR(10),
    UNAUTHORIZED(20),
    INTERNAL_ERROR(30),
    INVALID_TOKEN(40),
    UNKNOWN_TOKEN(50),
    ALREADY_DISABLED(60),
    ALREADY_ENABLED(70);

    private final int code;

    ErrorCode(int code) {
      this.code = code;
    }

    public int toInt() {
      return code;
    }
  }

  @PostConstruct
  public void init() throws AliasServiceException, ServiceLifecycleException, KeyLengthException {

    String audiences = context.getInitParameter(TOKEN_AUDIENCES_PARAM);
    if (audiences != null) {
      String[] auds = audiences.split(",");
      for (String aud : auds) {
        targetAudiences.add(aud.trim());
      }
    }

    String clientCert = context.getInitParameter(TOKEN_CLIENT_CERT_REQUIRED);
    clientCertRequired = "true".equals(clientCert);

    String principals = context.getInitParameter(TOKEN_ALLOWED_PRINCIPALS);
    if (principals != null) {
      String[] dns = principals.split(";");
      for (String dn : dns) {
        allowedDNs.add(dn.replaceAll("\\s+", ""));
      }
    }

    String ttl = context.getInitParameter(TOKEN_TTL_PARAM);
    if (ttl != null) {
      try {
        tokenTTL = Long.parseLong(ttl);
        if (tokenTTL < -1 || (tokenTTL + System.currentTimeMillis() < 0)) {
          log.invalidTokenTTLEncountered(ttl);
          tokenTTL = TOKEN_TTL_DEFAULT;
        }
      } catch (NumberFormatException nfe) {
        log.invalidTokenTTLEncountered(ttl);
      }
    }

    String includeGroupsInTokenAllowedParam = context.getInitParameter(TOKEN_INCLUDE_GROUPS_IN_JWT_ALLOWED);
    includeGroupsInTokenAllowed = includeGroupsInTokenAllowedParam == null
            ? true
            : Boolean.parseBoolean(includeGroupsInTokenAllowedParam);

    this.tokenIssuer = StringUtils.isBlank(context.getInitParameter(KNOX_TOKEN_ISSUER))
            ? JWTokenAttributes.DEFAULT_ISSUER
            : context.getInitParameter(KNOX_TOKEN_ISSUER);
    this.tokenType = context.getInitParameter(TOKEN_TYPE_PARAM);

    tokenTTLAsText = getTokenTTLAsText();

    tokenTargetUrl = context.getInitParameter(TOKEN_TARGET_URL);

    String clientData = context.getInitParameter(TOKEN_CLIENT_DATA);
    if (clientData != null) {
      tokenClientDataMap = new HashMap<>();
      String[] tokenClientData = clientData.split(",");
      addClientDataToMap(tokenClientData, tokenClientDataMap);
    }

    setSignatureAlogrithm();

    String targetEndpointPublicCert = context.getInitParameter(TARGET_ENDPOINT_PULIC_CERT_PEM);
    if (targetEndpointPublicCert != null) {
      endpointPublicCert = targetEndpointPublicCert;
    }

    // KnoxToken impersonation should be configurable regardless of the token state
    // management status (i.e. even if token state management is enabled users
    // should be able to opt-out token impersonation
    final String impersonationEnabledValue = context.getInitParameter(IMPERSONATION_ENABLED_PARAM);
    impersonationEnabled = impersonationEnabledValue == null ? Boolean.TRUE : Boolean.parseBoolean(impersonationEnabledValue);

    // If server-managed token expiration is configured, set the token state service
    if (isServerManagedTokenStateEnabled()) {
      String topologyName = getTopologyName();
      log.serverManagedTokenStateEnabled(topologyName);

      GatewayServices services = (GatewayServices) context.getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
      tokenStateService = services.getService(ServiceType.TOKEN_STATE_SERVICE);
      final GatewayConfig gatewayConfig = (GatewayConfig) context.getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE);
      final AliasService aliasService = services.getService(ServiceType.ALIAS_SERVICE);
      tokenMAC = new TokenMAC(gatewayConfig.getKnoxTokenHashAlgorithm(), aliasService.getPasswordFromAliasForGateway(TokenMAC.KNOX_TOKEN_HASH_KEY_ALIAS_NAME));

      tokenLimitPerUser = gatewayConfig.getMaximumNumberOfTokensPerUser();
      final String userLimitExceededActionParam = context.getInitParameter(KNOX_TOKEN_USER_LIMIT_EXCEEDED_ACTION);
      if (userLimitExceededActionParam != null) {
        userLimitExceededAction = UserLimitExceededAction.valueOf(userLimitExceededActionParam);
        log.generalInfoMessage("Configured Knox Token user limit exceeded action = " + userLimitExceededAction.name());
      }

      String renewIntervalValue = context.getInitParameter(TOKEN_EXP_RENEWAL_INTERVAL);
      if (renewIntervalValue != null && !renewIntervalValue.isEmpty()) {
        try {
          renewInterval = Optional.of(Long.parseLong(renewIntervalValue));
        } catch (NumberFormatException e) {
          log.invalidConfigValue(topologyName, TOKEN_EXP_RENEWAL_INTERVAL, renewIntervalValue, e);
        }
      }

      String maxLifetimeValue = context.getInitParameter(TOKEN_EXP_RENEWAL_MAX_LIFETIME);
      if (maxLifetimeValue != null && !maxLifetimeValue.isEmpty()) {
        try {
          maxTokenLifetime = Optional.of(Long.parseLong(maxLifetimeValue));
        } catch (NumberFormatException e) {
          log.invalidConfigValue(topologyName, TOKEN_EXP_RENEWAL_MAX_LIFETIME, maxLifetimeValue, e);
        }
      }

      allowedRenewers = new ArrayList<>();
      String renewerList = context.getInitParameter(TOKEN_RENEWER_WHITELIST);
      if (renewerList != null && !renewerList.isEmpty()) {
        for (String renewer : renewerList.split(",")) {
          allowedRenewers.add(renewer.trim());
        }
      } else {
        log.noRenewersConfigured(topologyName);
      }

      // refreshing Hadoop ProxyUser groups config only makes sense if token state management is turned on
      // and impersonation is enabled
      if (impersonationEnabled) {
        final Configuration conf = AuthFilterUtils.getProxyUserConfiguration(context, PROXYUSER_PREFIX);
        ProxyUsers.refreshSuperUserGroupsConfiguration(conf, PROXYUSER_PREFIX);
      }
    }
    setTokenStateServiceStatusMap();
  }

  private String getTokenTTLAsText() {
    if (tokenTTL == -1) {
      return "Unlimited lifetime";
    }

    final Duration tokenTTLDuration = Duration.ofMillis(tokenTTL);
    long daysPart = tokenTTLDuration.toDays();
    long hoursPart = daysPart > 0 ? tokenTTLDuration.minusDays(daysPart).toHours() : tokenTTLDuration.toHours();
    long minutesPart = tokenTTLDuration.toHours() > 0 ? tokenTTLDuration.minusHours(tokenTTLDuration.toHours()).toMinutes() : tokenTTLDuration.toMinutes();
    long secondsPart = tokenTTLDuration.toMinutes() > 0 ? tokenTTLDuration.minusMinutes(tokenTTLDuration.toMinutes()).getSeconds() : tokenTTLDuration.getSeconds();
    final StringBuilder sb = new StringBuilder(32);
    if (daysPart > 0) {
      sb.append(daysPart).append(" days ");
    }
    if (hoursPart > 0) {
      sb.append(hoursPart).append(" hours ");
    }
    if (minutesPart > 0) {
      sb.append(minutesPart).append(" minutes ");
    }
    if (secondsPart > 0) {
      sb.append(secondsPart).append(" seconds");
    }
    return sb.toString();
  }

  private void setTokenStateServiceStatusMap() {
    if (isServerManagedTokenStateEnabled()) {
      tokenStateServiceStatusMap.put(TSS_STATUS_IS_MANAGEMENT_ENABLED, "true");
      final GatewayConfig config = (GatewayConfig) request.getServletContext().getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE);
      final String configuredTokenStateServiceImpl = config.getServiceParameter(ServiceType.TOKEN_STATE_SERVICE.getShortName(), "impl");
      final String configuredTokenServiceName = StringUtils.isBlank(configuredTokenStateServiceImpl) ? ""
          : configuredTokenStateServiceImpl.substring(configuredTokenStateServiceImpl.lastIndexOf('.') + 1);
      final String actualTokenStateServiceImpl = tokenStateService.getClass().getCanonicalName();
      final String actualTokenServiceName = actualTokenStateServiceImpl.substring(actualTokenStateServiceImpl.lastIndexOf('.') + 1);
      tokenStateServiceStatusMap.put(TSS_STATUS_CONFIFURED_BACKEND, configuredTokenServiceName);
      tokenStateServiceStatusMap.put(TSS_STATUS_ACTUAL_BACKEND, actualTokenServiceName);
      populateAllowedTokenStateBackendForTokenGenApp(actualTokenServiceName);
      tokenStateServiceStatusMap.put(TSS_MAXIMUM_LIFETIME_SECONDS, String.valueOf(tokenTTL == -1 ? tokenTTL : (tokenTTL / 1000)));
      tokenStateServiceStatusMap.put(TSS_MAXIMUM_LIFETIME_TEXT, tokenTTLAsText);
    } else {
      tokenStateServiceStatusMap.put(TSS_STATUS_IS_MANAGEMENT_ENABLED, "false");
    }
    final String lifespanInputEnabledValue = context.getInitParameter(LIFESPAN_INPUT_ENABLED_PARAM);
    final Boolean lifespanInputEnabled = lifespanInputEnabledValue == null ? Boolean.TRUE : Boolean.parseBoolean(lifespanInputEnabledValue);
    tokenStateServiceStatusMap.put(LIFESPAN_INPUT_ENABLED_TEXT, lifespanInputEnabled.toString());

    tokenStateServiceStatusMap.put(IMPERSONATION_ENABLED_TEXT, Boolean.toString(impersonationEnabled));
  }

  private void populateAllowedTokenStateBackendForTokenGenApp(final String actualTokenServiceName) {
    tokenStateServiceStatusMap.put(TSS_ALLOWED_BACKEND_FOR_TOKENGEN, "false");
    final String allowedTssBackends = context.getInitParameter(TOKEN_EXP_TOKENGEN_ALLOWED_TSS_BACKENDS);
    if (allowedTssBackends != null && !allowedTssBackends.isEmpty()) {
      for (String allowedTssBackend : allowedTssBackends.split(",")) {
        if (allowedTssBackend.trim().equals(actualTokenServiceName)) {
          tokenStateServiceStatusMap.put(TSS_ALLOWED_BACKEND_FOR_TOKENGEN, "true");
          break;
        }
      }
    } else {
      //if there is no custom configuration in the topology, then we allow keystore and DB back-end for the tokengen application
      if ("AliasBasedTokenStateService".equals(actualTokenServiceName) || "JDBCTokenStateService".equals(actualTokenServiceName)) {
        tokenStateServiceStatusMap.put(TSS_ALLOWED_BACKEND_FOR_TOKENGEN, "true");
      }
    }
  }

  private void setSignatureAlogrithm() throws AliasServiceException, KeyLengthException {
    final String configuredSigAlg = context.getInitParameter(TOKEN_SIG_ALG);
    final GatewayConfig config = (GatewayConfig) request.getServletContext().getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE);
    final GatewayServices services = (GatewayServices) request.getServletContext().getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
    AliasService aliasService = services.getService(ServiceType.ALIAS_SERVICE);
    signatureAlgorithm = TokenUtils.getSignatureAlgorithm(configuredSigAlg, aliasService, config.getSigningKeystoreName());
    char[] hmacSecret = aliasService.getPasswordFromAliasForGateway(TokenUtils.SIGNING_HMAC_SECRET_ALIAS);
    if (hmacSecret != null && !isAlgCompatibleWithSecret(signatureAlgorithm, hmacSecret)) {
      throw new KeyLengthException(JWSAlgorithm.parse(signatureAlgorithm));
    }
  }

  private boolean isAlgCompatibleWithSecret(String algName, char[] secret) {
    return MACSigner.getCompatibleAlgorithms(ByteUtils.bitLength(secret.length))
            .contains(JWSAlgorithm.parse(algName));
  }

  private boolean isServerManagedTokenStateEnabled() {
    boolean isServerManaged;

    // First, check for explicit service-level configuration
    String serviceParamValue = context.getInitParameter(TokenStateService.CONFIG_SERVER_MANAGED);

    // If there is no service-level configuration
    if (serviceParamValue == null || serviceParamValue.isEmpty()) {
      // Fall back to the gateway-level default
      GatewayConfig config = (GatewayConfig) context.getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE);
      isServerManaged = (config != null) && config.isServerManagedTokenStateEnabled();
    } else {
      // Otherwise, apply the service-level configuration
      isServerManaged = Boolean.valueOf(serviceParamValue);
    }

    return isServerManaged;
  }

  @GET
  @Produces({APPLICATION_JSON, APPLICATION_XML})
  public Response doGet() {
    return getAuthenticationToken();
  }

  @POST
  @Produces({APPLICATION_JSON, APPLICATION_XML})
  public Response doPost() {
    return getAuthenticationToken();
  }

  @GET
  @Path(GET_USER_TOKENS)
  @Produces({APPLICATION_JSON, APPLICATION_XML})
  public Response getUserTokens(@Context UriInfo uriInfo) {
    if (tokenStateService == null) {
      return Response.status(Response.Status.SERVICE_UNAVAILABLE).entity("{\n  \"error\": \"Token management is not configured\"\n}\n").build();
    } else {
      if (uriInfo == null) {
        throw new IllegalArgumentException("URI info cannot be NULL.");
      }
      final Map<String, String> metadataMap = new HashMap<>();
      uriInfo.getQueryParameters().entrySet().forEach(entry -> {
        if (entry.getKey().startsWith(METADATA_QUERY_PARAM_PREFIX)) {
          String metadataName = entry.getKey().substring(METADATA_QUERY_PARAM_PREFIX.length());
          metadataMap.put(metadataName, entry.getValue().get(0));
        }
      });

      final String userName = uriInfo.getQueryParameters().getFirst("userName");
      final String createdBy = uriInfo.getQueryParameters().getFirst("createdBy");
      final Collection<KnoxToken> userTokens = createdBy == null ? tokenStateService.getTokens(userName) : tokenStateService.getDoAsTokens(createdBy);
      final Collection<KnoxToken> tokens = new TreeSet<>();
      if (metadataMap.isEmpty()) {
        tokens.addAll(userTokens);
      } else {
        userTokens.forEach(knoxToken -> {
          for (Map.Entry<String, String> entry : metadataMap.entrySet()) {
            if (StringUtils.isBlank(entry.getValue()) || "*".equals(entry.getValue())) {
              // we should only filter tokens by metadata name
              if (knoxToken.hasMetadata(entry.getKey())) {
                tokens.add(knoxToken);
              }
            } else {
              // metadata value should also match
              if (entry.getValue().equals(knoxToken.getMetadataValue(entry.getKey()))) {
                tokens.add(knoxToken);
              }
            }
          }
        });
      }
      return Response.status(Response.Status.OK).entity(JsonUtils.renderAsJsonString(Collections.singletonMap("tokens", tokens))).build();
    }
  }

  @GET
  @Path(GET_TSS_STATUS_PATH)
  @Produces({ APPLICATION_JSON })
  public Response getTokenStateServiceStatus() {
    return Response.status(Response.Status.OK).entity(JsonUtils.renderAsJsonString(tokenStateServiceStatusMap)).build();
  }

  @PUT
  @Path(RENEW_PATH)
  @Produces({APPLICATION_JSON})
  public Response renew(String token) {
    Response resp;

    long expiration = 0;

    String          error       = "";
    ErrorCode       errorCode   = ErrorCode.UNKNOWN;
    Response.Status errorStatus = Response.Status.BAD_REQUEST;

    if (tokenStateService == null) {
      // If the token state service is disabled, then return the expiration from the specified token
      try {
        JWTToken jwt = new JWTToken(token);
        log.renewalDisabled(getTopologyName(),
                            Tokens.getTokenDisplayText(token),
                            Tokens.getTokenIDDisplayText(TokenUtils.getTokenId(jwt)));
        expiration = Long.parseLong(jwt.getExpires());
      } catch (ParseException e) {
        log.invalidToken(getTopologyName(), Tokens.getTokenDisplayText(token), e);
        error = safeGetMessage(e);
        errorCode = ErrorCode.INVALID_TOKEN;
      } catch (Exception e) {
        error = safeGetMessage(e);
        errorCode = ErrorCode.INTERNAL_ERROR;
      }
    } else {
      String renewer = SubjectUtils.getCurrentEffectivePrincipalName();
      if (allowedRenewers.contains(renewer)) {
        try {
          JWTToken jwt = new JWTToken(token);
          // If renewal fails, it should be an exception
          expiration = tokenStateService.renewToken(jwt,
                                                    renewInterval.orElse(tokenStateService.getDefaultRenewInterval()));
          log.renewedToken(getTopologyName(),
                           Tokens.getTokenDisplayText(token),
                           Tokens.getTokenIDDisplayText(TokenUtils.getTokenId(jwt)),
                           renewer);
        } catch (ParseException e) {
          log.invalidToken(getTopologyName(), Tokens.getTokenDisplayText(token), e);
          errorCode = ErrorCode.INVALID_TOKEN;
          error = safeGetMessage(e);
        } catch (Exception e) {
          error = safeGetMessage(e);
          errorCode = ErrorCode.INTERNAL_ERROR;
        }
      } else {
        errorStatus = Response.Status.FORBIDDEN;
        error = "Caller (" + renewer + ") not authorized to renew tokens.";
        errorCode = ErrorCode.UNAUTHORIZED;
      }
    }

    if(error.isEmpty()) {
      resp =  Response.status(Response.Status.OK)
                      .entity("{\n  \"renewed\": \"true\",\n  \"expires\": \"" + expiration + "\"\n}\n")
                      .build();
    } else {
      log.badRenewalRequest(getTopologyName(), Tokens.getTokenDisplayText(token), error);
      resp = Response.status(errorStatus)
                     .entity("{\n  \"renewed\": \"false\",\n  \"error\": \"" + error + "\",\n  \"code\": " + errorCode.toInt() + "\n}\n")
                     .build();
    }

    return resp;
  }

  @DELETE
  @Path(REVOKE_PATH)
  @Produces({APPLICATION_JSON})
  public Response revoke(String token) {
    Response resp;

    String          error       = "";
    ErrorCode       errorCode   = ErrorCode.UNKNOWN;
    Response.Status errorStatus = Response.Status.BAD_REQUEST;

    if (tokenStateService == null) {
      error = "Token revocation support is not configured";
      errorCode = ErrorCode.CONFIGURATION_ERROR;
    } else {
      try {
        final String revoker = SubjectUtils.getCurrentEffectivePrincipalName();
        final String tokenId = getTokenId(token);
        if (triesToRevokeOwnToken(tokenId, revoker) || allowedRenewers.contains(revoker)) {
            tokenStateService.revokeToken(tokenId);
            log.revokedToken(getTopologyName(),
                Tokens.getTokenDisplayText(token),
                Tokens.getTokenIDDisplayText(tokenId),
                revoker);
        } else {
          errorStatus = Response.Status.FORBIDDEN;
          error = "Caller (" + revoker + ") not authorized to revoke tokens.";
          errorCode = ErrorCode.UNAUTHORIZED;
        }
      } catch (ParseException e) {
        log.invalidToken(getTopologyName(), Tokens.getTokenDisplayText(token), e);
        error = safeGetMessage(e);
        errorCode = ErrorCode.INVALID_TOKEN;
      } catch (UnknownTokenException e) {
        error = safeGetMessage(e);
        errorCode = ErrorCode.UNKNOWN_TOKEN;
      }
    }

    if (error.isEmpty()) {
      resp =  Response.status(Response.Status.OK)
                      .entity("{\n  \"revoked\": \"true\"\n}\n")
                      .build();
    } else {
      log.badRevocationRequest(getTopologyName(), Tokens.getTokenDisplayText(token), error);
      resp = Response.status(errorStatus)
                     .entity("{\n  \"revoked\": \"false\",\n  \"error\": \"" + error + "\",\n  \"code\": " + errorCode.toInt() + "\n}\n")
                     .build();
    }

    return resp;
  }

  private boolean triesToRevokeOwnToken(String tokenId, String revoker) throws UnknownTokenException {
    final TokenMetadata metadata = tokenStateService.getTokenMetadata(tokenId);
    final String tokenUserName = metadata == null ? "" : metadata.getUserName();
    return StringUtils.isNotBlank(revoker) && revoker.equals(tokenUserName);
  }

  /*
   * If the supplied 'token' conforms the UUID string representation, we consider
   * that as the token ID; otherwise we expect that 'token' is the entire JWT and
   * we get the token ID from it
   */
  private String getTokenId(String token) throws ParseException {
    try {
      UUID.fromString(token);
      return token;
    } catch (IllegalArgumentException e) {
      //NOP: the supplied token is not a UUID, we expect the entire JWT
    }
    final JWTToken jwt = new JWTToken(token);
    return TokenUtils.getTokenId(jwt);
  }

  @PUT
  @Path(ENABLE_PATH)
  @Produces({ APPLICATION_JSON })
  public Response enable(String tokenId) {
    return setTokenEnabledFlag(tokenId, true);
  }

  @PUT
  @Path(DISABLE_PATH)
  @Produces({ APPLICATION_JSON })
  public Response disable(String tokenId) {
    return setTokenEnabledFlag(tokenId, false);
  }

  private Response setTokenEnabledFlag(String tokenId, boolean enabled) {
    String error = "";
    ErrorCode errorCode = ErrorCode.UNKNOWN;
    if (tokenStateService == null) {
      error = "Unable to " + (enabled ? "enable" : "disable") + " tokens because token management is not configured";
      errorCode = ErrorCode.CONFIGURATION_ERROR;
    } else {
      try {
        final TokenMetadata tokenMetadata = tokenStateService.getTokenMetadata(tokenId);
        if (enabled && tokenMetadata.isEnabled()) {
          error = "Token is already enabled";
          errorCode = ErrorCode.ALREADY_ENABLED;
        } else if (!enabled && !tokenMetadata.isEnabled()) {
          error = "Token is already disabled";
          errorCode = ErrorCode.ALREADY_DISABLED;
        } else {
          tokenMetadata.setEnabled(enabled);
          tokenStateService.addMetadata(tokenId, tokenMetadata);
        }
      } catch (UnknownTokenException e) {
        error = safeGetMessage(e);
        errorCode = ErrorCode.UNKNOWN_TOKEN;
      }
    }
    if (error.isEmpty()) {
      return Response.status(Response.Status.OK).entity("{\n  \"setEnabledFlag\": \"true\",\n  \"isEnabled\": \"" + enabled + "\"\n}\n").build();
    } else {
      log.badSetEnabledFlagRequest(getTopologyName(), Tokens.getTokenIDDisplayText(tokenId), error);
      return Response.status(Response.Status.BAD_REQUEST).entity("{\n  \"setEnabledFlag\": \"false\",\n  \"error\": \"" + error + "\",\n  \"code\": " + errorCode.toInt() + "\n}\n").build();
    }
  }

  private X509Certificate extractCertificate(HttpServletRequest req) {
    X509Certificate[] certs = (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate");
    if (null != certs && certs.length > 0) {
      return certs[0];
    }
    return null;
  }

  private Response getAuthenticationToken() {
    if (clientCertRequired) {
      X509Certificate cert = extractCertificate(request);
      if (cert != null) {
        if (!allowedDNs.contains(cert.getSubjectDN().getName().replaceAll("\\s+", ""))) {
          return Response.status(Response.Status.FORBIDDEN)
                         .entity("{ \"Unable to get token - untrusted client cert.\" }")
                         .build();
        }
      } else {
        return Response.status(Response.Status.FORBIDDEN)
                       .entity("{ \"Unable to get token - client cert required.\" }")
                       .build();
      }
    }
    GatewayServices services = (GatewayServices) request.getServletContext()
        .getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);

    JWTokenAuthority ts = services.getService(ServiceType.TOKEN_SERVICE);

    String userName = request.getUserPrincipal().getName();
    String createdBy = null;
    // checking the doAs user only makes sense if tokens are managed (this is where we store the userName information)
    // and if impersonation is enabled
    if (impersonationEnabled && tokenStateService != null) {
      final String doAsUser = request.getParameter(QUERY_PARAMETER_DOAS);
      if (doAsUser != null && !doAsUser.equals(userName)) {
        try {
          //this call will authorize the doAs request
          AuthFilterUtils.authorizeImpersonationRequest(request, doAsUser);
          createdBy = userName;
          userName = doAsUser;
        } catch (AuthorizationException e) {
          return Response.status(Response.Status.FORBIDDEN).entity("{ \"" + e.getMessage() + "\" }").build();
        }
      }
    }

    long expires = getExpiry();

    if (endpointPublicCert == null) {
      // acquire PEM for gateway identity of this gateway instance
      KeystoreService ks = services.getService(ServiceType.KEYSTORE_SERVICE);
      if (ks != null) {
        try {
          Certificate cert = ks.getCertificateForGateway();
          byte[] bytes = cert.getEncoded();
          endpointPublicCert = Base64.encodeBase64String(bytes);
        } catch (KeyStoreException | KeystoreServiceException | CertificateEncodingException e) {
          // assuming that certs will be properly provisioned across all clients
          log.unableToAcquireCertForEndpointClients(e);
        }
      }
    }

    String jku = null;
    /* remove .../token and replace it with ..../jwks.json */
    final int idx = request.getRequestURL().lastIndexOf("/");
    if(idx > 1) {
      jku = request.getRequestURL().substring(0, idx) + JWKSResource.JWKS_PATH;
    }

    if (tokenStateService != null) {
      if (tokenLimitPerUser != -1) { // if -1 => unlimited tokens for all users
        final Collection<KnoxToken> userTokens = tokenStateService.getTokens(userName);
        if (userTokens.size() >= tokenLimitPerUser) {
          log.tokenLimitExceeded(userName);
          if (UserLimitExceededAction.RETURN_ERROR == userLimitExceededAction) {
            return Response.status(Response.Status.FORBIDDEN).entity("{ \"Unable to get token - token limit exceeded.\" }").build();
          } else {
            // userTokens is an ordered collection (by issue time) -> the first element is the oldest one
            final String oldestTokenId = userTokens.iterator().next().getTokenId();
            log.generalInfoMessage(String.format(Locale.getDefault(), "Revoking %s's oldest token %s ...", userName, Tokens.getTokenIDDisplayText(oldestTokenId)));
            revoke(oldestTokenId);
           }
        }
      }
    }

    try {
      final boolean managedToken = tokenStateService != null;
      JWT token;
      JWTokenAttributes jwtAttributes;
      final JWTokenAttributesBuilder jwtAttributesBuilder = new JWTokenAttributesBuilder();
      jwtAttributesBuilder
          .setIssuer(tokenIssuer)
          .setUserName(userName)
          .setAlgorithm(signatureAlgorithm)
          .setExpires(expires)
          .setManaged(managedToken)
          .setJku(jku)
          .setType(tokenType);
      if (!targetAudiences.isEmpty()) {
        jwtAttributesBuilder.setAudiences(targetAudiences);
      }
      if (shouldIncludeGroups()) {
        if (includeGroupsInTokenAllowed) {
          jwtAttributesBuilder.setGroups(groups());
        } else {
          return Response
                  .status(Response.Status.BAD_REQUEST)
                  .entity("{\n  \"error\": \"Including group information in tokens is disabled\"\n}\n")
                  .build();
        }
      }

      jwtAttributes = jwtAttributesBuilder.build();
      token = ts.issueToken(jwtAttributes);

      if (token != null) {
        String accessToken = token.toString();
        String tokenId = TokenUtils.getTokenId(token);
        log.issuedToken(getTopologyName(), Tokens.getTokenDisplayText(accessToken), Tokens.getTokenIDDisplayText(tokenId));

        final HashMap<String, Object> map = new HashMap<>();
        map.put(ACCESS_TOKEN, accessToken);
        map.put(TOKEN_ID, tokenId);
        map.put(MANAGED_TOKEN, String.valueOf(managedToken));
        map.put(TOKEN_TYPE, BEARER);
        map.put(EXPIRES_IN, expires);
        if (tokenTargetUrl != null) {
          map.put(TARGET_URL, tokenTargetUrl);
        }
        if (tokenClientDataMap != null) {
          map.putAll(tokenClientDataMap);
        }
        if (endpointPublicCert != null) {
          map.put(ENDPOINT_PUBLIC_CERT, endpointPublicCert);
        }

        final String passcode = UUID.randomUUID().toString();
        if (tokenStateService != null && tokenStateService instanceof PersistentTokenStateService) {
          map.put(PASSCODE, generatePasscodeField(tokenId, passcode));
        }

        String jsonResponse = JsonUtils.renderAsJsonString(map);

        // Optional token store service persistence
        if (tokenStateService != null) {
          final long issueTime = System.currentTimeMillis();
          tokenStateService.addToken(tokenId,
                                     issueTime,
                                     expires,
                                     maxTokenLifetime.orElse(tokenStateService.getDefaultMaxLifetimeDuration()));
          final String comment = request.getParameter(COMMENT);
          final TokenMetadata tokenMetadata = new TokenMetadata(userName, StringUtils.isBlank(comment) ? null : comment);
          tokenMetadata.setPasscode(tokenMAC.hash(tokenId, issueTime, userName, passcode));
          addArbitraryTokenMetadata(tokenMetadata);
          if (createdBy != null) {
            tokenMetadata.setCreatedBy(createdBy);
          }
          tokenStateService.addMetadata(tokenId, tokenMetadata);
          log.storedToken(getTopologyName(), Tokens.getTokenDisplayText(accessToken), Tokens.getTokenIDDisplayText(tokenId));
        }

        return Response.ok().entity(jsonResponse).build();
      } else {
        return Response.serverError().build();
      }
    } catch (TokenServiceException e) {
      log.unableToIssueToken(e);
    }
    return Response.ok().entity("{ \"Unable to acquire token.\" }").build();
  }

  private boolean shouldIncludeGroups() {
    return Boolean.parseBoolean(request.getParameter(KNOX_TOKEN_INCLUDE_GROUPS));
  }

  protected Set<String> groups() {
    Subject subject = Subject.getSubject(AccessController.getContext());
    Set<String> groups = subject.getPrincipals(GroupPrincipal.class).stream()
            .map(GroupPrincipal::getName)
            .collect(Collectors.toSet());
    return groups;
  }

  private void addArbitraryTokenMetadata(TokenMetadata tokenMetadata) {
    final Enumeration<String> paramNames = request.getParameterNames();
    while (paramNames.hasMoreElements()) {
      final String paramName = paramNames.nextElement();
      if (paramName.startsWith(METADATA_QUERY_PARAM_PREFIX)) {
        final String metadataName = paramName.substring(METADATA_QUERY_PARAM_PREFIX.length());
        final String metadataValue = request.getParameter(paramName);
        tokenMetadata.add(metadataName, metadataValue);
      }
    }
  }

  private String generatePasscodeField(String tokenId, String passcode) {
    final String base64TokenIdPasscode = Base64.encodeBase64String(tokenId.getBytes(StandardCharsets.UTF_8)) + "::" + Base64.encodeBase64String(passcode.getBytes(StandardCharsets.UTF_8));
    return Base64.encodeBase64String(base64TokenIdPasscode.getBytes(StandardCharsets.UTF_8));
  }

  void addClientDataToMap(String[] tokenClientData,
      Map<String,Object> map) {
    String[] kv;
    for (String tokenClientDatum : tokenClientData) {
      //client data value may contain the '=' itself. For instance "homepage_url=homepage/home?profile=token&amp;topologies=sandbox"
      kv = tokenClientDatum.split("=", 2);
      if (kv.length == 2) {
        map.put(kv[0], kv[1]);
      }
    }
  }

  private long getExpiry() {
    long expiry = 0L;
    long millis = tokenTTL;

    String lifetimeStr = request.getParameter(LIFESPAN);
    if (lifetimeStr == null || lifetimeStr.isEmpty()) {
      if (tokenTTL == -1) {
        return -1;
      }
    }
    else {
      try {
        long lifetime = Duration.parse(lifetimeStr).toMillis();
        if (tokenTTL == -1) {
          // if TTL is set to -1 the topology owner grants unlimited lifetime therefore no additional check is needed on lifespan
          millis = lifetime;
        } else if (lifetime <= tokenTTL) {
          //this is expected due to security reasons: the configured TTL acts as an upper limit regardless of the supplied lifespan
          millis = lifetime;
        }
      }
      catch (DateTimeParseException e) {
        log.invalidLifetimeValue(lifetimeStr);
      }
    }
    expiry = System.currentTimeMillis() + millis;

    return expiry;
  }

  private String getTopologyName() {
    return (String) context.getAttribute("org.apache.knox.gateway.gateway.cluster");
  }

  /**
   * Safely get the message from the specified Throwable.
   *
   * @param t A Throwable
   * @return The result of t.getMessage(), or &quot;null&quot; if that result is null.
   */
  private String safeGetMessage(Throwable t) {
    String message = t.getMessage();
    return message != null ? message : "null";
  }
}
