class ClientAuthInterceptor implements ClientInterceptor {

  @Override
  public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
      final MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, final Channel next) {
    // TODO(ejona86): If the call fails for Auth reasons, this does not properly propagate info that
    // would be in WWW-Authenticate, because it does not yet have access to the header.
    return new CheckedForwardingClientCall<ReqT, RespT>(next.newCall(method, callOptions)) {
      @Override
      protected void checkedStart(Listener<RespT> responseListener, Metadata headers)
          throws StatusException {
        Metadata cachedSaved;
        URI uri = serviceUri(next, method);
        synchronized (ClientAuthInterceptor.this) {
          // TODO(louiscryan): This is icky but the current auth library stores the same
          // metadata map until the next refresh cycle. This will be fixed once
          // https://github.com/google/google-auth-library-java/issues/3
          // is resolved.
          // getRequestMetadata() may return a different map based on the provided URI, i.e., for
          // JWT. However, today it does not cache JWT and so we won't bother tring to cache its
          // return value based on the URI.
          Map<String, List<String>> latestMetadata = getRequestMetadata(uri);
          if (lastMetadata == null || lastMetadata != latestMetadata) {
            lastMetadata = latestMetadata;
            cached = toHeaders(lastMetadata);
          }
          cachedSaved = cached;
        }
        headers.merge(cachedSaved);
        delegate().start(responseListener, headers);
      }
    };
  }

  public  ClientAuthInterceptor(
      Credentials credentials, @SuppressWarnings("unused") Executor executor);

}