// 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;
/*
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed 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 com.google.api.auth;


/**
 * An authenticator that extracts the auth token from the HTTP request and
 * constructs a {@link UserInfo} object based on the claims contained in the
 * auth token.
 *
 * @author yangguan@google.com
 *
 */
public class Authenticator {

  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private static final String ACCESS_TOKEN_PARAM_NAME = "access_token";
  private static final String BEARER_TOKEN_PREFIX = "Bearer ";
  private static final String EMAIL_CLAIM_NAME = "email";

  private final AuthTokenDecoder authTokenDecoder;
  private final Clock clock;
  private final Map<String, String> issuersToProviderIds;

  /**
   * Constructor.
   *
   * @param authTokenDecoder decodes auth tokens into {@link UserInfo} objects.
   * @param clock provides the time.
   * @param issuersToProviderIds maps from issuers to provider IDs.
   */
  @VisibleForTesting
  Authenticator(
      AuthTokenDecoder authTokenDecoder,
      Clock clock,
      Map<String, String> issuersToProviderIds) {
    this.authTokenDecoder = authTokenDecoder;
    this.clock = clock;
    this.issuersToProviderIds = issuersToProviderIds;
  }

  /**
   * Authenticate the current HTTP request.
   *
   * @param httpServletRequest is the incoming HTTP request object.
   * @param authInfo contains authentication configurations of the API method being called.
   * @param serviceName is the name of this service.
   * @return a constructed {@link UserInfo} object representing the identity of the caller.
   */
  public UserInfo authenticate(
      HttpServletRequest httpServletRequest,
// 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;

/*
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed 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 com.google.api.auth;


/**
 * An authenticator that extracts the auth token from the HTTP request and
 * constructs a {@link UserInfo} object based on the claims contained in the
 * auth token.
 *
 * @author yangguan@google.com
 *
 */
public class Authenticator {

  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private static final String ACCESS_TOKEN_PARAM_NAME = "access_token";
  private static final String BEARER_TOKEN_PREFIX = "Bearer ";
  private static final String EMAIL_CLAIM_NAME = "email";

  private final AuthTokenDecoder authTokenDecoder;
  private final Clock clock;
  private final Map<String, String> issuersToProviderIds;

  /**
   * Constructor.
   *
   * @param authTokenDecoder decodes auth tokens into {@link UserInfo} objects.
   * @param clock provides the time.
   * @param issuersToProviderIds maps from issuers to provider IDs.
   */
  @VisibleForTesting
  Authenticator(
      AuthTokenDecoder authTokenDecoder,
      Clock clock,
      Map<String, String> issuersToProviderIds) {
    this.authTokenDecoder = authTokenDecoder;
    this.clock = clock;
    this.issuersToProviderIds = issuersToProviderIds;
  }

  /**
   * Authenticate the current HTTP request.
   *
   * @param httpServletRequest is the incoming HTTP request object.
   * @param authInfo contains authentication configurations of the API method being called.
   * @param serviceName is the name of this service.
   * @return a constructed {@link UserInfo} object representing the identity of the caller.
   */
  public UserInfo authenticate(
      HttpServletRequest httpServletRequest,
      AuthInfo authInfo,