Skip to content

Commit d37c1c5

Browse files
hectorcast-dbclaude
andcommitted
Refactor OIDC endpoint resolution in ExternalBrowserCredentialsProvider
Move OIDC endpoint resolution logic to a utility method in OAuthClientUtils. This allows proper error handling and avoids null pointer exceptions when OIDC endpoints cannot be resolved. Changes: - Add resolveOidcEndpoints() utility method in OAuthClientUtils - Update ExternalBrowserCredentialsProvider to use the utility method - Pass OpenIDConnectEndpoints explicitly to helper methods - Add proper error handling for OIDC endpoint resolution failures Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 192d315 commit d37c1c5

File tree

2 files changed

+43
-7
lines changed

2 files changed

+43
-7
lines changed

databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/ExternalBrowserCredentialsProvider.java

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,13 @@ public OAuthHeaderFactory configure(DatabricksConfig config) {
5858
// Use the utility class to resolve client ID and client secret
5959
String clientId = OAuthClientUtils.resolveClientId(config);
6060
String clientSecret = OAuthClientUtils.resolveClientSecret(config);
61+
OpenIDConnectEndpoints oidcEndpoints = null;
62+
try {
63+
oidcEndpoints = OAuthClientUtils.resolveOidcEndpoints(config);
64+
} catch (IOException e) {
65+
LOGGER.error("Failed to resolve OIDC endpoints: {}", e.getMessage());
66+
return null;
67+
}
6168

6269
try {
6370
if (tokenCache == null) {
@@ -78,7 +85,7 @@ public OAuthHeaderFactory configure(DatabricksConfig config) {
7885
new SessionCredentialsTokenSource(
7986
cachedToken,
8087
config.getHttpClient(),
81-
config.getOidcEndpoints().getTokenEndpoint(),
88+
oidcEndpoints.getTokenEndpoint(),
8289
clientId,
8390
clientSecret,
8491
Optional.of(config.getEffectiveOAuthRedirectUrl()),
@@ -100,7 +107,7 @@ public OAuthHeaderFactory configure(DatabricksConfig config) {
100107

101108
// If no cached token or refresh failed, perform browser auth
102109
CachedTokenSource cachedTokenSource =
103-
performBrowserAuth(config, clientId, clientSecret, tokenCache);
110+
performBrowserAuth(config, clientId, clientSecret, tokenCache, oidcEndpoints);
104111
tokenCache.save(cachedTokenSource.getToken());
105112
return OAuthHeaderFactory.fromTokenSource(cachedTokenSource);
106113
} catch (IOException | DatabricksException e) {
@@ -109,7 +116,7 @@ public OAuthHeaderFactory configure(DatabricksConfig config) {
109116
}
110117
}
111118

112-
protected List<String> getScopes(DatabricksConfig config) {
119+
protected List<String> getScopes(DatabricksConfig config, OpenIDConnectEndpoints oidcEndpoints) {
113120
// Get user-provided scopes and add required default scopes.
114121
Set<String> scopes = new HashSet<>(config.getScopes());
115122
// Requesting a refresh token is most of the time the right thing to do from a
@@ -125,7 +132,7 @@ protected List<String> getScopes(DatabricksConfig config) {
125132
}
126133

127134
CachedTokenSource performBrowserAuth(
128-
DatabricksConfig config, String clientId, String clientSecret, TokenCache tokenCache)
135+
DatabricksConfig config, String clientId, String clientSecret, TokenCache tokenCache, OpenIDConnectEndpoints oidcEndpoints)
129136
throws IOException {
130137
LOGGER.debug("Performing browser authentication");
131138

@@ -138,8 +145,8 @@ CachedTokenSource performBrowserAuth(
138145
.withAccountId(config.getAccountId())
139146
.withRedirectUrl(config.getEffectiveOAuthRedirectUrl())
140147
.withBrowserTimeout(config.getOAuthBrowserAuthTimeout())
141-
.withScopes(getScopes(config))
142-
.withOpenIDConnectEndpoints(config.getOidcEndpoints())
148+
.withScopes(getScopes(config, oidcEndpoints))
149+
.withOpenIDConnectEndpoints(oidcEndpoints)
143150
.build();
144151
Consent consent = client.initiateConsent();
145152

@@ -151,7 +158,7 @@ CachedTokenSource performBrowserAuth(
151158
new SessionCredentialsTokenSource(
152159
token,
153160
config.getHttpClient(),
154-
config.getOidcEndpoints().getTokenEndpoint(),
161+
oidcEndpoints.getTokenEndpoint(),
155162
config.getClientId(),
156163
config.getClientSecret(),
157164
Optional.ofNullable(config.getEffectiveOAuthRedirectUrl()),

databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/OAuthClientUtils.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package com.databricks.sdk.core.oauth;
22

33
import com.databricks.sdk.core.DatabricksConfig;
4+
import com.databricks.sdk.core.http.Request;
5+
import com.databricks.sdk.core.http.Response;
6+
import java.io.IOException;
47

58
/** Utility methods for OAuth client credentials resolution. */
69
public class OAuthClientUtils {
@@ -39,4 +42,30 @@ public static String resolveClientSecret(DatabricksConfig config) {
3942
}
4043
return null;
4144
}
45+
46+
/**
47+
* Resolves the OAuth OIDC endpoints from the configuration. Prioritizes regular OIDC endpoints, then Azure OIDC endpoints.
48+
* If the client ID and client secret are provided, the OIDC endpoints are fetched from the discovery URL.
49+
* If the Azure client ID and client secret are provided, the OIDC endpoints are fetched from the Azure AD endpoint.
50+
* If no client ID and client secret are provided, the OIDC endpoints are fetched from the default OIDC endpoints.
51+
* @param config The Databricks configuration
52+
* @return The resolved OIDC endpoints
53+
* @throws IOException if the OIDC endpoints cannot be resolved
54+
*/
55+
public static OpenIDConnectEndpoints resolveOidcEndpoints(DatabricksConfig config) throws IOException {
56+
if (config.getClientId() != null && config.getClientSecret() != null) {
57+
return config.getOidcEndpoints();
58+
} else if (config.getAzureClientId() != null && config.getAzureClientSecret() != null) {
59+
Request request = new Request("GET", config.getHost() + "/oidc/oauth2/v2.0/authorize");
60+
request.setRedirectionBehavior(false);
61+
Response resp = config.getHttpClient().execute(request);
62+
String realAuthUrl = resp.getFirstHeader("location");
63+
if (realAuthUrl == null) {
64+
return null;
65+
}
66+
return new OpenIDConnectEndpoints(
67+
realAuthUrl.replaceAll("/authorize", "/token"), realAuthUrl);
68+
}
69+
return config.getOidcEndpoints();
70+
}
4271
}

0 commit comments

Comments
 (0)