diff --git a/build.gradle b/build.gradle
index bad6e6b992..5340839127 100644
--- a/build.gradle
+++ b/build.gradle
@@ -46,9 +46,10 @@ subprojects {
     // For Google libraries, check <http-client-bom.version>, <google.auth.version>, <guava.version>,
     // ... in https://github.com/googleapis/google-cloud-java/blob/master/google-cloud-clients/pom.xml
     // for best compatibility.
-    GOOGLE_HTTP_CLIENT: '1.27.0',
-    GOOGLE_AUTH_LIBRARY_OAUTH2_HTTP: '0.16.2',
-    GUAVA: '28.0-jre',
+    GOOGLE_HTTP_CLIENT: '1.33.0',
+    GOOGLE_HTTP_CLIENT_APACHE_V2: '1.33.0',
+    GOOGLE_AUTH_LIBRARY_OAUTH2_HTTP: '0.18.0',
+    GUAVA: '28.1-jre',
 
     COMMONS_COMPRESS: '1.19',
     JACKSON_DATABIND: '2.9.10',
@@ -64,7 +65,10 @@ subprojects {
   // Use this to ensure we correctly override transitive dependencies
   // TODO: There might be a plugin that does this
   task ensureTransitiveDependencyOverrides {
-    def rules = ["google-http-client": dependencyVersions.GOOGLE_HTTP_CLIENT]
+    def rules = [
+        "google-http-client": dependencyVersions.GOOGLE_HTTP_CLIENT,
+        "google-http-client-apache-v2": dependencyVersions.GOOGLE_HTTP_CLIENT_APACHE_V2,
+    ]
     doLast {
       configurations.runtimeClasspath.resolvedConfiguration.resolvedArtifacts.each { artifact ->
         def dependency = artifact.moduleVersion.id
diff --git a/jib-core/build.gradle b/jib-core/build.gradle
index 624a319697..672ab9f3ba 100644
--- a/jib-core/build.gradle
+++ b/jib-core/build.gradle
@@ -5,9 +5,8 @@ plugins {
 
 dependencies {
   implementation "com.google.http-client:google-http-client:${dependencyVersions.GOOGLE_HTTP_CLIENT}"
-  implementation("com.google.auth:google-auth-library-oauth2-http:${dependencyVersions.GOOGLE_AUTH_LIBRARY_OAUTH2_HTTP}") {
-    exclude group: "com.google.http-client", module: "google-http-client"
-  }
+  implementation "com.google.http-client:google-http-client-apache-v2:${dependencyVersions.GOOGLE_HTTP_CLIENT_APACHE_V2}"
+  implementation "com.google.auth:google-auth-library-oauth2-http:${dependencyVersions.GOOGLE_AUTH_LIBRARY_OAUTH2_HTTP}"
 
   implementation "org.apache.commons:commons-compress:${dependencyVersions.COMMONS_COMPRESS}"
   implementation "com.google.guava:guava:${dependencyVersions.GUAVA}"
diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/http/FailoverHttpClient.java b/jib-core/src/main/java/com/google/cloud/tools/jib/http/FailoverHttpClient.java
index 46bf2615ee..78e073c5ca 100644
--- a/jib-core/src/main/java/com/google/cloud/tools/jib/http/FailoverHttpClient.java
+++ b/jib-core/src/main/java/com/google/cloud/tools/jib/http/FailoverHttpClient.java
@@ -22,10 +22,10 @@
 import com.google.api.client.http.HttpRequest;
 import com.google.api.client.http.HttpResponseException;
 import com.google.api.client.http.HttpTransport;
-import com.google.api.client.http.apache.ApacheHttpTransport;
+import com.google.api.client.http.apache.v2.ApacheHttpTransport;
+import com.google.api.client.util.SslUtils;
 import com.google.cloud.tools.jib.api.LogEvent;
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
 import java.io.IOException;
 import java.net.ConnectException;
 import java.net.URL;
@@ -33,9 +33,8 @@
 import java.util.function.Consumer;
 import java.util.function.Supplier;
 import javax.net.ssl.SSLException;
-import org.apache.http.auth.AuthScope;
-import org.apache.http.auth.UsernamePasswordCredentials;
-import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.impl.client.HttpClientBuilder;
 
 /**
  * Thread-safe HTTP client that can automatically failover from secure HTTPS to insecure HTTPS or
@@ -86,55 +85,23 @@ private static HttpTransport getSecureHttpTransport() {
     //
     // A new ApacheHttpTransport needs to be created for each connection because otherwise HTTP
     // connection persistence causes the connection to throw NoHttpResponseException.
-    ApacheHttpTransport transport = new ApacheHttpTransport();
-    addProxyCredentials(transport);
-    return transport;
+    return new ApacheHttpTransport();
   }
 
   private static HttpTransport getInsecureHttpTransport() {
     try {
-      ApacheHttpTransport insecureTransport =
-          new ApacheHttpTransport.Builder().doNotValidateCertificate().build();
-      addProxyCredentials(insecureTransport);
-      return insecureTransport;
+      HttpClientBuilder httpClientBuilder =
+          ApacheHttpTransport.newDefaultHttpClientBuilder()
+              .setSSLSocketFactory(null) // creates new factory with the SSLContext given below
+              .setSSLContext(SslUtils.trustAllSSLContext())
+              .setSSLHostnameVerifier(new NoopHostnameVerifier());
+      // Do not use NetHttpTransport. See comments in getConnectionFactory for details.
+      return new ApacheHttpTransport(httpClientBuilder.build());
     } catch (GeneralSecurityException ex) {
       throw new RuntimeException("platform does not support TLS protocol", ex);
     }
   }
 
-  /**
-   * Registers proxy credentials onto transport client, in order to deal with proxies that require
-   * basic authentication.
-   *
-   * @param transport Apache HTTP transport
-   */
-  @VisibleForTesting
-  static void addProxyCredentials(ApacheHttpTransport transport) {
-    addProxyCredentials(transport, "https");
-    addProxyCredentials(transport, "http");
-  }
-
-  private static void addProxyCredentials(ApacheHttpTransport transport, String protocol) {
-    Preconditions.checkArgument(protocol.equals("http") || protocol.equals("https"));
-
-    String proxyHost = System.getProperty(protocol + ".proxyHost");
-    String proxyUser = System.getProperty(protocol + ".proxyUser");
-    String proxyPassword = System.getProperty(protocol + ".proxyPassword");
-    if (proxyHost == null || proxyUser == null || proxyPassword == null) {
-      return;
-    }
-
-    String defaultProxyPort = protocol.equals("http") ? "80" : "443";
-    int proxyPort = Integer.parseInt(System.getProperty(protocol + ".proxyPort", defaultProxyPort));
-
-    DefaultHttpClient httpClient = (DefaultHttpClient) transport.getHttpClient();
-    httpClient
-        .getCredentialsProvider()
-        .setCredentials(
-            new AuthScope(proxyHost, proxyPort),
-            new UsernamePasswordCredentials(proxyUser, proxyPassword));
-  }
-
   private final boolean enableHttpAndInsecureFailover;
   private final boolean sendAuthorizationOverHttp;
   private final Consumer<LogEvent> logger;
diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/registry/RegistryEndpointCaller.java b/jib-core/src/main/java/com/google/cloud/tools/jib/registry/RegistryEndpointCaller.java
index eb5d0fd98a..debfbd4737 100644
--- a/jib-core/src/main/java/com/google/cloud/tools/jib/registry/RegistryEndpointCaller.java
+++ b/jib-core/src/main/java/com/google/cloud/tools/jib/registry/RegistryEndpointCaller.java
@@ -164,10 +164,11 @@ private T call(URL url) throws IOException, RegistryException {
             throw new RegistryUnauthorizedException(serverUrl, imageName, responseException);
           }
 
-        } else if (responseException.getStatusCode()
-                == HttpStatusCodes.STATUS_CODE_TEMPORARY_REDIRECT
-            || responseException.getStatusCode() == HttpStatusCodes.STATUS_CODE_MOVED_PERMANENTLY
-            || responseException.getStatusCode() == STATUS_CODE_PERMANENT_REDIRECT) {
+          // 301 (Moved Permanently), 302 (Found), 303 (See Other), and 307 (Temporary Redirect) are
+          // automatically followed by Google HTTP Client (setFollowRedirects(true)), but 308 isn't.
+          // https://github.com/googleapis/google-http-java-client/issues/873
+          // TODO: remove this when the bug is fixed.
+        } else if (responseException.getStatusCode() == STATUS_CODE_PERMANENT_REDIRECT) {
           // 'Location' header can be relative or absolute.
           URL redirectLocation = new URL(url, responseException.getHeaders().getLocation());
           return call(redirectLocation);
diff --git a/jib-core/src/test/java/com/google/cloud/tools/jib/http/FailoverHttpClientProxyCredentialsTest.java b/jib-core/src/test/java/com/google/cloud/tools/jib/http/FailoverHttpClientProxyCredentialsTest.java
deleted file mode 100644
index 615f3f0cfb..0000000000
--- a/jib-core/src/test/java/com/google/cloud/tools/jib/http/FailoverHttpClientProxyCredentialsTest.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright 2018 Google LLC.
- *
- * 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.cloud.tools.jib.http;
-
-import com.google.api.client.http.apache.ApacheHttpTransport;
-import com.google.common.collect.ImmutableList;
-import org.apache.http.auth.AuthScope;
-import org.apache.http.auth.Credentials;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.contrib.java.lang.system.RestoreSystemProperties;
-
-/** Tests for {@link FailoverHttpClient} with setting proxy credentials. */
-public class FailoverHttpClientProxyCredentialsTest {
-
-  private static final ImmutableList<String> proxyProperties =
-      ImmutableList.of(
-          "http.proxyHost",
-          "http.proxyPort",
-          "http.proxyUser",
-          "http.proxyPassword",
-          "https.proxyHost",
-          "https.proxyPort",
-          "https.proxyUser",
-          "https.proxyPassword");
-
-  @Rule public final RestoreSystemProperties systemPropertyRestorer = new RestoreSystemProperties();
-
-  private final ApacheHttpTransport transport = new ApacheHttpTransport();
-
-  @Before
-  public void setUp() {
-    proxyProperties.stream().forEach(key -> System.clearProperty(key));
-  }
-
-  @Test
-  public void testAddProxyCredentials_undefined() {
-    FailoverHttpClient.addProxyCredentials(transport);
-    DefaultHttpClient httpClient = (DefaultHttpClient) transport.getHttpClient();
-    Credentials credentials = httpClient.getCredentialsProvider().getCredentials(AuthScope.ANY);
-    Assert.assertNull(credentials);
-  }
-
-  @Test
-  public void testAddProxyCredentials() {
-    System.setProperty("http.proxyHost", "http://localhost");
-    System.setProperty("http.proxyPort", "1080");
-    System.setProperty("http.proxyUser", "user");
-    System.setProperty("http.proxyPassword", "pass");
-
-    System.setProperty("https.proxyHost", "https://host.com");
-    System.setProperty("https.proxyPort", "1443");
-    System.setProperty("https.proxyUser", "s-user");
-    System.setProperty("https.proxyPassword", "s-pass");
-
-    FailoverHttpClient.addProxyCredentials(transport);
-    DefaultHttpClient httpClient = (DefaultHttpClient) transport.getHttpClient();
-    Credentials httpCredentials =
-        httpClient.getCredentialsProvider().getCredentials(new AuthScope("http://localhost", 1080));
-    Assert.assertEquals("user", httpCredentials.getUserPrincipal().getName());
-    Assert.assertEquals("pass", httpCredentials.getPassword());
-
-    Credentials httpsCredentials =
-        httpClient.getCredentialsProvider().getCredentials(new AuthScope("https://host.com", 1443));
-    Assert.assertEquals("s-user", httpsCredentials.getUserPrincipal().getName());
-    Assert.assertEquals("s-pass", httpsCredentials.getPassword());
-  }
-
-  @Test
-  public void testAddProxyCredentials_defaultPorts() {
-    System.setProperty("http.proxyHost", "http://localhost");
-    System.setProperty("http.proxyUser", "user");
-    System.setProperty("http.proxyPassword", "pass");
-
-    System.setProperty("https.proxyHost", "https://host.com");
-    System.setProperty("https.proxyUser", "s-user");
-    System.setProperty("https.proxyPassword", "s-pass");
-
-    FailoverHttpClient.addProxyCredentials(transport);
-    DefaultHttpClient httpClient = (DefaultHttpClient) transport.getHttpClient();
-    Credentials httpCredentials =
-        httpClient.getCredentialsProvider().getCredentials(new AuthScope("http://localhost", 80));
-    Assert.assertEquals("user", httpCredentials.getUserPrincipal().getName());
-    Assert.assertEquals("pass", httpCredentials.getPassword());
-
-    Credentials httpsCredentials =
-        httpClient.getCredentialsProvider().getCredentials(new AuthScope("https://host.com", 443));
-    Assert.assertEquals("s-user", httpsCredentials.getUserPrincipal().getName());
-    Assert.assertEquals("s-pass", httpsCredentials.getPassword());
-  }
-
-  @Test
-  public void testAddProxyCredentials_hostUndefined() {
-    System.setProperty("http.proxyUser", "user");
-    System.setProperty("http.proxyPassword", "pass");
-
-    System.setProperty("https.proxyUser", "s-user");
-    System.setProperty("https.proxyPassword", "s-pass");
-
-    FailoverHttpClient.addProxyCredentials(transport);
-    DefaultHttpClient httpClient = (DefaultHttpClient) transport.getHttpClient();
-    Credentials credentials = httpClient.getCredentialsProvider().getCredentials(AuthScope.ANY);
-    Assert.assertNull(credentials);
-  }
-
-  @Test
-  public void testAddProxyCredentials_userUndefined() {
-    System.setProperty("http.proxyHost", "http://localhost");
-    System.setProperty("http.proxyPassword", "pass");
-
-    System.setProperty("https.proxyHost", "https://host.com");
-    System.setProperty("https.proxyPassword", "s-pass");
-
-    FailoverHttpClient.addProxyCredentials(transport);
-    DefaultHttpClient httpClient = (DefaultHttpClient) transport.getHttpClient();
-    Credentials credentials = httpClient.getCredentialsProvider().getCredentials(AuthScope.ANY);
-    Assert.assertNull(credentials);
-  }
-
-  @Test
-  public void testAddProxyCredentials_passwordUndefined() {
-    System.setProperty("http.proxyHost", "http://localhost");
-    System.setProperty("http.proxyUser", "user");
-
-    System.setProperty("https.proxyHost", "https://host.com");
-    System.setProperty("https.proxyUser", "s-user");
-
-    FailoverHttpClient.addProxyCredentials(transport);
-    DefaultHttpClient httpClient = (DefaultHttpClient) transport.getHttpClient();
-    Credentials credentials = httpClient.getCredentialsProvider().getCredentials(AuthScope.ANY);
-    Assert.assertNull(credentials);
-  }
-}
diff --git a/jib-core/src/test/java/com/google/cloud/tools/jib/http/WithServerFailoverHttpClientTest.java b/jib-core/src/test/java/com/google/cloud/tools/jib/http/WithServerFailoverHttpClientTest.java
index 471b74002a..72e8baa979 100644
--- a/jib-core/src/test/java/com/google/cloud/tools/jib/http/WithServerFailoverHttpClientTest.java
+++ b/jib-core/src/test/java/com/google/cloud/tools/jib/http/WithServerFailoverHttpClientTest.java
@@ -24,6 +24,7 @@
 import java.nio.charset.StandardCharsets;
 import java.security.GeneralSecurityException;
 import java.util.Arrays;
+import java.util.List;
 import java.util.function.Consumer;
 import javax.net.ssl.SSLException;
 import org.hamcrest.CoreMatchers;
@@ -149,4 +150,45 @@ public void testProxyCredentialProperties()
       }
     }
   }
+
+  @Test
+  public void testRedirectionUrls()
+      throws IOException, InterruptedException, GeneralSecurityException, URISyntaxException {
+    // Sample query strings from
+    // https://github.com/GoogleContainerTools/jib/issues/1986#issuecomment-547610104
+    String url1 = "?id=301&_auth_=exp=1572285389~hmac=f0a387f0";
+    String url2 = "?id=302&Signature=2wYOD0a%2BDAkK%2F9lQJUOuIpYti8o%3D&Expires=1569997614";
+    String url3 = "?id=303&_auth_=exp=1572285389~hmac=f0a387f0";
+    String url4 = "?id=307&Signature=2wYOD0a%2BDAkK%2F9lQJUOuIpYti8o%3D&Expires=1569997614";
+
+    String redirect301 =
+        "HTTP/1.1 301 Moved Permanently\nLocation: " + url1 + "\nContent-Length: 0\n\n";
+    String redirect302 = "HTTP/1.1 302 Found\nLocation: " + url2 + "\nContent-Length: 0\n\n";
+    String redirect303 = "HTTP/1.1 303 See Other\nLocation: " + url3 + "\nContent-Length: 0\n\n";
+    String redirect307 =
+        "HTTP/1.1 307 Temporary Redirect\nLocation: " + url4 + "\nContent-Length: 0\n\n";
+    String ok200 = "HTTP/1.1 200 OK\nContent-Length:12\n\nHello World!";
+    List<String> responses =
+        Arrays.asList(redirect301, redirect302, redirect303, redirect307, ok200);
+
+    FailoverHttpClient httpClient = new FailoverHttpClient(true /*insecure*/, false, logger);
+    try (TestWebServer server = new TestWebServer(false, responses, 1)) {
+      httpClient.get(new URL(server.getEndpoint()), request);
+
+      Assert.assertThat(
+          server.getInputRead(),
+          CoreMatchers.containsString("GET /?id=301&_auth_=exp%3D1572285389~hmac%3Df0a387f0 "));
+      Assert.assertThat(
+          server.getInputRead(),
+          CoreMatchers.containsString(
+              "GET /?id=302&Signature=2wYOD0a%2BDAkK/9lQJUOuIpYti8o%3D&Expires=1569997614 "));
+      Assert.assertThat(
+          server.getInputRead(),
+          CoreMatchers.containsString("GET /?id=303&_auth_=exp%3D1572285389~hmac%3Df0a387f0 "));
+      Assert.assertThat(
+          server.getInputRead(),
+          CoreMatchers.containsString(
+              "GET /?id=307&Signature=2wYOD0a%2BDAkK/9lQJUOuIpYti8o%3D&Expires=1569997614 "));
+    }
+  }
 }
diff --git a/jib-core/src/test/java/com/google/cloud/tools/jib/registry/RegistryEndpointCallerTest.java b/jib-core/src/test/java/com/google/cloud/tools/jib/registry/RegistryEndpointCallerTest.java
index 2179cd5b2b..3487df0b58 100644
--- a/jib-core/src/test/java/com/google/cloud/tools/jib/registry/RegistryEndpointCallerTest.java
+++ b/jib-core/src/test/java/com/google/cloud/tools/jib/registry/RegistryEndpointCallerTest.java
@@ -242,18 +242,22 @@ public void testCall_unknown() throws IOException, RegistryException {
   }
 
   @Test
-  public void testCall_temporaryRedirect() throws IOException, RegistryException {
-    verifyRetriesWithNewLocation(HttpStatusCodes.STATUS_CODE_TEMPORARY_REDIRECT);
-  }
+  public void testCall_permanentRedirect() throws IOException, RegistryException {
+    ResponseException redirectException =
+        mockResponseException(
+            RegistryEndpointCaller.STATUS_CODE_PERMANENT_REDIRECT,
+            new HttpHeaders().setLocation("https://newlocation"));
 
-  @Test
-  public void testCall_movedPermanently() throws IOException, RegistryException {
-    verifyRetriesWithNewLocation(HttpStatusCodes.STATUS_CODE_MOVED_PERMANENTLY);
-  }
+    // Make httpClient.call() throw first, then succeed.
+    setUpRegistryResponse(redirectException);
+    Mockito.when(
+            mockHttpClient.call(
+                Mockito.eq("httpMethod"),
+                Mockito.eq(new URL("https://newlocation")),
+                Mockito.any()))
+        .thenReturn(mockResponse);
 
-  @Test
-  public void testCall_permanentRedirect() throws IOException, RegistryException {
-    verifyRetriesWithNewLocation(RegistryEndpointCaller.STATUS_CODE_PERMANENT_REDIRECT);
+    Assert.assertEquals("body", endpointCaller.call());
   }
 
   @Test
@@ -471,28 +475,6 @@ private void verifyThrowsRegistryErrorException(int httpStatusCode)
     }
   }
 
-  /**
-   * Verifies that a response with {@code httpStatusCode} retries the request with the {@code
-   * Location} header.
-   */
-  private void verifyRetriesWithNewLocation(int httpStatusCode)
-      throws IOException, RegistryException {
-    // Mocks a response for temporary redirect to a new location.
-    ResponseException redirectException =
-        mockResponseException(httpStatusCode, new HttpHeaders().setLocation("https://newlocation"));
-
-    // Make httpClient.call() throw first, then succeed.
-    setUpRegistryResponse(redirectException);
-    Mockito.when(
-            mockHttpClient.call(
-                Mockito.eq("httpMethod"),
-                Mockito.eq(new URL("https://newlocation")),
-                Mockito.any()))
-        .thenReturn(mockResponse);
-
-    Assert.assertEquals("body", endpointCaller.call());
-  }
-
   private void setUpRegistryResponse(Exception exceptionToThrow)
       throws MalformedURLException, IOException {
     Mockito.when(