From 6293e1916db8978dd71c69727afc234175d90cc9 Mon Sep 17 00:00:00 2001 From: Diego Alonso Marquez Palacios Date: Tue, 1 Apr 2025 13:48:41 -0400 Subject: [PATCH 1/3] feat: allow cached ADC to be refreshed Fixes https://github.com/googleapis/google-api-java-client/issues/2541 This introduces the new method `public static GoogleCredential getApplicationDefault(boolean resetCachedCredentials)` which will reset the cached credentials when the argument is `true`. --- .../oauth2/DefaultCredentialProvider.java | 23 +++++++++- .../auth/oauth2/GoogleCredential.java | 46 +++++++++++++++++-- .../oauth2/DefaultCredentialProviderTest.java | 14 ++++++ 3 files changed, 78 insertions(+), 5 deletions(-) diff --git a/google-api-client/src/main/java/com/google/api/client/googleapis/auth/oauth2/DefaultCredentialProvider.java b/google-api-client/src/main/java/com/google/api/client/googleapis/auth/oauth2/DefaultCredentialProvider.java index 9f1534a19..a8111c2b0 100644 --- a/google-api-client/src/main/java/com/google/api/client/googleapis/auth/oauth2/DefaultCredentialProvider.java +++ b/google-api-client/src/main/java/com/google/api/client/googleapis/auth/oauth2/DefaultCredentialProvider.java @@ -82,6 +82,7 @@ private static enum Environment { * authorize the whole application. This is the built-in service account if running on Google * Compute Engine or the credentials file from the path in the environment variable * GOOGLE_APPLICATION_CREDENTIALS. + * If the credentials have been cached, the cached credential will be returned. * * @param transport the transport for Http calls. * @param jsonFactory the factory for Json parsing and formatting. @@ -90,8 +91,28 @@ private static enum Environment { */ final GoogleCredential getDefaultCredential(HttpTransport transport, JsonFactory jsonFactory) throws IOException { + return getDefaultCredential(transport, jsonFactory, false); + } + + /** + * {@link Beta}
+ * Returns the Application Default Credentials. + * + *

