From 773f1d315dea93e262f8916cab9db080f548bda4 Mon Sep 17 00:00:00 2001 From: Neenu1995 Date: Fri, 17 Apr 2026 15:43:43 -0400 Subject: [PATCH 01/10] Add Google Drive readonly scope to all auth mechanisms --- .../jdbc/BigQueryJdbcOAuthUtility.java | 133 +++++++++++++----- 1 file changed, 94 insertions(+), 39 deletions(-) diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java index f7be358dde18..6fdf8a8ade51 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java @@ -117,6 +117,17 @@ static Map parseOAuthProperties(DataSource ds, String callerClas throw new IllegalArgumentException(OAUTH_TYPE_ERROR_MESSAGE); } oauthProperties.put(BigQueryJdbcUrlUtility.OAUTH_TYPE_PROPERTY_NAME, String.valueOf(authType)); + + Integer reqGoogleDriveScope = ds.getRequestGoogleDriveScope(); + if( reqGoogleDriveScope != null){ + Boolean reqGoogleDriveScopeBool = BigQueryJdbcUrlUtility.convertIntToBoolean(String.valueOf(reqGoogleDriveScope), BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME); + oauthProperties.put( + BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME, + String.valueOf(reqGoogleDriveScopeBool)); + LOG.fine("RequestGoogleDriveScope parsed."); + } + + switch (authType) { case GOOGLE_SERVICE_ACCOUNT: // For using a Google Service Account (OAuth Type 0) @@ -144,11 +155,6 @@ static Map parseOAuthProperties(DataSource ds, String callerClas BigQueryJdbcUrlUtility.OAUTH_CLIENT_ID_PROPERTY_NAME, ds.getOAuthClientId()); oauthProperties.put( BigQueryJdbcUrlUtility.OAUTH_CLIENT_SECRET_PROPERTY_NAME, ds.getOAuthClientSecret()); - int reqGoogleDriveScope = ds.getRequestGoogleDriveScope(); - oauthProperties.put( - BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME, - String.valueOf(reqGoogleDriveScope)); - LOG.fine("RequestGoogleDriveScope parsed."); break; case PRE_GENERATED_TOKEN: String refreshToken = ds.getOAuthRefreshToken(); @@ -280,7 +286,7 @@ static GoogleCredentials getCredentials( break; case APPLICATION_DEFAULT_CREDENTIALS: // This auth method doesn't support service account impersonation - return getApplicationDefaultCredentials(callerClassName); + return getApplicationDefaultCredentials(authProperties, callerClassName); case EXTERNAL_ACCOUNT_AUTH: // This auth method doesn't support service account impersonation return getExternalAccountAuthCredentials(authProperties, callerClassName); @@ -373,6 +379,13 @@ private static GoogleCredentials getGoogleServiceAccountCredentials( builder.setUniverseDomain( overrideProperties.get(BigQueryJdbcUrlUtility.UNIVERSE_DOMAIN_OVERRIDE_PROPERTY_NAME)); } + if ("true".equals(authProperties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME))){ + builder.setScopes( + Arrays.asList( + "https://www.googleapis.com/auth/bigquery", + "https://www.googleapis.com/auth/drive.readonly")); + LOG.fine("Added Google Drive read-only scope to Service Account builder."); + } } catch (URISyntaxException | IOException e) { LOG.severe("Validation failure for Service Account credentials."); throw new BigQueryJdbcRuntimeException(e); @@ -388,28 +401,6 @@ static UserAuthorizer getUserAuthorizer( String callerClassName) throws URISyntaxException { LOG.finest("++enter++\t" + callerClassName); - List scopes = new ArrayList<>(); - scopes.add("https://www.googleapis.com/auth/bigquery"); - - // Add Google Drive scope conditionally - if (authProperties.containsKey( - BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME)) { - try { - int driveScopeValue = - Integer.parseInt( - authProperties.get( - BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME)); - if (driveScopeValue == 1) { - scopes.add("https://www.googleapis.com/auth/drive.readonly"); - LOG.fine("Added Google Drive read-only scope. Caller: " + callerClassName); - } - } catch (NumberFormatException e) { - LOG.severe( - "Invalid value for RequestGoogleDriveScope, defaulting to not request Drive scope." - + " Caller: " - + callerClassName); - } - } List responseTypes = new ArrayList<>(); responseTypes.add("code"); @@ -421,13 +412,21 @@ static UserAuthorizer getUserAuthorizer( UserAuthorizer.Builder userAuthorizerBuilder = UserAuthorizer.newBuilder() .setClientId(clientId) - .setScopes(scopes) .setCallbackUri(URI.create("http://localhost:" + port)); if (overrideProperties.containsKey(BigQueryJdbcUrlUtility.OAUTH2_TOKEN_URI_PROPERTY_NAME)) { userAuthorizerBuilder.setTokenServerUri( new URI(overrideProperties.get(BigQueryJdbcUrlUtility.OAUTH2_TOKEN_URI_PROPERTY_NAME))); } + List scopes = new ArrayList<>(); + scopes.add("https://www.googleapis.com/auth/bigquery"); + + if ("true".equals(authProperties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME))) { + scopes.add("https://www.googleapis.com/auth/drive.readonly"); + LOG.fine("Added Google Drive read-only scope to User Account builder."); + } + + userAuthorizerBuilder.setScopes(scopes); return userAuthorizerBuilder.build(); } @@ -500,14 +499,27 @@ private static GoogleCredentials getPreGeneratedAccessTokenCredentials( builder.setUniverseDomain( overrideProperties.get(BigQueryJdbcUrlUtility.UNIVERSE_DOMAIN_OVERRIDE_PROPERTY_NAME)); } + LOG.info("Connection established. Auth Method: Pre-generated Access Token."); - return builder + GoogleCredentials credentials = builder .setAccessToken( AccessToken.newBuilder() .setTokenValue( authProperties.get(BigQueryJdbcUrlUtility.OAUTH_ACCESS_TOKEN_PROPERTY_NAME)) .build()) .build(); + + + if ("true".equals(authProperties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME))) { + credentials = credentials.createScoped( + Arrays.asList( + "https://www.googleapis.com/auth/bigquery", + "https://www.googleapis.com/auth/drive.readonly" + ) + ); + } + + return credentials; } static GoogleCredentials getPreGeneratedTokensCredentials( @@ -552,11 +564,22 @@ static UserCredentials getPreGeneratedRefreshTokenCredentials( userCredentialsBuilder.setUniverseDomain( overrideProperties.get(BigQueryJdbcUrlUtility.UNIVERSE_DOMAIN_OVERRIDE_PROPERTY_NAME)); } + + UserCredentials userCredentials = userCredentialsBuilder.build(); + + if ("true".equals(authProperties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME))) { + userCredentials = (UserCredentials) userCredentials.createScoped( + Arrays.asList( + "https://www.googleapis.com/auth/bigquery", + "https://www.googleapis.com/auth/drive.readonly" + ) + ); + } LOG.info("Connection established. Auth Method: Pre-generated Refresh Token."); - return userCredentialsBuilder.build(); + return userCredentials; } - private static GoogleCredentials getApplicationDefaultCredentials(String callerClassName) { + private static GoogleCredentials getApplicationDefaultCredentials(Map authProperties, String callerClassName) { LOG.finest("++enter++\t" + callerClassName); try { GoogleCredentials credentials = GoogleCredentials.getApplicationDefault(); @@ -571,6 +594,17 @@ private static GoogleCredentials getApplicationDefaultCredentials(String callerC LOG.info( "Connection established. Auth Method: Application Default Credentials, Principal: %s.", principal); + + if ("true".equals(authProperties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME))) { + credentials = credentials.createScoped( + Arrays.asList( + "https://www.googleapis.com/auth/bigquery", + "https://www.googleapis.com/auth/drive.readonly" + ) + ); + LOG.fine("Added Google Drive read-only scope to ADC credentials."); + } + return credentials; } catch (IOException exception) { // TODO throw exception @@ -616,16 +650,29 @@ private static GoogleCredentials getExternalAccountAuthCredentials( } } + GoogleCredentials credentials; if (credentialsPath != null) { - return ExternalAccountCredentials.fromStream( + credentials = ExternalAccountCredentials.fromStream( Files.newInputStream(Paths.get(credentialsPath))); } else if (jsonObject != null) { - return ExternalAccountCredentials.fromStream( + credentials = ExternalAccountCredentials.fromStream( new ByteArrayInputStream(jsonObject.toString().getBytes())); } else { throw new IllegalArgumentException( "Insufficient info provided for external authentication"); } + + if ("true".equals(authProperties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME))) { + credentials = credentials.createScoped( + Arrays.asList( + "https://www.googleapis.com/auth/bigquery", + "https://www.googleapis.com/auth/drive.readonly" + ) + ); + LOG.fine("Added Google Drive read-only scope to External Account credentials."); + } + + return credentials; } catch (IOException e) { throw new BigQueryJdbcRuntimeException(e); } @@ -634,7 +681,7 @@ private static GoogleCredentials getExternalAccountAuthCredentials( // This function checks if connection string contains configuration for // credentials impersonation. If not, it returns regular credentials object. // If impersonated service account is provided, returns Credentials object - // accomodating this information. + // accommodating this information. private static GoogleCredentials getServiceAccountImpersonatedCredentials( GoogleCredentials credentials, Map authProperties) { @@ -653,10 +700,18 @@ private static GoogleCredentials getServiceAccountImpersonatedCredentials( // Scopes has a default value, so it should never be null List impersonationScopes = - Arrays.asList( - authProperties - .get(BigQueryJdbcUrlUtility.OAUTH_SA_IMPERSONATION_SCOPES_PROPERTY_NAME) - .split(",")); + new java.util.ArrayList<>( + Arrays.asList( + authProperties + .get(BigQueryJdbcUrlUtility.OAUTH_SA_IMPERSONATION_SCOPES_PROPERTY_NAME) + .split(","))); + + if ("true".equals(authProperties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME))) { + if (!impersonationScopes.contains("https://www.googleapis.com/auth/drive.readonly")) { + impersonationScopes.add("https://www.googleapis.com/auth/drive.readonly"); + LOG.fine("Added Google Drive read-only scope to impersonation scopes."); + } + } // Token lifetime has a default value, so it should never be null String impersonationLifetime = From a3db96bad1a7fe35cbbcf61385ac1d2c49b00182 Mon Sep 17 00:00:00 2001 From: Neenu1995 Date: Fri, 17 Apr 2026 15:47:20 -0400 Subject: [PATCH 02/10] add unit tests --- .../jdbc/BigQueryJdbcOAuthUtilityTest.java | 37 +++++++++++++++++-- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtilityTest.java b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtilityTest.java index ac2a7a8661e0..2761874449ed 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtilityTest.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtilityTest.java @@ -356,7 +356,7 @@ public void testParseOAuthProperties_UserAccount_RequestDriveScopeEnabled() { "redactedClientSecret", properties.get(BigQueryJdbcUrlUtility.OAUTH_CLIENT_SECRET_PROPERTY_NAME)); assertEquals( - "1", properties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME)); + "true", properties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME)); } @Test @@ -369,7 +369,7 @@ public void testParseOAuthProperties_UserAccount_RequestDriveScopeDisabled() { BigQueryJdbcOAuthUtility.parseOAuthProperties( DataSource.fromUrl(url), this.getClass().getName()); assertEquals( - "0", properties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME)); + "false", properties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME)); } @Test @@ -381,7 +381,7 @@ public void testParseOAuthProperties_UserAccount_RequestDriveScopeDefault() { BigQueryJdbcOAuthUtility.parseOAuthProperties( DataSource.fromUrl(url), this.getClass().getName()); assertEquals( - String.valueOf(BigQueryJdbcUrlUtility.DEFAULT_REQUEST_GOOGLE_DRIVE_SCOPE_VALUE), + "false", properties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME)); } @@ -391,7 +391,7 @@ public void testGetUserAuthorizer_WithDriveScope() throws URISyntaxException { authProperties.put(BigQueryJdbcUrlUtility.OAUTH_CLIENT_ID_PROPERTY_NAME, "redactedClientId"); authProperties.put( BigQueryJdbcUrlUtility.OAUTH_CLIENT_SECRET_PROPERTY_NAME, "redactedClientSecret"); - authProperties.put(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME, "1"); + authProperties.put(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME, "true"); UserAuthorizer authorizer = BigQueryJdbcOAuthUtility.getUserAuthorizer( @@ -432,6 +432,35 @@ public void testGetUserAuthorizer_InvalidDriveScopeValue() throws URISyntaxExcep assertFalse(authorizer.getScopes().contains("https://www.googleapis.com/auth/drive.readonly")); } + @Test + public void testParseOAuthProperties_ServiceAccount_RequestDriveScopeEnabled() { + String url = + "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;" + + "OAuthType=0;OAuthServiceAcctEmail=dummy@email.com;OAuthPvtKey=key;" + + "RequestGoogleDriveScope=1;"; + Map properties = + BigQueryJdbcOAuthUtility.parseOAuthProperties( + DataSource.fromUrl(url), this.getClass().getName()); + assertEquals( + "true", properties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME)); + } + + @Test + public void testGetCredentialsForPreGeneratedToken_WithDriveScope() { + Map authProperties = + BigQueryJdbcOAuthUtility.parseOAuthProperties( + DataSource.fromUrl( + "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;" + + "OAuthType=2;ProjectId=MyBigQueryProject;" + + "OAuthAccessToken=RedactedToken;" + + "RequestGoogleDriveScope=1;"), + null); + + GoogleCredentials credentials = + BigQueryJdbcOAuthUtility.getCredentials(authProperties, Collections.EMPTY_MAP, null); + assertThat(credentials).isNotNull(); + } + @Test public void testParseUserImpersonationDefault() { String connectionUri = From 313371bfeb629296ff5dbb4b9a196429ec59b47e Mon Sep 17 00:00:00 2001 From: cloud-java-bot Date: Fri, 17 Apr 2026 23:31:24 +0000 Subject: [PATCH 03/10] chore: generate libraries at Fri Apr 17 23:29:25 UTC 2026 --- java-iam/.repo-metadata.json | 1 - java-iam/README.md | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/java-iam/.repo-metadata.json b/java-iam/.repo-metadata.json index fa9ab8c76a75..d35667f774d9 100644 --- a/java-iam/.repo-metadata.json +++ b/java-iam/.repo-metadata.json @@ -10,7 +10,6 @@ "repo": "googleapis/google-cloud-java", "repo_short": "java-iam", "distribution_name": "com.google.cloud:google-iam-policy", - "api_id": "iam.googleapis.com", "library_type": "GAPIC_AUTO", "requires_billing": true, "excluded_dependencies": "google-iam-policy", diff --git a/java-iam/README.md b/java-iam/README.md index a31d56fecfdc..b5f33684f9cf 100644 --- a/java-iam/README.md +++ b/java-iam/README.md @@ -188,7 +188,7 @@ Java is a registered trademark of Oracle and/or its affiliates. [code-of-conduct]: https://github.com/googleapis/google-cloud-java/blob/main/CODE_OF_CONDUCT.md#contributor-code-of-conduct [license]: https://github.com/googleapis/google-cloud-java/blob/main/LICENSE [enable-billing]: https://cloud.google.com/apis/docs/getting-started#enabling_billing -[enable-api]: https://console.cloud.google.com/flows/enableapi?apiid=iam.googleapis.com + [libraries-bom]: https://github.com/GoogleCloudPlatform/cloud-opensource-java/wiki/The-Google-Cloud-Platform-Libraries-BOM [shell_img]: https://gstatic.com/cloudssh/images/open-btn.png From c1bed227bd56e06c3d58d98b6e84e2898f435fca Mon Sep 17 00:00:00 2001 From: Neenu1995 Date: Fri, 17 Apr 2026 19:41:28 -0400 Subject: [PATCH 04/10] avoid duplication of hardcoded OAuth scopes --- .../jdbc/BigQueryJdbcOAuthUtility.java | 119 +++++++++--------- .../bigquery/jdbc/BigQueryJdbcUrlUtility.java | 5 +- .../jdbc/BigQueryJdbcOAuthUtilityTest.java | 5 +- 3 files changed, 64 insertions(+), 65 deletions(-) diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java index 6fdf8a8ade51..50f86b327db1 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java @@ -80,6 +80,12 @@ final class BigQueryJdbcOAuthUtility { + "Thank you for using JDBC Driver for Google BigQuery!\n" + "You may now close the window."; + static final String BIGQUERY_SCOPE = "https://www.googleapis.com/auth/bigquery"; + static final String DRIVE_READONLY_SCOPE = "https://www.googleapis.com/auth/drive.readonly"; + + static final List DEFAULT_SCOPES = Arrays.asList(BIGQUERY_SCOPE); + static final List DRIVE_SCOPES = Arrays.asList(BIGQUERY_SCOPE, DRIVE_READONLY_SCOPE); + private static final int USER_AUTH_TIMEOUT_MS = 120000; private static final BigQueryJdbcCustomLogger LOG = new BigQueryJdbcCustomLogger(BigQueryJdbcOAuthUtility.class.getName()); @@ -119,15 +125,17 @@ static Map parseOAuthProperties(DataSource ds, String callerClas oauthProperties.put(BigQueryJdbcUrlUtility.OAUTH_TYPE_PROPERTY_NAME, String.valueOf(authType)); Integer reqGoogleDriveScope = ds.getRequestGoogleDriveScope(); - if( reqGoogleDriveScope != null){ - Boolean reqGoogleDriveScopeBool = BigQueryJdbcUrlUtility.convertIntToBoolean(String.valueOf(reqGoogleDriveScope), BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME); + if (reqGoogleDriveScope != null) { + Boolean reqGoogleDriveScopeBool = + BigQueryJdbcUrlUtility.convertIntToBoolean( + String.valueOf(reqGoogleDriveScope), + BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME); oauthProperties.put( BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME, String.valueOf(reqGoogleDriveScopeBool)); LOG.fine("RequestGoogleDriveScope parsed."); } - switch (authType) { case GOOGLE_SERVICE_ACCOUNT: // For using a Google Service Account (OAuth Type 0) @@ -245,7 +253,7 @@ static Map parseOAuthProperties(DataSource ds, String callerClas BigQueryJdbcUrlUtility.OAUTH_SA_IMPERSONATION_SCOPES_PROPERTY_NAME, ds.getOAuthSAImpersonationScopes() != null ? ds.getOAuthSAImpersonationScopes() - : BigQueryJdbcUrlUtility.DEFAULT_OAUTH_SA_IMPERSONATION_SCOPES_VALUE); + : BIGQUERY_SCOPE); oauthProperties.put( BigQueryJdbcUrlUtility.OAUTH_SA_IMPERSONATION_TOKEN_LIFETIME_PROPERTY_NAME, ds.getOAuthSAImpersonationTokenLifetime() != null @@ -379,11 +387,11 @@ private static GoogleCredentials getGoogleServiceAccountCredentials( builder.setUniverseDomain( overrideProperties.get(BigQueryJdbcUrlUtility.UNIVERSE_DOMAIN_OVERRIDE_PROPERTY_NAME)); } - if ("true".equals(authProperties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME))){ - builder.setScopes( - Arrays.asList( - "https://www.googleapis.com/auth/bigquery", - "https://www.googleapis.com/auth/drive.readonly")); + if ("true" + .equals( + authProperties.get( + BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME))) { + builder.setScopes(DRIVE_SCOPES); LOG.fine("Added Google Drive read-only scope to Service Account builder."); } } catch (URISyntaxException | IOException e) { @@ -418,11 +426,12 @@ static UserAuthorizer getUserAuthorizer( userAuthorizerBuilder.setTokenServerUri( new URI(overrideProperties.get(BigQueryJdbcUrlUtility.OAUTH2_TOKEN_URI_PROPERTY_NAME))); } - List scopes = new ArrayList<>(); - scopes.add("https://www.googleapis.com/auth/bigquery"); + List scopes = new java.util.ArrayList<>(DEFAULT_SCOPES); - if ("true".equals(authProperties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME))) { - scopes.add("https://www.googleapis.com/auth/drive.readonly"); + if ("true" + .equals( + authProperties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME))) { + scopes.add(DRIVE_READONLY_SCOPE); LOG.fine("Added Google Drive read-only scope to User Account builder."); } @@ -501,22 +510,19 @@ private static GoogleCredentials getPreGeneratedAccessTokenCredentials( } LOG.info("Connection established. Auth Method: Pre-generated Access Token."); - GoogleCredentials credentials = builder - .setAccessToken( - AccessToken.newBuilder() - .setTokenValue( - authProperties.get(BigQueryJdbcUrlUtility.OAUTH_ACCESS_TOKEN_PROPERTY_NAME)) - .build()) - .build(); - - - if ("true".equals(authProperties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME))) { - credentials = credentials.createScoped( - Arrays.asList( - "https://www.googleapis.com/auth/bigquery", - "https://www.googleapis.com/auth/drive.readonly" - ) - ); + GoogleCredentials credentials = + builder + .setAccessToken( + AccessToken.newBuilder() + .setTokenValue( + authProperties.get(BigQueryJdbcUrlUtility.OAUTH_ACCESS_TOKEN_PROPERTY_NAME)) + .build()) + .build(); + + if ("true" + .equals( + authProperties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME))) { + credentials = credentials.createScoped(DRIVE_SCOPES); } return credentials; @@ -567,19 +573,17 @@ static UserCredentials getPreGeneratedRefreshTokenCredentials( UserCredentials userCredentials = userCredentialsBuilder.build(); - if ("true".equals(authProperties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME))) { - userCredentials = (UserCredentials) userCredentials.createScoped( - Arrays.asList( - "https://www.googleapis.com/auth/bigquery", - "https://www.googleapis.com/auth/drive.readonly" - ) - ); + if ("true" + .equals( + authProperties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME))) { + userCredentials = (UserCredentials) userCredentials.createScoped(DRIVE_SCOPES); } LOG.info("Connection established. Auth Method: Pre-generated Refresh Token."); return userCredentials; } - private static GoogleCredentials getApplicationDefaultCredentials(Map authProperties, String callerClassName) { + private static GoogleCredentials getApplicationDefaultCredentials( + Map authProperties, String callerClassName) { LOG.finest("++enter++\t" + callerClassName); try { GoogleCredentials credentials = GoogleCredentials.getApplicationDefault(); @@ -595,13 +599,11 @@ private static GoogleCredentials getApplicationDefaultCredentials(Map> eldes static final String HTAPI_ACTIVATION_RATIO_PROPERTY_NAME = "HighThroughputActivationRatio"; static final String KMS_KEY_NAME_PROPERTY_NAME = "KMSKeyName"; static final String QUERY_PROPERTIES_NAME = "QueryProperties"; - static final int DEFAULT_HTAPI_ACTIVATION_RATIO_VALUE = - 2; // TODO: to adjust this value before private preview based on performance testing. + static final int DEFAULT_HTAPI_ACTIVATION_RATIO_VALUE = 2; static final String HTAPI_MIN_TABLE_SIZE_PROPERTY_NAME = "HighThroughputMinTableSize"; static final int DEFAULT_HTAPI_MIN_TABLE_SIZE_VALUE = 100; static final int DEFAULT_OAUTH_TYPE_VALUE = -1; @@ -86,8 +85,6 @@ protected boolean removeEldestEntry(Map.Entry> eldes static final String DEFAULT_OAUTH_SA_IMPERSONATION_CHAIN_VALUE = null; static final String OAUTH_SA_IMPERSONATION_SCOPES_PROPERTY_NAME = "ServiceAccountImpersonationScopes"; - static final String DEFAULT_OAUTH_SA_IMPERSONATION_SCOPES_VALUE = - "https://www.googleapis.com/auth/bigquery"; static final String OAUTH_SA_IMPERSONATION_TOKEN_LIFETIME_PROPERTY_NAME = "ServiceAccountImpersonationTokenLifetime"; static final String DEFAULT_OAUTH_SA_IMPERSONATION_TOKEN_LIFETIME_VALUE = "3600"; diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtilityTest.java b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtilityTest.java index 2761874449ed..92ff47d19293 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtilityTest.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtilityTest.java @@ -381,8 +381,7 @@ public void testParseOAuthProperties_UserAccount_RequestDriveScopeDefault() { BigQueryJdbcOAuthUtility.parseOAuthProperties( DataSource.fromUrl(url), this.getClass().getName()); assertEquals( - "false", - properties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME)); + "false", properties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME)); } @Test @@ -473,7 +472,7 @@ public void testParseUserImpersonationDefault() { "impersonated", result.get(BigQueryJdbcUrlUtility.OAUTH_SA_IMPERSONATION_EMAIL_PROPERTY_NAME)); assertEquals( - BigQueryJdbcUrlUtility.DEFAULT_OAUTH_SA_IMPERSONATION_SCOPES_VALUE, + BigQueryJdbcOAuthUtility.BIGQUERY_SCOPE, result.get(BigQueryJdbcUrlUtility.OAUTH_SA_IMPERSONATION_SCOPES_PROPERTY_NAME)); assertEquals( BigQueryJdbcUrlUtility.DEFAULT_OAUTH_SA_IMPERSONATION_TOKEN_LIFETIME_VALUE, From 14e2a5f4aa8f899c680d98f4ef86527f7ae5d1f4 Mon Sep 17 00:00:00 2001 From: Neenu1995 Date: Mon, 20 Apr 2026 15:00:20 -0400 Subject: [PATCH 05/10] move reqDriveScope property to connection layer --- .../bigquery/jdbc/BigQueryConnection.java | 9 ++- .../jdbc/BigQueryJdbcOAuthUtility.java | 65 ++++++------------- .../jdbc/BigQueryJdbcOAuthUtilityTest.java | 12 ++-- 3 files changed, 35 insertions(+), 51 deletions(-) diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryConnection.java b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryConnection.java index e60f0874c446..bfe0a847dc54 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryConnection.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryConnection.java @@ -139,6 +139,7 @@ public class BigQueryConnection extends BigQueryNoOpsConnection { Long listenerPoolSize; String partnerToken; DatabaseMetaData databaseMetaData; + Boolean reqGoogleDriveScope; BigQueryConnection(String url) throws IOException { this(url, DataSource.fromUrl(url)); @@ -171,9 +172,15 @@ public class BigQueryConnection extends BigQueryNoOpsConnection { this.overrideProperties.put( BigQueryJdbcUrlUtility.UNIVERSE_DOMAIN_OVERRIDE_PROPERTY_NAME, this.universeDomain); } + + Boolean reqGoogleDriveScopeBool = + BigQueryJdbcUrlUtility.convertIntToBoolean( + String.valueOf(ds.getRequestGoogleDriveScope()), + BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME); + this.credentials = BigQueryJdbcOAuthUtility.getCredentials( - authProperties, overrideProperties, this.connectionClassName); + authProperties, overrideProperties, reqGoogleDriveScopeBool, this.connectionClassName); String defaultDatasetString = ds.getDefaultDataset(); if (defaultDatasetString == null || defaultDatasetString.trim().isEmpty()) { this.defaultDataset = null; diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java index 50f86b327db1..b9511908443d 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java @@ -83,8 +83,9 @@ final class BigQueryJdbcOAuthUtility { static final String BIGQUERY_SCOPE = "https://www.googleapis.com/auth/bigquery"; static final String DRIVE_READONLY_SCOPE = "https://www.googleapis.com/auth/drive.readonly"; - static final List DEFAULT_SCOPES = Arrays.asList(BIGQUERY_SCOPE); - static final List DRIVE_SCOPES = Arrays.asList(BIGQUERY_SCOPE, DRIVE_READONLY_SCOPE); + static final List DEFAULT_BIGQUERY_SCOPES = Arrays.asList(BIGQUERY_SCOPE); + static final List BIGQUERY_WITH_DRIVE_SCOPES = + Arrays.asList(BIGQUERY_SCOPE, DRIVE_READONLY_SCOPE); private static final int USER_AUTH_TIMEOUT_MS = 120000; private static final BigQueryJdbcCustomLogger LOG = @@ -272,6 +273,7 @@ static Map parseOAuthProperties(DataSource ds, String callerClas static GoogleCredentials getCredentials( Map authProperties, Map overrideProperties, + Boolean reqGoogleDriveScopeBool, String callerClassName) { LOG.finest("++enter++\t" + callerClassName); @@ -294,15 +296,24 @@ static GoogleCredentials getCredentials( break; case APPLICATION_DEFAULT_CREDENTIALS: // This auth method doesn't support service account impersonation - return getApplicationDefaultCredentials(authProperties, callerClassName); + + credentials = getApplicationDefaultCredentials(authProperties, callerClassName); + break; case EXTERNAL_ACCOUNT_AUTH: // This auth method doesn't support service account impersonation - return getExternalAccountAuthCredentials(authProperties, callerClassName); + credentials = getExternalAccountAuthCredentials(authProperties, callerClassName); + break; default: throw new IllegalStateException(OAUTH_TYPE_ERROR_MESSAGE); } - return getServiceAccountImpersonatedCredentials(credentials, authProperties); + if (reqGoogleDriveScopeBool) { + credentials = credentials.createScoped(BIGQUERY_WITH_DRIVE_SCOPES); + LOG.fine("Added Google Drive read-only scope centrally to GoogleCredentials."); + } + + return getServiceAccountImpersonatedCredentials( + credentials, reqGoogleDriveScopeBool, authProperties); } private static boolean isFileExists(String filename) { @@ -387,13 +398,6 @@ private static GoogleCredentials getGoogleServiceAccountCredentials( builder.setUniverseDomain( overrideProperties.get(BigQueryJdbcUrlUtility.UNIVERSE_DOMAIN_OVERRIDE_PROPERTY_NAME)); } - if ("true" - .equals( - authProperties.get( - BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME))) { - builder.setScopes(DRIVE_SCOPES); - LOG.fine("Added Google Drive read-only scope to Service Account builder."); - } } catch (URISyntaxException | IOException e) { LOG.severe("Validation failure for Service Account credentials."); throw new BigQueryJdbcRuntimeException(e); @@ -426,7 +430,7 @@ static UserAuthorizer getUserAuthorizer( userAuthorizerBuilder.setTokenServerUri( new URI(overrideProperties.get(BigQueryJdbcUrlUtility.OAUTH2_TOKEN_URI_PROPERTY_NAME))); } - List scopes = new java.util.ArrayList<>(DEFAULT_SCOPES); + List scopes = new java.util.ArrayList<>(DEFAULT_BIGQUERY_SCOPES); if ("true" .equals( @@ -519,12 +523,6 @@ private static GoogleCredentials getPreGeneratedAccessTokenCredentials( .build()) .build(); - if ("true" - .equals( - authProperties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME))) { - credentials = credentials.createScoped(DRIVE_SCOPES); - } - return credentials; } @@ -573,11 +571,6 @@ static UserCredentials getPreGeneratedRefreshTokenCredentials( UserCredentials userCredentials = userCredentialsBuilder.build(); - if ("true" - .equals( - authProperties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME))) { - userCredentials = (UserCredentials) userCredentials.createScoped(DRIVE_SCOPES); - } LOG.info("Connection established. Auth Method: Pre-generated Refresh Token."); return userCredentials; } @@ -599,14 +592,6 @@ private static GoogleCredentials getApplicationDefaultCredentials( "Connection established. Auth Method: Application Default Credentials, Principal: %s.", principal); - if ("true" - .equals( - authProperties.get( - BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME))) { - credentials = credentials.createScoped(DRIVE_SCOPES); - LOG.fine("Added Google Drive read-only scope to ADC credentials."); - } - return credentials; } catch (IOException exception) { // TODO throw exception @@ -665,14 +650,6 @@ private static GoogleCredentials getExternalAccountAuthCredentials( "Insufficient info provided for external authentication"); } - if ("true" - .equals( - authProperties.get( - BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME))) { - credentials = credentials.createScoped(DRIVE_SCOPES); - LOG.fine("Added Google Drive read-only scope to External Account credentials."); - } - return credentials; } catch (IOException e) { throw new BigQueryJdbcRuntimeException(e); @@ -684,7 +661,9 @@ private static GoogleCredentials getExternalAccountAuthCredentials( // If impersonated service account is provided, returns Credentials object // accommodating this information. private static GoogleCredentials getServiceAccountImpersonatedCredentials( - GoogleCredentials credentials, Map authProperties) { + GoogleCredentials credentials, + Boolean reqGoogleDriveScopeBool, + Map authProperties) { String impersonationEmail = authProperties.get(BigQueryJdbcUrlUtility.OAUTH_SA_IMPERSONATION_EMAIL_PROPERTY_NAME); @@ -707,9 +686,7 @@ private static GoogleCredentials getServiceAccountImpersonatedCredentials( .get(BigQueryJdbcUrlUtility.OAUTH_SA_IMPERSONATION_SCOPES_PROPERTY_NAME) .split(","))); - if ("true" - .equals( - authProperties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME))) { + if (reqGoogleDriveScopeBool) { if (!impersonationScopes.contains(DRIVE_READONLY_SCOPE)) { impersonationScopes.add(DRIVE_READONLY_SCOPE); LOG.fine("Added Google Drive read-only scope to impersonation scopes."); diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtilityTest.java b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtilityTest.java index 92ff47d19293..db03b4786824 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtilityTest.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtilityTest.java @@ -109,7 +109,7 @@ public void testInvalidTokenUriForAuthType0() { DataSource.fromUrl(connectionString).getOverrideProperties(); try { - BigQueryJdbcOAuthUtility.getCredentials(oauthProperties, overrideProperties, null); + BigQueryJdbcOAuthUtility.getCredentials(oauthProperties, overrideProperties, false, null); Assertions.fail(); } catch (BigQueryJdbcRuntimeException e) { assertThat(e.getMessage()).contains("java.net.URISyntaxException"); @@ -165,7 +165,7 @@ public void testGetCredentialsForPreGeneratedToken() { null); GoogleCredentials credentials = - BigQueryJdbcOAuthUtility.getCredentials(authProperties, Collections.EMPTY_MAP, null); + BigQueryJdbcOAuthUtility.getCredentials(authProperties, Collections.EMPTY_MAP, false, null); assertThat(credentials).isNotNull(); } @@ -185,7 +185,7 @@ public void testGetCredentialsForPreGeneratedTokenTPC() throws IOException { Map overrideProperties = new HashMap<>(stringStringMap); GoogleCredentials credentials = - BigQueryJdbcOAuthUtility.getCredentials(authProperties, overrideProperties, null); + BigQueryJdbcOAuthUtility.getCredentials(authProperties, overrideProperties, false, null); assertThat(credentials.getUniverseDomain()).isEqualTo("testDomain"); } @@ -200,7 +200,7 @@ public void testGetCredentialsForApplicationDefault() { null); GoogleCredentials credentials = - BigQueryJdbcOAuthUtility.getCredentials(authProperties, null, null); + BigQueryJdbcOAuthUtility.getCredentials(authProperties, null, false, null); assertThat(credentials).isNotNull(); } @@ -456,7 +456,7 @@ public void testGetCredentialsForPreGeneratedToken_WithDriveScope() { null); GoogleCredentials credentials = - BigQueryJdbcOAuthUtility.getCredentials(authProperties, Collections.EMPTY_MAP, null); + BigQueryJdbcOAuthUtility.getCredentials(authProperties, Collections.EMPTY_MAP, true, null); assertThat(credentials).isNotNull(); } @@ -510,7 +510,7 @@ public void testGetServiceAccountImpersonatedCredentials() { .toString()), ""); GoogleCredentials credentials = - BigQueryJdbcOAuthUtility.getCredentials(authProperties, Collections.EMPTY_MAP, null); + BigQueryJdbcOAuthUtility.getCredentials(authProperties, Collections.EMPTY_MAP, false, null); assertThat(credentials).isInstanceOf(ImpersonatedCredentials.class); } From 071adfcb516d5dde6a2dc4a177db98ce53fcbeba Mon Sep 17 00:00:00 2001 From: Neenu1995 Date: Mon, 20 Apr 2026 15:02:30 -0400 Subject: [PATCH 06/10] cleanup --- .../jdbc/BigQueryJdbcOAuthUtility.java | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java index b9511908443d..3f3710ab1c68 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java @@ -125,18 +125,6 @@ static Map parseOAuthProperties(DataSource ds, String callerClas } oauthProperties.put(BigQueryJdbcUrlUtility.OAUTH_TYPE_PROPERTY_NAME, String.valueOf(authType)); - Integer reqGoogleDriveScope = ds.getRequestGoogleDriveScope(); - if (reqGoogleDriveScope != null) { - Boolean reqGoogleDriveScopeBool = - BigQueryJdbcUrlUtility.convertIntToBoolean( - String.valueOf(reqGoogleDriveScope), - BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME); - oauthProperties.put( - BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME, - String.valueOf(reqGoogleDriveScopeBool)); - LOG.fine("RequestGoogleDriveScope parsed."); - } - switch (authType) { case GOOGLE_SERVICE_ACCOUNT: // For using a Google Service Account (OAuth Type 0) @@ -432,13 +420,6 @@ static UserAuthorizer getUserAuthorizer( } List scopes = new java.util.ArrayList<>(DEFAULT_BIGQUERY_SCOPES); - if ("true" - .equals( - authProperties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME))) { - scopes.add(DRIVE_READONLY_SCOPE); - LOG.fine("Added Google Drive read-only scope to User Account builder."); - } - userAuthorizerBuilder.setScopes(scopes); return userAuthorizerBuilder.build(); From 578c84a998e009740702e2c8605c04e52e84cf8e Mon Sep 17 00:00:00 2001 From: Neenu1995 Date: Mon, 20 Apr 2026 15:11:51 -0400 Subject: [PATCH 07/10] revert old changes --- .../jdbc/BigQueryJdbcOAuthUtility.java | 21 ++++++------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java index 3f3710ab1c68..55854ada450c 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java @@ -418,9 +418,6 @@ static UserAuthorizer getUserAuthorizer( userAuthorizerBuilder.setTokenServerUri( new URI(overrideProperties.get(BigQueryJdbcUrlUtility.OAUTH2_TOKEN_URI_PROPERTY_NAME))); } - List scopes = new java.util.ArrayList<>(DEFAULT_BIGQUERY_SCOPES); - - userAuthorizerBuilder.setScopes(scopes); return userAuthorizerBuilder.build(); } @@ -550,14 +547,11 @@ static UserCredentials getPreGeneratedRefreshTokenCredentials( overrideProperties.get(BigQueryJdbcUrlUtility.UNIVERSE_DOMAIN_OVERRIDE_PROPERTY_NAME)); } - UserCredentials userCredentials = userCredentialsBuilder.build(); - LOG.info("Connection established. Auth Method: Pre-generated Refresh Token."); - return userCredentials; + return userCredentialsBuilder.build(); } - private static GoogleCredentials getApplicationDefaultCredentials( - Map authProperties, String callerClassName) { + private static GoogleCredentials getApplicationDefaultCredentials(String callerClassName) { LOG.finest("++enter++\t" + callerClassName); try { GoogleCredentials credentials = GoogleCredentials.getApplicationDefault(); @@ -620,18 +614,15 @@ private static GoogleCredentials getExternalAccountAuthCredentials( GoogleCredentials credentials; if (credentialsPath != null) { - credentials = - ExternalAccountCredentials.fromStream(Files.newInputStream(Paths.get(credentialsPath))); + return ExternalAccountCredentials.fromStream( + Files.newInputStream(Paths.get(credentialsPath))); } else if (jsonObject != null) { - credentials = - ExternalAccountCredentials.fromStream( - new ByteArrayInputStream(jsonObject.toString().getBytes())); + return ExternalAccountCredentials.fromStream( + new ByteArrayInputStream(jsonObject.toString().getBytes())); } else { throw new IllegalArgumentException( "Insufficient info provided for external authentication"); } - - return credentials; } catch (IOException e) { throw new BigQueryJdbcRuntimeException(e); } From 404d66a764ddddd254b683966fd7929547a4a7a0 Mon Sep 17 00:00:00 2001 From: Neenu1995 Date: Mon, 20 Apr 2026 15:17:24 -0400 Subject: [PATCH 08/10] revert unknown file changes --- java-iam-policy/.repo-metadata.json | 1 + java-iam-policy/README.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/java-iam-policy/.repo-metadata.json b/java-iam-policy/.repo-metadata.json index bf65bd5c8655..0d797eebf786 100644 --- a/java-iam-policy/.repo-metadata.json +++ b/java-iam-policy/.repo-metadata.json @@ -10,6 +10,7 @@ "repo": "googleapis/google-cloud-java", "repo_short": "java-iam-policy", "distribution_name": "com.google.cloud:google-iam-policy", + "api_id": "iam.googleapis.com", "library_type": "GAPIC_AUTO", "requires_billing": true, "excluded_dependencies": "google-iam-policy", diff --git a/java-iam-policy/README.md b/java-iam-policy/README.md index b5f33684f9cf..a31d56fecfdc 100644 --- a/java-iam-policy/README.md +++ b/java-iam-policy/README.md @@ -188,7 +188,7 @@ Java is a registered trademark of Oracle and/or its affiliates. [code-of-conduct]: https://github.com/googleapis/google-cloud-java/blob/main/CODE_OF_CONDUCT.md#contributor-code-of-conduct [license]: https://github.com/googleapis/google-cloud-java/blob/main/LICENSE [enable-billing]: https://cloud.google.com/apis/docs/getting-started#enabling_billing - +[enable-api]: https://console.cloud.google.com/flows/enableapi?apiid=iam.googleapis.com [libraries-bom]: https://github.com/GoogleCloudPlatform/cloud-opensource-java/wiki/The-Google-Cloud-Platform-Libraries-BOM [shell_img]: https://gstatic.com/cloudssh/images/open-btn.png From bc55edfed687731140b54d862a82a8a7a950cac4 Mon Sep 17 00:00:00 2001 From: Neenu1995 Date: Mon, 20 Apr 2026 15:56:50 -0400 Subject: [PATCH 09/10] fix tests --- .../bigquery/jdbc/BigQueryConnection.java | 4 +- .../jdbc/BigQueryJdbcOAuthUtility.java | 6 +- .../bigquery/jdbc/BigQueryConnectionTest.java | 24 ++++ .../jdbc/BigQueryJdbcOAuthUtilityTest.java | 123 ------------------ 4 files changed, 31 insertions(+), 126 deletions(-) diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryConnection.java b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryConnection.java index bfe0a847dc54..73bbb985799f 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryConnection.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryConnection.java @@ -173,14 +173,14 @@ public class BigQueryConnection extends BigQueryNoOpsConnection { BigQueryJdbcUrlUtility.UNIVERSE_DOMAIN_OVERRIDE_PROPERTY_NAME, this.universeDomain); } - Boolean reqGoogleDriveScopeBool = + this.reqGoogleDriveScope = BigQueryJdbcUrlUtility.convertIntToBoolean( String.valueOf(ds.getRequestGoogleDriveScope()), BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME); this.credentials = BigQueryJdbcOAuthUtility.getCredentials( - authProperties, overrideProperties, reqGoogleDriveScopeBool, this.connectionClassName); + authProperties, overrideProperties, this.reqGoogleDriveScope, this.connectionClassName); String defaultDatasetString = ds.getDefaultDataset(); if (defaultDatasetString == null || defaultDatasetString.trim().isEmpty()) { this.defaultDataset = null; diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java index 55854ada450c..f24193e45980 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java @@ -285,7 +285,7 @@ static GoogleCredentials getCredentials( case APPLICATION_DEFAULT_CREDENTIALS: // This auth method doesn't support service account impersonation - credentials = getApplicationDefaultCredentials(authProperties, callerClassName); + credentials = getApplicationDefaultCredentials(callerClassName); break; case EXTERNAL_ACCOUNT_AUTH: // This auth method doesn't support service account impersonation @@ -402,6 +402,9 @@ static UserAuthorizer getUserAuthorizer( throws URISyntaxException { LOG.finest("++enter++\t" + callerClassName); + List scopes = new ArrayList<>(); + scopes.add("https://www.googleapis.com/auth/bigquery"); + List responseTypes = new ArrayList<>(); responseTypes.add("code"); @@ -412,6 +415,7 @@ static UserAuthorizer getUserAuthorizer( UserAuthorizer.Builder userAuthorizerBuilder = UserAuthorizer.newBuilder() .setClientId(clientId) + .setScopes(scopes) .setCallbackUri(URI.create("http://localhost:" + port)); if (overrideProperties.containsKey(BigQueryJdbcUrlUtility.OAUTH2_TOKEN_URI_PROPERTY_NAME)) { diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryConnectionTest.java b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryConnectionTest.java index 4430ba4cf315..dddc7c771100 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryConnectionTest.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryConnectionTest.java @@ -413,4 +413,28 @@ public void testBigQueryJobCreationMode_default() throws Exception { bq.getOptions().getDefaultJobCreationMode(), JobCreationMode.JOB_CREATION_OPTIONAL); } } + + @Test + public void testWithDriveScopeTrue() throws Exception { + String url = BASE_URL + "RequestGoogleDriveScope=1;"; + try (BigQueryConnection connection = new BigQueryConnection(url)) { + assertTrue(connection.reqGoogleDriveScope); + } + } + + @Test + public void testWithDriveScopeFalse() throws Exception { + String url = BASE_URL + "RequestGoogleDriveScope=0;"; + try (BigQueryConnection connection = new BigQueryConnection(url)) { + assertFalse(connection.reqGoogleDriveScope); + } + } + + @Test + public void testWithDriveScopeDefault() throws Exception { + String url = BASE_URL; + try (BigQueryConnection connection = new BigQueryConnection(url)) { + assertFalse(connection.reqGoogleDriveScope); + } + } } diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtilityTest.java b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtilityTest.java index db03b4786824..3630f86133dc 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtilityTest.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtilityTest.java @@ -18,7 +18,6 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -338,128 +337,6 @@ public void testParseBYOIDProps() { assertThat(result.get("BYOID_TokenUri")).isEqualTo("https://testuri.com/v1/token"); } - @Test - public void testParseOAuthProperties_UserAccount_RequestDriveScopeEnabled() { - String url = - "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;" - + "OAuthType=1;OAuthClientId=redactedClientId;OAuthClientSecret=redactedClientSecret;" - + "RequestGoogleDriveScope=1;"; - Map properties = - BigQueryJdbcOAuthUtility.parseOAuthProperties( - DataSource.fromUrl(url), this.getClass().getName()); - assertEquals( - String.valueOf(BigQueryJdbcOAuthUtility.AuthType.GOOGLE_USER_ACCOUNT), - properties.get(BigQueryJdbcUrlUtility.OAUTH_TYPE_PROPERTY_NAME)); - assertEquals( - "redactedClientId", properties.get(BigQueryJdbcUrlUtility.OAUTH_CLIENT_ID_PROPERTY_NAME)); - assertEquals( - "redactedClientSecret", - properties.get(BigQueryJdbcUrlUtility.OAUTH_CLIENT_SECRET_PROPERTY_NAME)); - assertEquals( - "true", properties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME)); - } - - @Test - public void testParseOAuthProperties_UserAccount_RequestDriveScopeDisabled() { - String url = - "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;" - + "OAuthType=1;OAuthClientId=redactedClientId;OAuthClientSecret=redactedClientSecret;" - + "RequestGoogleDriveScope=0;"; - Map properties = - BigQueryJdbcOAuthUtility.parseOAuthProperties( - DataSource.fromUrl(url), this.getClass().getName()); - assertEquals( - "false", properties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME)); - } - - @Test - public void testParseOAuthProperties_UserAccount_RequestDriveScopeDefault() { - String url = - "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;" - + "OAuthType=1;OAuthClientId=redactedClientId;OAuthClientSecret=redactedClientSecret;"; - Map properties = - BigQueryJdbcOAuthUtility.parseOAuthProperties( - DataSource.fromUrl(url), this.getClass().getName()); - assertEquals( - "false", properties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME)); - } - - @Test - public void testGetUserAuthorizer_WithDriveScope() throws URISyntaxException { - Map authProperties = new HashMap<>(); - authProperties.put(BigQueryJdbcUrlUtility.OAUTH_CLIENT_ID_PROPERTY_NAME, "redactedClientId"); - authProperties.put( - BigQueryJdbcUrlUtility.OAUTH_CLIENT_SECRET_PROPERTY_NAME, "redactedClientSecret"); - authProperties.put(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME, "true"); - - UserAuthorizer authorizer = - BigQueryJdbcOAuthUtility.getUserAuthorizer( - authProperties, Collections.emptyMap(), 12345, this.getClass().getName()); - - assertTrue(authorizer.getScopes().contains("https://www.googleapis.com/auth/bigquery")); - assertTrue(authorizer.getScopes().contains("https://www.googleapis.com/auth/drive.readonly")); - assertEquals(2, authorizer.getScopes().size()); - } - - @Test - public void testGetUserAuthorizer_WithoutDriveScope() throws URISyntaxException { - Map authProperties = new HashMap<>(); - authProperties.put(BigQueryJdbcUrlUtility.OAUTH_CLIENT_ID_PROPERTY_NAME, "redactedClientId"); - authProperties.put( - BigQueryJdbcUrlUtility.OAUTH_CLIENT_SECRET_PROPERTY_NAME, "redactedClientSecret"); - authProperties.put(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME, "0"); - - UserAuthorizer authorizer = - BigQueryJdbcOAuthUtility.getUserAuthorizer( - authProperties, Collections.emptyMap(), 12345, this.getClass().getName()); - assertTrue(authorizer.getScopes().contains("https://www.googleapis.com/auth/bigquery")); - assertFalse(authorizer.getScopes().contains("https://www.googleapis.com/auth/drive.readonly")); - assertEquals(1, authorizer.getScopes().size()); - } - - @Test - public void testGetUserAuthorizer_InvalidDriveScopeValue() throws URISyntaxException { - Map authProperties = new HashMap<>(); - authProperties.put(BigQueryJdbcUrlUtility.OAUTH_CLIENT_ID_PROPERTY_NAME, "redactedClientId"); - authProperties.put( - BigQueryJdbcUrlUtility.OAUTH_CLIENT_SECRET_PROPERTY_NAME, "redactedClientSecret"); - authProperties.put( - BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME, "invalid_value"); - UserAuthorizer authorizer = - BigQueryJdbcOAuthUtility.getUserAuthorizer( - authProperties, Collections.emptyMap(), 12345, this.getClass().getName()); - assertFalse(authorizer.getScopes().contains("https://www.googleapis.com/auth/drive.readonly")); - } - - @Test - public void testParseOAuthProperties_ServiceAccount_RequestDriveScopeEnabled() { - String url = - "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;" - + "OAuthType=0;OAuthServiceAcctEmail=dummy@email.com;OAuthPvtKey=key;" - + "RequestGoogleDriveScope=1;"; - Map properties = - BigQueryJdbcOAuthUtility.parseOAuthProperties( - DataSource.fromUrl(url), this.getClass().getName()); - assertEquals( - "true", properties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME)); - } - - @Test - public void testGetCredentialsForPreGeneratedToken_WithDriveScope() { - Map authProperties = - BigQueryJdbcOAuthUtility.parseOAuthProperties( - DataSource.fromUrl( - "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;" - + "OAuthType=2;ProjectId=MyBigQueryProject;" - + "OAuthAccessToken=RedactedToken;" - + "RequestGoogleDriveScope=1;"), - null); - - GoogleCredentials credentials = - BigQueryJdbcOAuthUtility.getCredentials(authProperties, Collections.EMPTY_MAP, true, null); - assertThat(credentials).isNotNull(); - } - @Test public void testParseUserImpersonationDefault() { String connectionUri = From ccd45609708724d9ed967e32c30dd0130e19431a Mon Sep 17 00:00:00 2001 From: Neenu1995 Date: Tue, 21 Apr 2026 10:39:49 -0400 Subject: [PATCH 10/10] nit --- .../cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java index f24193e45980..eef61d393521 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java @@ -295,11 +295,6 @@ static GoogleCredentials getCredentials( throw new IllegalStateException(OAUTH_TYPE_ERROR_MESSAGE); } - if (reqGoogleDriveScopeBool) { - credentials = credentials.createScoped(BIGQUERY_WITH_DRIVE_SCOPES); - LOG.fine("Added Google Drive read-only scope centrally to GoogleCredentials."); - } - return getServiceAccountImpersonatedCredentials( credentials, reqGoogleDriveScopeBool, authProperties); } @@ -616,7 +611,6 @@ private static GoogleCredentials getExternalAccountAuthCredentials( } } - GoogleCredentials credentials; if (credentialsPath != null) { return ExternalAccountCredentials.fromStream( Files.newInputStream(Paths.get(credentialsPath))); @@ -644,6 +638,10 @@ private static GoogleCredentials getServiceAccountImpersonatedCredentials( String impersonationEmail = authProperties.get(BigQueryJdbcUrlUtility.OAUTH_SA_IMPERSONATION_EMAIL_PROPERTY_NAME); if (impersonationEmail == null || impersonationEmail.isEmpty()) { + if (reqGoogleDriveScopeBool) { + credentials = credentials.createScoped(BIGQUERY_WITH_DRIVE_SCOPES); + LOG.fine("Added Google Drive read-only scope to GoogleCredentials."); + } return credentials; }