Skip to content

[ISSUE] DatabricksOAuthTokenSource relies on mandatory client id - not suitable for Web oauth2 use cases #757

@findinpath

Description

@findinpath

Description
Context https://docs.databricks.com/aws/en/dev-tools/auth/oauth-federation-exchange

DatabricksOAuthTokenSource seems to be configured only for service principal use cases because it always attempts passingclient_id header.

java.lang.NullPointerException: ClientID cannot be null
	at java.base/java.util.Objects.requireNonNull(Objects.java:246)
	at com.databricks.sdk.core.oauth.DatabricksOAuthTokenSource.getToken(DatabricksOAuthTokenSource.java:148)

The users authenticated over the Web browser don't come with client ID in the IdP JWT token.
Allow such users to do token exchanging when using databricks-sdk-java

Reproduction

import com.databricks.sdk.core.ApiClient;
import com.databricks.sdk.core.DatabricksConfig;
import com.databricks.sdk.core.CredentialsProvider;
import com.databricks.sdk.core.HeaderFactory;
import com.databricks.sdk.core.oauth.DatabricksOAuthTokenSource;
import com.databricks.sdk.core.oauth.IDTokenSource;
import com.databricks.sdk.core.oauth.IDToken;
import com.databricks.sdk.core.oauth.OpenIDConnectEndpoints;
import com.databricks.sdk.core.oauth.TokenSourceCredentialsProvider;
import com.databricks.sdk.service.catalog.SchemasAPI;

public class CustomOIDCExample {


    public static void main(String[] args) {
        DatabricksConfig config = new DatabricksConfig()
                .setHost("https://dbc-xxxx.cloud.databricks.com")
                // I have been using a service principal explicitly otherwise a NPE occurs 
                .setClientId("xxxx")
                .setCredentialsProvider(new CredentialsProvider() {
                    @Override
                    public String authType()
                    {
                        return "oidc";
                    }

                    @Override
                    public HeaderFactory configure(DatabricksConfig config)
                    {
                        IDTokenSource idTokenSource = audience -> {
                            // Logic to fetch your JWT from your IdP (OKTA)
                            String jwt = "xxxx";
                            return new IDToken(jwt);
                        };

                        OpenIDConnectEndpoints endpoints;
                        try {
                            endpoints = config.getOidcEndpoints();
                        } catch (Exception e) {
                            throw new RuntimeException(e);
                        }

                        DatabricksOAuthTokenSource oauthTokenSource =
                                new DatabricksOAuthTokenSource.Builder(
                                        config.getClientId(),
                                        config.getHost(),
                                        endpoints,
                                        idTokenSource,
                                        config.getHttpClient())
                                        .audience(config.getTokenAudience())
                                        .accountId(config.isAccountClient() ? config.getAccountId() : null)
                                        .scopes(config.getScopes())
                                        .build();

                        CredentialsProvider provider = new TokenSourceCredentialsProvider(oauthTokenSource, "oidc");
                        return provider.configure(config);
                    }
                });
        ApiClient apiClient = new ApiClient(config);
        new SchemasAPI(apiClient).list("main").forEach(schemaInfo -> System.out.println(schemaInfo));
    }
}

Expected behavior

The users authenticated over the Web browser don't come with client ID in the IdP JWT token.
Allow such users to do token exchanging when using databricks-sdk-java

Is it a regression?
Did this work in a previous version of the SDK? If so, which versions did you try?

Debug Logs
The SDK logs helpful debugging information when debug logging is enabled. Set the log level to TRACE (e.g. add log4j.logger.com.databricks=TRACE to the log4j.properties in your project), and include the logs here.

Other Information

  • OS: [e.g. macOS]
  • Version: [e.g. 0.1.0]

Additional context
Add any other context about the problem here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions