From fea5c07e80046a7f94f75aacad02b51cce2e3147 Mon Sep 17 00:00:00 2001 From: Matt Castelaz Date: Wed, 8 Jul 2026 19:16:59 +0000 Subject: [PATCH 1/4] fix(oauth2_http): avoid retrying on 403 Forbidden during GCE metadata server ping --- .../com/google/auth/oauth2/ComputeEngineCredentials.java | 4 ++++ .../google/auth/oauth2/ComputeEngineCredentialsTest.java | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/ComputeEngineCredentials.java b/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/ComputeEngineCredentials.java index ad5fb8e7dcf3..bd5b6c28d968 100644 --- a/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/ComputeEngineCredentials.java +++ b/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/ComputeEngineCredentials.java @@ -673,6 +673,10 @@ private static boolean pingComputeEngineMetadata( } catch (SocketTimeoutException expected) { // Ignore logging timeouts which is the expected failure mode in non GCE environments. } catch (IOException e) { + if (e instanceof HttpResponseException httpResponseException + && httpResponseException.getStatusCode() == 403) { + return false; + } LOGGER.log( Level.FINE, "Encountered an unexpected exception when checking" diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ComputeEngineCredentialsTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ComputeEngineCredentialsTest.java index 82240171d9af..1528831203e6 100644 --- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ComputeEngineCredentialsTest.java +++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ComputeEngineCredentialsTest.java @@ -1177,6 +1177,15 @@ void getProjectId_explicitSet_noMDsCall() { assertEquals(0, transportFactory.transport.getRequestCount()); } + @Test + void isOnGce_forbidden_doesNotRetry() { + MockMetadataServerTransportFactory transportFactory = new MockMetadataServerTransportFactory(); + transportFactory.transport.setStatusCode(HttpStatusCodes.STATUS_CODE_FORBIDDEN); + DefaultCredentialsProvider provider = new DefaultCredentialsProvider(); + boolean isOnGce = ComputeEngineCredentials.isOnGce(transportFactory, provider); + assertFalse(isOnGce); + } + static class MockMetadataServerTransportFactory implements HttpTransportFactory { MockMetadataServerTransport transport = From 5f0f25a0cd511399192d40b19b34fc4238727e11 Mon Sep 17 00:00:00 2001 From: Matt Castelaz Date: Wed, 8 Jul 2026 21:17:19 +0000 Subject: [PATCH 2/4] test: assert exactly 1 request is made on 403 in isOnGce_forbidden_doesNotRetry --- .../com/google/auth/oauth2/ComputeEngineCredentialsTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ComputeEngineCredentialsTest.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ComputeEngineCredentialsTest.java index 1528831203e6..7e07073020f4 100644 --- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ComputeEngineCredentialsTest.java +++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ComputeEngineCredentialsTest.java @@ -1184,6 +1184,7 @@ void isOnGce_forbidden_doesNotRetry() { DefaultCredentialsProvider provider = new DefaultCredentialsProvider(); boolean isOnGce = ComputeEngineCredentials.isOnGce(transportFactory, provider); assertFalse(isOnGce); + assertEquals(1, transportFactory.transport.getRequestCount()); } static class MockMetadataServerTransportFactory implements HttpTransportFactory { From be67e65c98d4b6b207347fd17cceab89b789fd09 Mon Sep 17 00:00:00 2001 From: Matt Castelaz Date: Wed, 8 Jul 2026 21:28:05 +0000 Subject: [PATCH 3/4] fix(oauth2_http): downgrade instanceof pattern matching for Java 8 compatibility --- .../java/com/google/auth/oauth2/ComputeEngineCredentials.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/ComputeEngineCredentials.java b/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/ComputeEngineCredentials.java index bd5b6c28d968..73effb539fad 100644 --- a/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/ComputeEngineCredentials.java +++ b/google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/ComputeEngineCredentials.java @@ -673,8 +673,8 @@ private static boolean pingComputeEngineMetadata( } catch (SocketTimeoutException expected) { // Ignore logging timeouts which is the expected failure mode in non GCE environments. } catch (IOException e) { - if (e instanceof HttpResponseException httpResponseException - && httpResponseException.getStatusCode() == 403) { + if (e instanceof HttpResponseException + && ((HttpResponseException) e).getStatusCode() == 403) { return false; } LOGGER.log( From 1cb6a68ec66a5da44bbf788a72eddd3eb3df09e5 Mon Sep 17 00:00:00 2001 From: Matt Castelaz Date: Thu, 9 Jul 2026 01:16:49 +0000 Subject: [PATCH 4/4] test: add getRequestCount to MockMetadataServerTransport to support verification in tests --- .../com/google/auth/oauth2/MockMetadataServerTransport.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/MockMetadataServerTransport.java b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/MockMetadataServerTransport.java index 1b218b73ef45..369ea35b857c 100644 --- a/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/MockMetadataServerTransport.java +++ b/google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/MockMetadataServerTransport.java @@ -71,6 +71,11 @@ public class MockMetadataServerTransport extends MockHttpTransport { private boolean emptyContent; private MockLowLevelHttpRequest request; + private int requestCount = 0; + + public int getRequestCount() { + return requestCount; + } public MockMetadataServerTransport() {} @@ -125,6 +130,7 @@ public MockLowLevelHttpRequest getRequest() { @Override public LowLevelHttpRequest buildRequest(String method, String url) throws IOException { + requestCount++; if (url.startsWith(ComputeEngineCredentials.getTokenServerEncodedUrl())) { this.request = getMockRequestForTokenEndpoint(url); return this.request;