From d5331fb38f795364d6172aca5c3024411b308a7d Mon Sep 17 00:00:00 2001 From: Hector Castejon Diaz Date: Mon, 9 Feb 2026 13:55:00 +0000 Subject: [PATCH 1/5] test --- .../databricks/sdk/core/DatabricksConfig.java | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/DatabricksConfig.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/DatabricksConfig.java index 23fd990b9..ff2d6c2f0 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/DatabricksConfig.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/DatabricksConfig.java @@ -798,15 +798,18 @@ private OpenIDConnectEndpoints fetchDefaultOidcEndpoints() throws IOException { } if (isAzure() && getAzureClientId() != null) { - Request request = new Request("GET", getHost() + "/oidc/oauth2/v2.0/authorize"); - request.setRedirectionBehavior(false); - Response resp = getHttpClient().execute(request); - String realAuthUrl = resp.getFirstHeader("location"); - if (realAuthUrl == null) { - return null; + ApiClient apiClient = + new ApiClient.Builder() + .withHttpClient(getHttpClient()) + .withGetHostFunc(v -> getHost()) + .build(); + try { + return apiClient.execute( + new Request("GET", "/oidc/.well-known/oauth-authorization-server"), + OpenIDConnectEndpoints.class); + } catch (IOException e) { + throw new DatabricksException("IO error: " + e.getMessage(), e); } - return new OpenIDConnectEndpoints( - realAuthUrl.replaceAll("/authorize", "/token"), realAuthUrl); } if (isAccountClient() && getAccountId() != null) { String prefix = getHost() + "/oidc/accounts/" + getAccountId(); From 7ca3b060776266399da1babac5ad053d27106d9e Mon Sep 17 00:00:00 2001 From: Hector Castejon Diaz Date: Tue, 10 Feb 2026 11:09:14 +0000 Subject: [PATCH 2/5] Add new OIDC Auth integration tests Add integration tests for Databricks Service Principal (M2M) and Azure Client Secret authentication types. This increases coverage for existing Auth types by adding: - Workspace OAuth M2M authentication test - Workspace Azure Client Secret authentication test - Account OAuth M2M authentication test - Account Azure Client Secret authentication test These tests verify that authentication works correctly by making API calls and validating responses. Co-Authored-By: Claude Sonnet 4.5 --- .../integration/DatabricksOidcAccountIT.java | 73 +++++++++++++++++++ .../DatabricksOidcWorkspaceIT.java | 72 ++++++++++++++++++ 2 files changed, 145 insertions(+) create mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/DatabricksOidcAccountIT.java create mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/integration/DatabricksOidcWorkspaceIT.java diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/DatabricksOidcAccountIT.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/DatabricksOidcAccountIT.java new file mode 100644 index 000000000..6e7f31e66 --- /dev/null +++ b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/DatabricksOidcAccountIT.java @@ -0,0 +1,73 @@ +package com.databricks.sdk.integration; + +import com.databricks.sdk.AccountClient; +import com.databricks.sdk.core.DatabricksConfig; +import com.databricks.sdk.integration.framework.EnvContext; +import com.databricks.sdk.integration.framework.EnvOrSkip; +import com.databricks.sdk.integration.framework.EnvTest; +import com.databricks.sdk.service.iam.ListAccountServicePrincipalsRequest; +import com.databricks.sdk.service.iam.ServicePrincipal; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@ExtendWith(EnvTest.class) +@EnvContext("account") +public class DatabricksOidcAccountIT { + private static final Logger LOG = LoggerFactory.getLogger(DatabricksOidcAccountIT.class); + + @Test + void testAccountOAuthM2MAuth( + @EnvOrSkip("CLOUD_ENV") String cloudEnv, + @EnvOrSkip("DATABRICKS_HOST") String host, + @EnvOrSkip("DATABRICKS_ACCOUNT_ID") String accountId, + @EnvOrSkip("TEST_DATABRICKS_CLIENT_ID") String clientId, + @EnvOrSkip("TEST_DATABRICKS_CLIENT_SECRET") String clientSecret) { + LOG.info("Cloud environment: {}", cloudEnv); + + // Create account client with OAuth M2M authentication + DatabricksConfig config = + new DatabricksConfig() + .setHost(host) + .setAccountId(accountId) + .setClientId(clientId) + .setClientSecret(clientSecret) + .setAuthType("oauth-m2m"); + + AccountClient ac = new AccountClient(config); + + // List service principals to verify authentication works + Iterable servicePrincipals = + ac.servicePrincipals().list(new ListAccountServicePrincipalsRequest()); + servicePrincipals.iterator().next(); + } + + @Test + void testAccountAzureClientSecretAuth( + @EnvOrSkip("CLOUD_ENV") String cloudEnv, + @EnvOrSkip("DATABRICKS_HOST") String host, + @EnvOrSkip("DATABRICKS_ACCOUNT_ID") String accountId, + @EnvOrSkip("ARM_CLIENT_ID") String azureClientId, + @EnvOrSkip("ARM_CLIENT_SECRET") String azureClientSecret, + @EnvOrSkip("ARM_TENANT_ID") String azureTenantId) { + LOG.info("Cloud environment: {}", cloudEnv); + + // Create account client with Azure client secret authentication + DatabricksConfig config = + new DatabricksConfig() + .setHost(host) + .setAccountId(accountId) + .setAzureClientId(azureClientId) + .setAzureClientSecret(azureClientSecret) + .setAzureTenantId(azureTenantId) + .setAuthType("azure-client-secret"); + + AccountClient ac = new AccountClient(config); + + // List service principals to verify authentication works + Iterable servicePrincipals = + ac.servicePrincipals().list(new ListAccountServicePrincipalsRequest()); + servicePrincipals.iterator().next(); + } +} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/DatabricksOidcWorkspaceIT.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/DatabricksOidcWorkspaceIT.java new file mode 100644 index 000000000..e81fd90c6 --- /dev/null +++ b/databricks-sdk-java/src/test/java/com/databricks/sdk/integration/DatabricksOidcWorkspaceIT.java @@ -0,0 +1,72 @@ +package com.databricks.sdk.integration; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import com.databricks.sdk.WorkspaceClient; +import com.databricks.sdk.core.DatabricksConfig; +import com.databricks.sdk.integration.framework.EnvContext; +import com.databricks.sdk.integration.framework.EnvOrSkip; +import com.databricks.sdk.integration.framework.EnvTest; +import com.databricks.sdk.service.iam.User; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@ExtendWith(EnvTest.class) +@EnvContext("ucws") +public class DatabricksOidcWorkspaceIT { + private static final Logger LOG = LoggerFactory.getLogger(DatabricksOidcWorkspaceIT.class); + + @Test + void testWorkspaceOAuthM2MAuth( + @EnvOrSkip("CLOUD_ENV") String cloudEnv, + @EnvOrSkip("DATABRICKS_HOST") String host, + @EnvOrSkip("TEST_DATABRICKS_CLIENT_ID") String clientId, + @EnvOrSkip("TEST_DATABRICKS_CLIENT_SECRET") String clientSecret) { + LOG.info("Cloud environment: {}", cloudEnv); + + // Create workspace client with OAuth M2M authentication + DatabricksConfig config = + new DatabricksConfig() + .setHost(host) + .setClientId(clientId) + .setClientSecret(clientSecret) + .setAuthType("oauth-m2m"); + + WorkspaceClient ws = new WorkspaceClient(config); + + // Call the "me" API + User me = ws.currentUser().me(); + + // Verify we got a valid response + assertNotNull(me.getUserName(), "Expected non-empty UserName"); + } + + @Test + void testWorkspaceAzureClientSecretAuth( + @EnvOrSkip("CLOUD_ENV") String cloudEnv, + @EnvOrSkip("DATABRICKS_HOST") String host, + @EnvOrSkip("ARM_CLIENT_ID") String azureClientId, + @EnvOrSkip("ARM_CLIENT_SECRET") String azureClientSecret, + @EnvOrSkip("ARM_TENANT_ID") String azureTenantId) { + LOG.info("Cloud environment: {}", cloudEnv); + + // Create workspace client with Azure client secret authentication + DatabricksConfig config = + new DatabricksConfig() + .setHost(host) + .setAzureClientId(azureClientId) + .setAzureClientSecret(azureClientSecret) + .setAzureTenantId(azureTenantId) + .setAuthType("azure-client-secret"); + + WorkspaceClient ws = new WorkspaceClient(config); + + // Call the "me" API + User me = ws.currentUser().me(); + + // Verify we got a valid response + assertNotNull(me.getUserName(), "Expected non-empty UserName"); + } +} From 132f54c42ccb2d2be654664d263c06ce69aa0258 Mon Sep 17 00:00:00 2001 From: Hector Castejon Diaz Date: Tue, 10 Feb 2026 11:11:41 +0000 Subject: [PATCH 3/5] Revert unintentional changes to DatabricksConfig.java --- .../databricks/sdk/core/DatabricksConfig.java | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/DatabricksConfig.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/DatabricksConfig.java index ff2d6c2f0..23fd990b9 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/DatabricksConfig.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/DatabricksConfig.java @@ -798,18 +798,15 @@ private OpenIDConnectEndpoints fetchDefaultOidcEndpoints() throws IOException { } if (isAzure() && getAzureClientId() != null) { - ApiClient apiClient = - new ApiClient.Builder() - .withHttpClient(getHttpClient()) - .withGetHostFunc(v -> getHost()) - .build(); - try { - return apiClient.execute( - new Request("GET", "/oidc/.well-known/oauth-authorization-server"), - OpenIDConnectEndpoints.class); - } catch (IOException e) { - throw new DatabricksException("IO error: " + e.getMessage(), e); + Request request = new Request("GET", getHost() + "/oidc/oauth2/v2.0/authorize"); + request.setRedirectionBehavior(false); + Response resp = getHttpClient().execute(request); + String realAuthUrl = resp.getFirstHeader("location"); + if (realAuthUrl == null) { + return null; } + return new OpenIDConnectEndpoints( + realAuthUrl.replaceAll("/authorize", "/token"), realAuthUrl); } if (isAccountClient() && getAccountId() != null) { String prefix = getHost() + "/oidc/accounts/" + getAccountId(); From 7ff54e5e2889e91841c4ed45dfda50f3b6bbb8ea Mon Sep 17 00:00:00 2001 From: Hector Castejon Diaz Date: Tue, 10 Feb 2026 11:39:14 +0000 Subject: [PATCH 4/5] Refactor: Extract OIDC endpoint fetching to reusable method Extract the logic for fetching OIDC endpoints from the well-known endpoint into a helper method fetchOidcEndpointsFromWellKnown(). This method is now reused for both the Azure client secret authentication case and the default case, reducing code duplication. Co-Authored-By: Claude Sonnet 4.5 --- .../databricks/sdk/core/DatabricksConfig.java | 38 +++++++++---------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/DatabricksConfig.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/DatabricksConfig.java index 23fd990b9..95c189897 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/DatabricksConfig.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/DatabricksConfig.java @@ -787,6 +787,21 @@ private OpenIDConnectEndpoints getUnifiedOidcEndpoints(String accountId) throws return new OpenIDConnectEndpoints(prefix + "/v1/token", prefix + "/v1/authorize"); } + private OpenIDConnectEndpoints fetchOidcEndpointsFromWellKnown() throws IOException { + ApiClient apiClient = + new ApiClient.Builder() + .withHttpClient(getHttpClient()) + .withGetHostFunc(v -> getHost()) + .build(); + try { + return apiClient.execute( + new Request("GET", "/oidc/.well-known/oauth-authorization-server"), + OpenIDConnectEndpoints.class); + } catch (IOException e) { + throw new DatabricksException("IO error: " + e.getMessage(), e); + } + } + private OpenIDConnectEndpoints fetchDefaultOidcEndpoints() throws IOException { if (getHost() == null) { return null; @@ -798,33 +813,14 @@ private OpenIDConnectEndpoints fetchDefaultOidcEndpoints() throws IOException { } if (isAzure() && getAzureClientId() != null) { - Request request = new Request("GET", getHost() + "/oidc/oauth2/v2.0/authorize"); - request.setRedirectionBehavior(false); - Response resp = getHttpClient().execute(request); - String realAuthUrl = resp.getFirstHeader("location"); - if (realAuthUrl == null) { - return null; - } - return new OpenIDConnectEndpoints( - realAuthUrl.replaceAll("/authorize", "/token"), realAuthUrl); + return fetchOidcEndpointsFromWellKnown(); } if (isAccountClient() && getAccountId() != null) { String prefix = getHost() + "/oidc/accounts/" + getAccountId(); return new OpenIDConnectEndpoints(prefix + "/v1/token", prefix + "/v1/authorize"); } - ApiClient apiClient = - new ApiClient.Builder() - .withHttpClient(getHttpClient()) - .withGetHostFunc(v -> getHost()) - .build(); - try { - return apiClient.execute( - new Request("GET", "/oidc/.well-known/oauth-authorization-server"), - OpenIDConnectEndpoints.class); - } catch (IOException e) { - throw new DatabricksException("IO error: " + e.getMessage(), e); - } + return fetchOidcEndpointsFromWellKnown(); } @Override From 1cc25db99a6ddc4d2528a51301ac44876c08c3d4 Mon Sep 17 00:00:00 2001 From: Hector Castejon Diaz Date: Tue, 10 Feb 2026 12:31:57 +0000 Subject: [PATCH 5/5] more fixes --- .../databricks/sdk/core/DatabricksConfig.java | 32 +++++++------------ 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/DatabricksConfig.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/DatabricksConfig.java index 95c189897..35127219c 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/DatabricksConfig.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/DatabricksConfig.java @@ -787,21 +787,6 @@ private OpenIDConnectEndpoints getUnifiedOidcEndpoints(String accountId) throws return new OpenIDConnectEndpoints(prefix + "/v1/token", prefix + "/v1/authorize"); } - private OpenIDConnectEndpoints fetchOidcEndpointsFromWellKnown() throws IOException { - ApiClient apiClient = - new ApiClient.Builder() - .withHttpClient(getHttpClient()) - .withGetHostFunc(v -> getHost()) - .build(); - try { - return apiClient.execute( - new Request("GET", "/oidc/.well-known/oauth-authorization-server"), - OpenIDConnectEndpoints.class); - } catch (IOException e) { - throw new DatabricksException("IO error: " + e.getMessage(), e); - } - } - private OpenIDConnectEndpoints fetchDefaultOidcEndpoints() throws IOException { if (getHost() == null) { return null; @@ -811,16 +796,23 @@ private OpenIDConnectEndpoints fetchDefaultOidcEndpoints() throws IOException { if (getHostType() == HostType.UNIFIED) { return getUnifiedOidcEndpoints(getAccountId()); } - - if (isAzure() && getAzureClientId() != null) { - return fetchOidcEndpointsFromWellKnown(); - } if (isAccountClient() && getAccountId() != null) { String prefix = getHost() + "/oidc/accounts/" + getAccountId(); return new OpenIDConnectEndpoints(prefix + "/v1/token", prefix + "/v1/authorize"); } - return fetchOidcEndpointsFromWellKnown(); + ApiClient apiClient = + new ApiClient.Builder() + .withHttpClient(getHttpClient()) + .withGetHostFunc(v -> getHost()) + .build(); + try { + return apiClient.execute( + new Request("GET", "/oidc/.well-known/oauth-authorization-server"), + OpenIDConnectEndpoints.class); + } catch (IOException e) { + throw new DatabricksException("IO error: " + e.getMessage(), e); + } } @Override