From 82fbbc2e5c9b9f38705df9a88ad0b6898d793b82 Mon Sep 17 00:00:00 2001 From: Hector Castejon Diaz Date: Wed, 25 Feb 2026 10:15:04 +0000 Subject: [PATCH 1/3] Add HostMetadata class and getHostMetadata() Adds `HostMetadata` and a package-private `getHostMetadata()` on `DatabricksConfig` for parsing the `/.well-known/databricks-config` discovery endpoint. The method returns raw metadata with no substitution (e.g. `{account_id}` placeholders are left as-is), keeping it a pure discovery primitive. Callers decide how to interpret the result. --- .../databricks/sdk/core/DatabricksConfig.java | 27 +++++++++ .../sdk/core/oauth/HostMetadata.java | 42 +++++++++++++ .../sdk/core/DatabricksConfigTest.java | 59 +++++++++++++++++++ 3 files changed, 128 insertions(+) create mode 100644 databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/HostMetadata.java 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 8388c218e..006dee40d 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 @@ -5,6 +5,7 @@ import com.databricks.sdk.core.http.Request; import com.databricks.sdk.core.http.Response; import com.databricks.sdk.core.oauth.ErrorTokenSource; +import com.databricks.sdk.core.oauth.HostMetadata; import com.databricks.sdk.core.oauth.OAuthHeaderFactory; import com.databricks.sdk.core.oauth.OpenIDConnectEndpoints; import com.databricks.sdk.core.oauth.TokenSource; @@ -800,6 +801,32 @@ public OpenIDConnectEndpoints getDatabricksOidcEndpoints() throws IOException { return fetchOidcEndpointsFromDiscovery(); } + /** + * [Experimental] Fetch the raw Databricks well-known configuration from + * {host}/.well-known/databricks-config. + * + *

Note: This API is experimental and may change or be removed in future releases + * without notice. + * + * @return Parsed {@link HostMetadata} as returned by the server. + * @throws DatabricksException if the request fails or the server returns a non-200 status. + */ + HostMetadata getHostMetadata() throws IOException { + String url = host + "/.well-known/databricks-config"; + try { + Request request = new Request("GET", url); + Response resp = getHttpClient().execute(request); + if (resp.getStatusCode() != 200) { + throw new DatabricksException( + "Failed to fetch host metadata from " + url + ": HTTP " + resp.getStatusCode()); + } + return new ObjectMapper().readValue(resp.getBody(), HostMetadata.class); + } catch (IOException e) { + throw new DatabricksException( + "Failed to fetch host metadata from " + url + ": " + e.getMessage(), e); + } + } + private OpenIDConnectEndpoints fetchOidcEndpointsFromDiscovery() { try { Request request = new Request("GET", discoveryUrl); diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/HostMetadata.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/HostMetadata.java new file mode 100644 index 000000000..d45844262 --- /dev/null +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/HostMetadata.java @@ -0,0 +1,42 @@ +package com.databricks.sdk.core.oauth; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * [Experimental] Parsed response from the /.well-known/databricks-config discovery endpoint. + * + *

Note: This API is experimental and may change or be removed in future releases without + * notice. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class HostMetadata { + @JsonProperty("oidc_endpoint") + private String oidcEndpoint; + + @JsonProperty("account_id") + private String accountId; + + @JsonProperty("workspace_id") + private String workspaceId; + + public HostMetadata() {} + + public HostMetadata(String oidcEndpoint, String accountId, String workspaceId) { + this.oidcEndpoint = oidcEndpoint; + this.accountId = accountId; + this.workspaceId = workspaceId; + } + + public String getOidcEndpoint() { + return oidcEndpoint; + } + + public String getAccountId() { + return accountId; + } + + public String getWorkspaceId() { + return workspaceId; + } +} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/core/DatabricksConfigTest.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/core/DatabricksConfigTest.java index ec7f0395f..55bbfb285 100644 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/core/DatabricksConfigTest.java +++ b/databricks-sdk-java/src/test/java/com/databricks/sdk/core/DatabricksConfigTest.java @@ -6,6 +6,7 @@ import com.databricks.sdk.core.commons.CommonsHttpClient; import com.databricks.sdk.core.http.HttpClient; import com.databricks.sdk.core.oauth.ErrorTokenSource; +import com.databricks.sdk.core.oauth.HostMetadata; import com.databricks.sdk.core.oauth.OAuthHeaderFactory; import com.databricks.sdk.core.oauth.OpenIDConnectEndpoints; import com.databricks.sdk.core.oauth.Token; @@ -421,4 +422,62 @@ public void testGetClientTypeAccountOnUnified() { .setExperimentalIsUnifiedHost(true) .getClientType()); } + + // --- HostMetadata tests --- + + private static final String DUMMY_ACCOUNT_ID = "00000000-0000-0000-0000-000000000001"; + private static final String DUMMY_WORKSPACE_ID = "111111111111111"; + + private static Environment emptyEnv() { + return new Environment(new HashMap<>(), new ArrayList<>(), System.getProperty("os.name")); + } + + @Test + public void testGetHostMetadataWorkspaceStaticOidcEndpoint() throws IOException { + String response = + "{\"oidc_endpoint\":\"https://ws.databricks.com/oidc\"," + + "\"account_id\":\"" + + DUMMY_ACCOUNT_ID + + "\"," + + "\"workspace_id\":\"" + + DUMMY_WORKSPACE_ID + + "\"}"; + try (FixtureServer server = + new FixtureServer().with("GET", "/.well-known/databricks-config", response, 200)) { + DatabricksConfig config = new DatabricksConfig().setHost(server.getUrl()); + config.resolve(emptyEnv()); + HostMetadata meta = config.getHostMetadata(); + assertEquals("https://ws.databricks.com/oidc", meta.getOidcEndpoint()); + assertEquals(DUMMY_ACCOUNT_ID, meta.getAccountId()); + assertEquals(DUMMY_WORKSPACE_ID, meta.getWorkspaceId()); + } + } + + @Test + public void testGetHostMetadataAccountRawOidcTemplate() throws IOException { + String response = + "{\"oidc_endpoint\":\"https://acc.databricks.com/oidc/accounts/{account_id}\"}"; + try (FixtureServer server = + new FixtureServer().with("GET", "/.well-known/databricks-config", response, 200)) { + DatabricksConfig config = new DatabricksConfig().setHost(server.getUrl()); + config.resolve(emptyEnv()); + HostMetadata meta = config.getHostMetadata(); + assertEquals( + "https://acc.databricks.com/oidc/accounts/{account_id}", meta.getOidcEndpoint()); + assertNull(meta.getAccountId()); + assertNull(meta.getWorkspaceId()); + } + } + + @Test + public void testGetHostMetadataRaisesOnHttpError() throws IOException { + try (FixtureServer server = + new FixtureServer().with("GET", "/.well-known/databricks-config", "{}", 404)) { + DatabricksConfig config = new DatabricksConfig().setHost(server.getUrl()); + config.resolve(emptyEnv()); + DatabricksException ex = + assertThrows(DatabricksException.class, () -> config.getHostMetadata()); + assertTrue(ex.getMessage().contains("Failed to fetch host metadata")); + } + } } From adbceef3cc10ffef3e5844fe09f58c210f922f6a Mon Sep 17 00:00:00 2001 From: Hector Castejon Diaz Date: Wed, 25 Feb 2026 10:17:21 +0000 Subject: [PATCH 2/3] Add tests for discoveryUrl OIDC endpoint resolution Adds tests covering: - DATABRICKS_DISCOVERY_URL env var is loaded into Config - getDatabricksOidcEndpoints() short-circuits to discoveryUrl when set The underlying implementation (discoveryUrl config field and getDatabricksOidcEndpoints() short-circuit) was already present in the Java SDK. Mirrors the Python SDK's get_endpoints_from_url() addition. --- .../sdk/core/DatabricksConfigTest.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/core/DatabricksConfigTest.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/core/DatabricksConfigTest.java index 55bbfb285..01726c757 100644 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/core/DatabricksConfigTest.java +++ b/databricks-sdk-java/src/test/java/com/databricks/sdk/core/DatabricksConfigTest.java @@ -480,4 +480,36 @@ public void testGetHostMetadataRaisesOnHttpError() throws IOException { assertTrue(ex.getMessage().contains("Failed to fetch host metadata")); } } + + // --- discoveryUrl / OIDC endpoint tests --- + + @Test + public void testDiscoveryUrlFromEnv() { + Map env = new HashMap<>(); + env.put("DATABRICKS_DISCOVERY_URL", "https://custom.idp.example.com/oidc"); + DatabricksConfig config = new DatabricksConfig(); + config.resolve(new Environment(env, new ArrayList<>(), System.getProperty("os.name"))); + assertEquals("https://custom.idp.example.com/oidc", config.getDiscoveryUrl()); + } + + @Test + public void testDatabricksOidcEndpointsUsesDiscoveryUrl() throws IOException { + String discoveryUrlSuffix = "/oidc"; + String discoveryUrlResponse = + "{\"authorization_endpoint\":\"https://ws.databricks.com/oidc/v1/authorize\"," + + "\"token_endpoint\":\"https://ws.databricks.com/oidc/v1/token\"}"; + try (FixtureServer server = + new FixtureServer().with("GET", discoveryUrlSuffix, discoveryUrlResponse, 200)) { + String discoveryUrl = server.getUrl() + discoveryUrlSuffix; + OpenIDConnectEndpoints endpoints = + new DatabricksConfig() + .setHost(server.getUrl()) + .setDiscoveryUrl(discoveryUrl) + .setHttpClient(new CommonsHttpClient.Builder().withTimeoutSeconds(30).build()) + .getDatabricksOidcEndpoints(); + assertEquals( + "https://ws.databricks.com/oidc/v1/authorize", endpoints.getAuthorizationEndpoint()); + assertEquals("https://ws.databricks.com/oidc/v1/token", endpoints.getTokenEndpoint()); + } + } } From 37e2032fd767f99b0c52b6ea57f60dea92e516e1 Mon Sep 17 00:00:00 2001 From: Hector Castejon Diaz Date: Wed, 25 Feb 2026 11:56:46 +0000 Subject: [PATCH 3/3] fmt --- .../java/com/databricks/sdk/core/DatabricksConfigTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/core/DatabricksConfigTest.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/core/DatabricksConfigTest.java index 01726c757..f7b2d247b 100644 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/core/DatabricksConfigTest.java +++ b/databricks-sdk-java/src/test/java/com/databricks/sdk/core/DatabricksConfigTest.java @@ -462,8 +462,7 @@ public void testGetHostMetadataAccountRawOidcTemplate() throws IOException { DatabricksConfig config = new DatabricksConfig().setHost(server.getUrl()); config.resolve(emptyEnv()); HostMetadata meta = config.getHostMetadata(); - assertEquals( - "https://acc.databricks.com/oidc/accounts/{account_id}", meta.getOidcEndpoint()); + assertEquals("https://acc.databricks.com/oidc/accounts/{account_id}", meta.getOidcEndpoint()); assertNull(meta.getAccountId()); assertNull(meta.getWorkspaceId()); }