Returns the Application Default Credentials which are credentials that identify and + * authorize the whole application. This is the built-in service account if running on Google + * Compute Engine or the credentials file from the path in the environment variable + * GOOGLE_APPLICATION_CREDENTIALS. + * + * @param transport the transport for Http calls. + * @param jsonFactory the factory for Json parsing and formatting. + * @param resetCachedCredentials if true, the cached credential will be reset. + * @return the credential instance. + * @throws IOException if the credential cannot be created in the current environment. + */ + final GoogleCredential getDefaultCredential(HttpTransport transport, JsonFactory jsonFactory, boolean resetCachedCredentials) + throws IOException { synchronized (this) { - if (cachedCredential == null) { + if (cachedCredential == null || resetCachedCredentials) { cachedCredential = getDefaultCredentialUnsynchronized(transport, jsonFactory); } if (cachedCredential != null) { diff --git a/google-api-client/src/main/java/com/google/api/client/googleapis/auth/oauth2/GoogleCredential.java b/google-api-client/src/main/java/com/google/api/client/googleapis/auth/oauth2/GoogleCredential.java index 590a422e2..56e701625 100644 --- a/google-api-client/src/main/java/com/google/api/client/googleapis/auth/oauth2/GoogleCredential.java +++ b/google-api-client/src/main/java/com/google/api/client/googleapis/auth/oauth2/GoogleCredential.java @@ -153,7 +153,7 @@ public class GoogleCredential extends Credential { static final String SERVICE_ACCOUNT_FILE_TYPE = "service_account"; @Beta - private static DefaultCredentialProvider defaultCredentialProvider = + private static final DefaultCredentialProvider defaultCredentialProvider = new DefaultCredentialProvider(); /** @@ -170,7 +170,7 @@ public class GoogleCredential extends Credential { */ @Beta public static GoogleCredential getApplicationDefault() throws IOException { - return getApplicationDefault(Utils.getDefaultTransport(), Utils.getDefaultJsonFactory()); + return getApplicationDefault(Utils.getDefaultTransport(), Utils.getDefaultJsonFactory(), false); } /** @@ -181,7 +181,25 @@ public static GoogleCredential getApplicationDefault() throws IOException { * authorize the whole application. This is the built-in service account if running on Google * Compute Engine or the credentials file from the path in the environment variable * GOOGLE_APPLICATION_CREDENTIALS. + * @param resetCachedCredentials whether to reset the cached credentials + * @return the credential instance. + * @throws IOException if the credential cannot be created in the current environment. + */ + @Beta + public static GoogleCredential getApplicationDefault(boolean resetCachedCredentials) throws IOException { + return getApplicationDefault(Utils.getDefaultTransport(), Utils.getDefaultJsonFactory(), resetCachedCredentials); + } + + /** + * {@link Beta}
+ * Returns the Application Default Credentials. * + *

Returns the Application Default Credentials which are credentials that identify and + * authorize the whole application. This is the built-in service account if running on Google + * Compute Engine or the credentials file from the path in the environment variable + * GOOGLE_APPLICATION_CREDENTIALS. + * + * @param resetCachedCredentials whether to reset the cached credentials. * @param transport the transport for Http calls. * @param jsonFactory the factory for Json parsing and formatting. * @return the credential instance. @@ -189,10 +207,30 @@ public static GoogleCredential getApplicationDefault() throws IOException { */ @Beta public static GoogleCredential getApplicationDefault( - HttpTransport transport, JsonFactory jsonFactory) throws IOException { + HttpTransport transport, JsonFactory jsonFactory, boolean resetCachedCredentials) throws IOException { Preconditions.checkNotNull(transport); Preconditions.checkNotNull(jsonFactory); - return defaultCredentialProvider.getDefaultCredential(transport, jsonFactory); + return defaultCredentialProvider.getDefaultCredential(transport, jsonFactory, resetCachedCredentials); + } + + /** + * {@link Beta}
+ * Returns the Application Default Credentials. + * + *

Returns the Application Default Credentials which are credentials that identify and + * authorize the whole application. This is the built-in service account if running on Google + * Compute Engine or the credentials file from the path in the environment variable + * GOOGLE_APPLICATION_CREDENTIALS. + * + * @param transport the transport for Http calls. + * @param jsonFactory the factory for Json parsing and formatting. + * @return the credential instance. + * @throws IOException if the credential cannot be created in the current environment. + */ + @Beta + public static GoogleCredential getApplicationDefault( + HttpTransport transport, JsonFactory jsonFactory) throws IOException { + return getApplicationDefault(transport, jsonFactory, false); } /** diff --git a/google-api-client/src/test/java/com/google/api/client/googleapis/auth/oauth2/DefaultCredentialProviderTest.java b/google-api-client/src/test/java/com/google/api/client/googleapis/auth/oauth2/DefaultCredentialProviderTest.java index d3ea60ccc..2974e764b 100644 --- a/google-api-client/src/test/java/com/google/api/client/googleapis/auth/oauth2/DefaultCredentialProviderTest.java +++ b/google-api-client/src/test/java/com/google/api/client/googleapis/auth/oauth2/DefaultCredentialProviderTest.java @@ -87,6 +87,20 @@ public void testDefaultCredentialAppEngineDeployed() throws IOException { assertSame(JSON_FACTORY, defaultCredential.getJsonFactory()); } + + public void testGetApplicationDefaultResetCacheTrueReturnsNewCredentials() throws IOException { + TestDefaultCredentialProvider testProvider = new TestDefaultCredentialProvider(); + HttpTransport transport = new MockHttpTransport(); + testProvider.addType( + DefaultCredentialProvider.APP_ENGINE_CREDENTIAL_CLASS, MockAppEngineCredential.class); + testProvider.addType(GAE_SIGNAL_CLASS, MockAppEngineSystemProperty.class); + Credential credential1 = testProvider.getDefaultCredential(transport, JSON_FACTORY, false); + Credential credential2 = testProvider.getDefaultCredential(transport, JSON_FACTORY, false); + Credential credential3 = testProvider.getDefaultCredential(transport, JSON_FACTORY, true); + assertSame(credential1, credential2); + assertNotSame(credential2, credential3); + } + public void testDefaultCredentialAppEngineComponentOffAppEngineGivesNotFoundError() { HttpTransport transport = new MockHttpTransport(); TestDefaultCredentialProvider testProvider = new TestDefaultCredentialProvider(); From 7cd8cc1e80dd8a44455d6aa3432a76ba37382cda Mon Sep 17 00:00:00 2001 From: Diego Alonso Marquez Palacios Date: Tue, 1 Apr 2025 13:58:55 -0400 Subject: [PATCH 2/3] format --- .../auth/oauth2/DefaultCredentialProvider.java | 7 ++++--- .../auth/oauth2/GoogleCredential.java | 17 ++++++++++++----- .../oauth2/DefaultCredentialProviderTest.java | 1 - 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/google-api-client/src/main/java/com/google/api/client/googleapis/auth/oauth2/DefaultCredentialProvider.java b/google-api-client/src/main/java/com/google/api/client/googleapis/auth/oauth2/DefaultCredentialProvider.java index a8111c2b0..7d17d4aed 100644 --- a/google-api-client/src/main/java/com/google/api/client/googleapis/auth/oauth2/DefaultCredentialProvider.java +++ b/google-api-client/src/main/java/com/google/api/client/googleapis/auth/oauth2/DefaultCredentialProvider.java @@ -81,8 +81,8 @@ private static enum Environment { *

Returns the Application Default Credentials which are credentials that identify and * authorize the whole application. This is the built-in service account if running on Google * Compute Engine or the credentials file from the path in the environment variable - * GOOGLE_APPLICATION_CREDENTIALS. - * If the credentials have been cached, the cached credential will be returned. + * GOOGLE_APPLICATION_CREDENTIALS. If the credentials have been cached, the cached credential will + * be returned. * * @param transport the transport for Http calls. * @param jsonFactory the factory for Json parsing and formatting. @@ -109,7 +109,8 @@ final GoogleCredential getDefaultCredential(HttpTransport transport, JsonFactory * @return the credential instance. * @throws IOException if the credential cannot be created in the current environment. */ - final GoogleCredential getDefaultCredential(HttpTransport transport, JsonFactory jsonFactory, boolean resetCachedCredentials) + final GoogleCredential getDefaultCredential( + HttpTransport transport, JsonFactory jsonFactory, boolean resetCachedCredentials) throws IOException { synchronized (this) { if (cachedCredential == null || resetCachedCredentials) { diff --git a/google-api-client/src/main/java/com/google/api/client/googleapis/auth/oauth2/GoogleCredential.java b/google-api-client/src/main/java/com/google/api/client/googleapis/auth/oauth2/GoogleCredential.java index 56e701625..2118f289a 100644 --- a/google-api-client/src/main/java/com/google/api/client/googleapis/auth/oauth2/GoogleCredential.java +++ b/google-api-client/src/main/java/com/google/api/client/googleapis/auth/oauth2/GoogleCredential.java @@ -181,13 +181,16 @@ public static GoogleCredential getApplicationDefault() throws IOException { * authorize the whole application. This is the built-in service account if running on Google * Compute Engine or the credentials file from the path in the environment variable * GOOGLE_APPLICATION_CREDENTIALS. + * * @param resetCachedCredentials whether to reset the cached credentials * @return the credential instance. * @throws IOException if the credential cannot be created in the current environment. */ @Beta - public static GoogleCredential getApplicationDefault(boolean resetCachedCredentials) throws IOException { - return getApplicationDefault(Utils.getDefaultTransport(), Utils.getDefaultJsonFactory(), resetCachedCredentials); + public static GoogleCredential getApplicationDefault(boolean resetCachedCredentials) + throws IOException { + return getApplicationDefault( + Utils.getDefaultTransport(), Utils.getDefaultJsonFactory(), resetCachedCredentials); } /** @@ -207,10 +210,12 @@ public static GoogleCredential getApplicationDefault(boolean resetCachedCredenti */ @Beta public static GoogleCredential getApplicationDefault( - HttpTransport transport, JsonFactory jsonFactory, boolean resetCachedCredentials) throws IOException { + HttpTransport transport, JsonFactory jsonFactory, boolean resetCachedCredentials) + throws IOException { Preconditions.checkNotNull(transport); Preconditions.checkNotNull(jsonFactory); - return defaultCredentialProvider.getDefaultCredential(transport, jsonFactory, resetCachedCredentials); + return defaultCredentialProvider.getDefaultCredential( + transport, jsonFactory, resetCachedCredentials); } /** @@ -607,7 +612,9 @@ public Builder setJsonFactory(JsonFactory jsonFactory) { return (Builder) super.setJsonFactory(jsonFactory); } - /** @since 1.9 */ + /** + * @since 1.9 + */ @Override public Builder setClock(Clock clock) { return (Builder) super.setClock(clock); diff --git a/google-api-client/src/test/java/com/google/api/client/googleapis/auth/oauth2/DefaultCredentialProviderTest.java b/google-api-client/src/test/java/com/google/api/client/googleapis/auth/oauth2/DefaultCredentialProviderTest.java index 2974e764b..b68d5940a 100644 --- a/google-api-client/src/test/java/com/google/api/client/googleapis/auth/oauth2/DefaultCredentialProviderTest.java +++ b/google-api-client/src/test/java/com/google/api/client/googleapis/auth/oauth2/DefaultCredentialProviderTest.java @@ -87,7 +87,6 @@ public void testDefaultCredentialAppEngineDeployed() throws IOException { assertSame(JSON_FACTORY, defaultCredential.getJsonFactory()); } - public void testGetApplicationDefaultResetCacheTrueReturnsNewCredentials() throws IOException { TestDefaultCredentialProvider testProvider = new TestDefaultCredentialProvider(); HttpTransport transport = new MockHttpTransport(); From 9d451e2d83cf208111e804342b31567ea6f46ecd Mon Sep 17 00:00:00 2001 From: Diego Alonso Marquez Palacios Date: Tue, 1 Apr 2025 19:30:16 -0400 Subject: [PATCH 3/3] lint with google-java-format 1.7 --- .../api/client/googleapis/auth/oauth2/GoogleCredential.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google-api-client/src/main/java/com/google/api/client/googleapis/auth/oauth2/GoogleCredential.java b/google-api-client/src/main/java/com/google/api/client/googleapis/auth/oauth2/GoogleCredential.java index 2118f289a..0b6c39ee8 100644 --- a/google-api-client/src/main/java/com/google/api/client/googleapis/auth/oauth2/GoogleCredential.java +++ b/google-api-client/src/main/java/com/google/api/client/googleapis/auth/oauth2/GoogleCredential.java @@ -140,8 +140,8 @@ * response handler, take a look at the sample usage for {@link HttpExecuteInterceptor} and {@link * HttpUnsuccessfulResponseHandler}, which are interfaces that this class also implements. * - * @since 1.7 * @author Yaniv Inbar + * @since 1.7 * @deprecated Please use * google-auth-library for handling Application Default Credentials and other non-OAuth2 * based authentication.