Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ public class DatabricksCliCredentialsProvider implements CredentialsProvider {

public static final String DATABRICKS_CLI = "databricks-cli";

static final String ERR_CUSTOM_SCOPES_NOT_SUPPORTED =
"custom scopes are not supported with databricks-cli auth; "
+ "scopes are determined by what was last used when logging in with `databricks auth login`";

@Override
public String authType() {
return DATABRICKS_CLI;
Expand Down Expand Up @@ -74,6 +78,10 @@ public OAuthHeaderFactory configure(DatabricksConfig config) {
return null;
}

if (config.isScopesExplicitlySet()) {
throw new DatabricksException(ERR_CUSTOM_SCOPES_NOT_SUPPORTED);
}

CachedTokenSource cachedTokenSource =
new CachedTokenSource.Builder(tokenSource)
.setAsyncDisabled(config.getDisableAsyncTokenRefresh())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ public class DatabricksConfig {
@ConfigAttribute(auth = "oauth")
private List<String> scopes;

// Temporary field to track if scopes were explicitly set by the user.
// This is used to ensure users don't set explicit scopes when using
// `databricks-cli` auth, as it does not respect the scopes.
// TODO: Remove this field once the `auth token` command supports scopes.
private boolean scopesExplicitlySet = false;

@ConfigAttribute(env = "DATABRICKS_REDIRECT_URL", auth = "oauth")
private String redirectUrl;

Expand Down Expand Up @@ -430,9 +436,14 @@ public List<String> getScopes() {

public DatabricksConfig setScopes(List<String> scopes) {
this.scopes = scopes;
this.scopesExplicitlySet = true;
return this;
}

public boolean isScopesExplicitlySet() {
return scopesExplicitlySet;
}

public String getProfile() {
return profile;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.databricks.sdk.core;

import static com.databricks.sdk.core.DatabricksCliCredentialsProvider.ERR_CUSTOM_SCOPES_NOT_SUPPORTED;
import static org.junit.jupiter.api.Assertions.*;

import java.util.Arrays;
Expand Down Expand Up @@ -139,4 +140,50 @@ void testBuildCliCommand_UnifiedHostFalse_WithAccountHost() {
CLI_PATH, "auth", "token", "--host", ACCOUNT_HOST, "--account-id", ACCOUNT_ID),
cmd);
}

@Test
void testConfigure_ErrorsWhenScopesExplicitlySet() {
DatabricksConfig config =
new DatabricksConfig()
.setHost(HOST)
.setDatabricksCliPath(CLI_PATH)
.setScopes(Arrays.asList("sql"));

DatabricksException e =
assertThrows(DatabricksException.class, () -> provider.configure(config));
assertEquals(ERR_CUSTOM_SCOPES_NOT_SUPPORTED, e.getMessage());
}

@Test
void testConfigure_SkipsWhenCliNotFoundEvenWithScopes() {
// When CLI is not available, the provider should return null (skip)
// rather than throwing an error about scopes.
DatabricksConfig config =
new DatabricksConfig()
.setHost(HOST)
.setScopes(Arrays.asList("sql"));

assertNull(provider.configure(config));
}

@Test
void testConfigure_NoErrorWhenNoScopes() {
DatabricksConfig config = new DatabricksConfig().setHost(HOST);

try {
provider.configure(config);
} catch (Exception e) {
// May fail for other reasons (CLI not found, env not set), but must not be the scope error
assertNotEquals(ERR_CUSTOM_SCOPES_NOT_SUPPORTED, e.getMessage());
}
}

@Test
void testScopesExplicitlySetFlag() {
DatabricksConfig config = new DatabricksConfig();
assertFalse(config.isScopesExplicitlySet());

config.setScopes(Arrays.asList("sql", "clusters"));
assertTrue(config.isScopesExplicitlySet());
}
}
Loading