@@ -217,6 +217,9 @@ public abstract static class Builder {
217217 */
218218 private Optional <GoogleCredentials .Builder > credentialsBuilder = Optional .empty ();
219219
220+ /** Specifies whether to use application default credentials. */
221+ private boolean useApplicationDefaultCredentials = false ;
222+
220223 /** Returns the credentials currently configured. */
221224 public abstract Credentials getCredentials ();
222225
@@ -230,61 +233,81 @@ public abstract static class Builder {
230233 */
231234 public abstract Builder setCredentials (Credentials credentials );
232235
236+ public Builder enableApplicationDefaultCredentials () {
237+ this .useApplicationDefaultCredentials = true ;
238+ return this ;
239+ }
240+
233241 private void setCredentials (Properties properties ) throws IOException {
234- // Validates that entries are present for exactly one of installed app/web flow credentials or
235- // service account credentials.
242+ boolean useAdc =
243+ Boolean .parseBoolean (
244+ ConfigPropertyKey .USE_APPLICATION_DEFAULT_CREDENTIALS .getPropertyValue (properties ));
245+
236246 boolean hasInstalledAppKeys =
237247 INSTALLED_APP_OAUTH_KEYS .stream ().anyMatch (k -> k .getPropertyValue (properties ) != null );
238248 boolean hasServiceAccountKeys =
239249 SERVICE_ACCOUNT_OAUTH_KEYS .stream ().anyMatch (k -> k .getPropertyValue (properties ) != null );
240- if (!(hasInstalledAppKeys || hasServiceAccountKeys )) {
241- // Entries missing for both types of credentials. Skips any further processing so user can
242- // merge this builder if needed.
243- return ;
244- }
245250
246- if (hasInstalledAppKeys && hasServiceAccountKeys ) {
247- // Entries specified for both types of credentials.
248- throw new IllegalArgumentException (
249- String .format (
250- "Entries found in properties for both %s and %s. Please modify properties to either"
251- + " include entries for %s if using installed application/web flow credentials,"
252- + " or %s if using service account credentials." ,
253- ConfigPropertyKey .SERVICE_ACCOUNT_SECRETS_PATH ,
254- ConfigPropertyKey .REFRESH_TOKEN ,
255- INSTALLED_APP_OAUTH_KEYS ,
256- SERVICE_ACCOUNT_OAUTH_KEYS ));
257- }
258-
259- if (credentialsBuilder .isPresent ()) {
260- if ((credentialsBuilder .get () instanceof UserCredentials .Builder )
261- && hasServiceAccountKeys ) {
251+ if (useAdc ) {
252+ if (hasInstalledAppKeys || hasServiceAccountKeys ) {
262253 throw new IllegalArgumentException (
263- "Entries found in properties for service account credentials, "
264- + "but this builder is already partially configured for installed application/"
265- + "web flow credentials." );
266- } else if ((credentialsBuilder .get () instanceof ServiceAccountCredentials .Builder )
267- && hasInstalledAppKeys ) {
254+ "Cannot use application default credentials when other credential types are"
255+ + " specified in the configuration. Please remove other credential keys or set"
256+ + " useApplicationDefaultCredentials to false." );
257+ }
258+ enableApplicationDefaultCredentials ();
259+ } else {
260+ // Validates that entries are present for exactly one of installed app/web flow credentials
261+ // or service account credentials.
262+ if (!(hasInstalledAppKeys || hasServiceAccountKeys )) {
263+ // Entries missing for all types of credentials. Skips any further processing so user can
264+ // merge this builder if needed.
265+ return ;
266+ }
267+
268+ if (hasInstalledAppKeys && hasServiceAccountKeys ) {
269+ // Entries specified for both types of credentials.
268270 throw new IllegalArgumentException (
269- "Entries found in properties for installed application/web flow credentials, but"
270- + " this builder is already partially configured for service account"
271- + " credentials." );
271+ String .format (
272+ "Entries found in properties for both %s and %s. Please modify properties to either"
273+ + " include entries for %s if using installed application/web flow credentials,"
274+ + " or %s if using service account credentials." ,
275+ ConfigPropertyKey .SERVICE_ACCOUNT_SECRETS_PATH ,
276+ ConfigPropertyKey .REFRESH_TOKEN ,
277+ INSTALLED_APP_OAUTH_KEYS ,
278+ SERVICE_ACCOUNT_OAUTH_KEYS ));
279+ }
280+
281+ if (credentialsBuilder .isPresent ()) {
282+ if ((credentialsBuilder .get () instanceof UserCredentials .Builder )
283+ && hasServiceAccountKeys ) {
284+ throw new IllegalArgumentException (
285+ "Entries found in properties for service account credentials, "
286+ + "but this builder is already partially configured for installed application/"
287+ + "web flow credentials." );
288+ } else if ((credentialsBuilder .get () instanceof ServiceAccountCredentials .Builder )
289+ && hasInstalledAppKeys ) {
290+ throw new IllegalArgumentException (
291+ "Entries found in properties for installed application/web flow credentials, but"
292+ + " this builder is already partially configured for service account"
293+ + " credentials." );
294+ }
272295 }
273- }
274296
275- // Clears the explicitly set credentials. This ensures that the credentials configured here
276- // will be used, even if the user previously explicitly set credentials. See build() for
277- // details.
278- setCredentials ((Credentials ) null );
297+ // Clears the explicitly set credentials. This ensures that the credentials configured here
298+ // will be used, even if the user previously explicitly set credentials. See build() for
299+ // details.
300+ setCredentials ((Credentials ) null );
279301
280- // Updates the credentials builder using the appropriate set of properties.
281- GoogleCredentials .Builder updatedBuilder ;
282- if (hasInstalledAppKeys ) {
283- updatedBuilder = configureUserCredentials (properties , credentialsBuilder );
284- } else {
285- updatedBuilder = configureServiceAccountCredentials (properties , credentialsBuilder );
302+ // Updates the credentials builder using the appropriate set of properties.
303+ GoogleCredentials .Builder updatedBuilder ;
304+ if (hasInstalledAppKeys ) {
305+ updatedBuilder = configureUserCredentials (properties , credentialsBuilder );
306+ } else {
307+ updatedBuilder = configureServiceAccountCredentials (properties , credentialsBuilder );
308+ }
309+ credentialsBuilder = Optional .of (updatedBuilder );
286310 }
287- credentialsBuilder = Optional .of (updatedBuilder );
288311 }
289312
290313 /**
@@ -342,8 +365,7 @@ private GoogleCredentials.Builder configureServiceAccountCredentials(
342365 builder = (ServiceAccountCredentials .Builder ) optionalBuilder .get ();
343366 } else {
344367 builder =
345- ServiceAccountCredentials .newBuilder ()
346- .setScopes (Collections .singleton (GOOGLE_ADS_API_SCOPE ));
368+ ServiceAccountCredentials .newBuilder ().setScopes (Collections .singleton (GOOGLE_ADS_API_SCOPE ));
347369 }
348370
349371 String serviceAccountSecretsPath =
@@ -614,14 +636,23 @@ public GoogleAdsClient build() {
614636 // with properties/environment variables that include credential settings. Note that
615637 // fromProperties() will set credentials to null in this case.
616638 // - The user explicitly set credentials via setCredentials(Credentials).
617- if (getCredentials () == null ) {
618- if (credentialsBuilder .isPresent ()) {
619- // Sets the credentials using the credentials builder.
620- setCredentials (credentialsBuilder .get ().build ());
621- } else {
622- throw new IllegalStateException ("Property \" credentials\" has not been set" );
639+ if (useApplicationDefaultCredentials ) {
640+ try {
641+ GoogleCredentials credentials =
642+ GoogleCredentials .getApplicationDefault ().createScoped (Collections .singleton (GOOGLE_ADS_API_SCOPE ));
643+ setCredentials (credentials );
644+ } catch (IOException e ) {
645+ throw new RuntimeException ("Failed to get application default credentials" , e );
623646 }
624647 } else {
648+ if (getCredentials () == null ) {
649+ if (credentialsBuilder .isPresent ()) {
650+ // Sets the credentials using the credentials builder.
651+ setCredentials (credentialsBuilder .get ().build ());
652+ } else {
653+ throw new IllegalStateException ("Property \" credentials\" has not been set" );
654+ }
655+ }
625656 // The last action by the user was to invoke setCredentials(Credentials), so no further
626657 // action is needed.
627658 }
@@ -777,7 +808,8 @@ public enum ConfigPropertyKey {
777808 // Service account keys
778809 SERVICE_ACCOUNT_SECRETS_PATH ("api.googleads.serviceAccountSecretsPath" ),
779810 SERVICE_ACCOUNT_USER ("api.googleads.serviceAccountUser" ),
780- MAX_INBOUND_MESSAGE_BYTES ("api.googleads.maxInboundMessageSize" );
811+ MAX_INBOUND_MESSAGE_BYTES ("api.googleads.maxInboundMessageSize" ),
812+ USE_APPLICATION_DEFAULT_CREDENTIALS ("api.googleads.useApplicationDefaultCredentials" );
781813
782814 private final String key ;
783815
0 commit comments