// Path: endpoints-service-config/src/main/java/com/google/api/config/ServiceConfigFetcher.java
// public class ServiceConfigFetcher {
// 
//   private final Supplier<Service> serviceSupplier;
// 
//   @VisibleForTesting
//   ServiceConfigFetcher(Supplier<Service> supplier) {
//     this.serviceSupplier = Suppliers.memoizeWithExpiration(supplier, 10, TimeUnit.MINUTES);
//   }
// 
//   public Service fetch() {
//     return this.serviceSupplier.get();
//   }
// 
//   public static ServiceConfigFetcher create() {
//     return new ServiceConfigFetcher(ServiceConfigSupplier.create());
//   }
// }
// 
// Path: endpoints-control/src/main/java/com/google/api/control/model/MethodRegistry.java
// public static final class AuthInfo {
//   private final Map<String, Set<String>> providerIdsToAudiences;
// 
//   public AuthInfo(Map<String, Set<String>> providerIdsToAudiences) {
//     Preconditions.checkNotNull(providerIdsToAudiences);
//     this.providerIdsToAudiences = providerIdsToAudiences;
//   }
// 
//   public boolean isProviderIdAllowed(String providerid) {
//     Preconditions.checkNotNull(providerid);
//     return this.providerIdsToAudiences.containsKey(providerid);
//   }
// 
//   public Set<String> getAudiencesForProvider(String providerId) {
//     Preconditions.checkNotNull(providerId);
// 
//     if (this.providerIdsToAudiences.containsKey(providerId)) {
//       return this.providerIdsToAudiences.get(providerId);
//     }
//     return ImmutableSet.<String>of();
//   }
// }


import com.google.api.AuthProvider;
import com.google.api.Authentication;
import com.google.api.Service;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpRequestFactory;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.util.Clock;
import com.google.api.client.util.Maps;
import com.google.api.config.ServiceConfigFetcher;
import com.google.api.control.model.MethodRegistry.AuthInfo;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import com.google.common.flogger.FluentLogger;
import com.google.common.net.HttpHeaders;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.MalformedClaimException;
import org.jose4j.jwt.NumericDate;
import org.jose4j.jwt.ReservedClaimNames;
  }

  // Check whether the JWT claims should be accepted.
  private void checkJwtClaims(JwtClaims jwtClaims) {
    Optional<NumericDate> expiration = getDateClaim(ReservedClaimNames.EXPIRATION_TIME, jwtClaims);
    if (!expiration.isPresent()) {
      throw new UnauthenticatedException("Missing expiration field");
    }
    Optional<NumericDate> notBefore = getDateClaim(ReservedClaimNames.NOT_BEFORE, jwtClaims);

    NumericDate currentTime = NumericDate.fromMilliseconds(clock.currentTimeMillis());
    if (expiration.get().isBefore(currentTime)) {
      throw new UnauthenticatedException("The auth token has already expired");
    }

    if (notBefore.isPresent() && notBefore.get().isAfter(currentTime)) {
      String message = "Current time is earlier than the \"nbf\" time";
      throw new UnauthenticatedException(message);
    }
  }

  /**
   * Create an instance of {@link Authenticator} using the service configuration fetched from Google
   * Service Management APIs.
   *
   * @return an {@code Authenticator}
   * @throws java.lang.IllegalArgumentException if the authentication message is not defined in the
   *         fetched service config.
   */
  public static Authenticator create() {
// Path: endpoints-service-config/src/main/java/com/google/api/config/ServiceConfigFetcher.java
// public class ServiceConfigFetcher {
// 
//   private final Supplier<Service> serviceSupplier;
// 
//   @VisibleForTesting
//   ServiceConfigFetcher(Supplier<Service> supplier) {
//     this.serviceSupplier = Suppliers.memoizeWithExpiration(supplier, 10, TimeUnit.MINUTES);
//   }
// 
//   public Service fetch() {
//     return this.serviceSupplier.get();
//   }
// 
//   public static ServiceConfigFetcher create() {
//     return new ServiceConfigFetcher(ServiceConfigSupplier.create());
//   }
// }
// 
// Path: endpoints-control/src/main/java/com/google/api/control/model/MethodRegistry.java
// public static final class AuthInfo {
//   private final Map<String, Set<String>> providerIdsToAudiences;
// 
//   public AuthInfo(Map<String, Set<String>> providerIdsToAudiences) {
//     Preconditions.checkNotNull(providerIdsToAudiences);
//     this.providerIdsToAudiences = providerIdsToAudiences;
//   }
// 
//   public boolean isProviderIdAllowed(String providerid) {
//     Preconditions.checkNotNull(providerid);
//     return this.providerIdsToAudiences.containsKey(providerid);
//   }
// 
//   public Set<String> getAudiencesForProvider(String providerId) {
//     Preconditions.checkNotNull(providerId);
// 
//     if (this.providerIdsToAudiences.containsKey(providerId)) {
//       return this.providerIdsToAudiences.get(providerId);
//     }
//     return ImmutableSet.<String>of();
//   }
// }


// Path: endpoints-auth/src/main/java/com/google/api/auth/Authenticator.java
import com.google.api.AuthProvider;
import com.google.api.Authentication;
import com.google.api.Service;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpRequestFactory;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.util.Clock;
import com.google.api.client.util.Maps;
import com.google.api.config.ServiceConfigFetcher;
import com.google.api.control.model.MethodRegistry.AuthInfo;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import com.google.common.flogger.FluentLogger;
import com.google.common.net.HttpHeaders;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.MalformedClaimException;
import org.jose4j.jwt.NumericDate;
import org.jose4j.jwt.ReservedClaimNames;

  }

  // Check whether the JWT claims should be accepted.
  private void checkJwtClaims(JwtClaims jwtClaims) {
    Optional<NumericDate> expiration = getDateClaim(ReservedClaimNames.EXPIRATION_TIME, jwtClaims);
    if (!expiration.isPresent()) {
      throw new UnauthenticatedException("Missing expiration field");
    }
    Optional<NumericDate> notBefore = getDateClaim(ReservedClaimNames.NOT_BEFORE, jwtClaims);

    NumericDate currentTime = NumericDate.fromMilliseconds(clock.currentTimeMillis());
    if (expiration.get().isBefore(currentTime)) {
      throw new UnauthenticatedException("The auth token has already expired");
    }

    if (notBefore.isPresent() && notBefore.get().isAfter(currentTime)) {
      String message = "Current time is earlier than the \"nbf\" time";
      throw new UnauthenticatedException(message);
    }
  }

  /**
   * Create an instance of {@link Authenticator} using the service configuration fetched from Google
   * Service Management APIs.
   *
   * @return an {@code Authenticator}
   * @throws java.lang.IllegalArgumentException if the authentication message is not defined in the
   *         fetched service config.
   */
  public static Authenticator create() {
    ServiceConfigFetcher fetcher = ServiceConfigFetcher.create();