Skip to content

Honor Auth_Scope for OAuth M2M client credentials - #1707

Merged
vuanhphung merged 5 commits into
mainfrom
fix/m2m-auth-scope-1706
Oct 5, 2026
Merged

vuanhphung merged 5 commits into
mainfrom
fix/m2m-auth-scope-1706

Conversation

@vuanhphung

@vuanhphung vuanhphung commented Oct 1, 2026 •

Copy link
Copy Markdown
Collaborator

Description

Honor Auth_Scope for Databricks OAuth client-secret M2M so scoped service-principal secrets can authenticate. Client-secret M2M, JWT-assertion M2M, and U2M now parse one space-separated property value consistently. Blank values use all-apis for client-secret M2M and sql offline_access for U2M; JWT-assertion M2M omits the scope parameter. Fixes #1706.

Testing

mvn -q test -pl jdbc-core -Dtest=ClientConfiguratorTest,DatabricksConnectionContextTest (190 passed).
mvn -q test -pl jdbc-core -Dtest=PrivateKeyClientCredentialProviderTest,JwtPrivateKeyClientCredentialsTest,ClientConfiguratorTest (61 passed).

Telemetry Errors

  • Not applicable — this PR does not add or change a telemetry-visible error.

Additional Notes to the Reviewer

A live connection with a sql-scoped secret was not exercised.


This PR was created with GitHub MCP.

@peco-review-bot peco-review-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: 1 Low

Looks good — a clean, well-targeted change that honors Auth_Scope for client-secret M2M while preserving the SDK's all-apis default (verified: getAuthScope() returns null when unset, mutable ArrayList wrap matches the documented SDK sortScopes caveat, and both default/configured paths are tested). One low-severity edge case around an empty Auth_Scope value noted inline.

Comment thread src/main/java/com/databricks/jdbc/dbclient/impl/common/ClientConfigurator.java Outdated

@peco-review-bot peco-review-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: 1 Nit

Looks good — honors Auth_Scope for M2M client-secret auth with correct null/blank handling that preserves the SDK's all-apis default. Uses a mutable ArrayList (consistent with the U2M sortScopes() note), is covered by three new tests, and includes changelog + README updates. One nit in the summary: scope is handled as a single value (no multi-scope split), which is consistent with the existing U2M path.

Other findings

  • ⚪ Nit — Auth_Scope is treated as a single opaque scope string (List.of(authScope.strip())), so a space- or comma-separated value like sql offline_access becomes one malformed scope rather than two. This mirrors the existing getOAuthScopesForU2M() behavior, so it's consistent — but if multi-scope M2M is ever expected, this would need splitting. Flagging only for awareness; no change required for this PR's stated goal.

@peco-review-bot peco-review-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: 1 Low

Looks good — a focused, well-tested fix that honors Auth_Scope for the standard OAuth M2M client-secret flow. The null/blank guard, whitespace splitting, and mutable-list wrapper (to avoid the SDK's in-place sortScopes()) are all correct, and the default all-apis behavior is preserved and covered by tests. One low-severity note on parsing inconsistency between the M2M and U2M scope handling.

Comment thread src/main/java/com/databricks/jdbc/dbclient/impl/common/ClientConfigurator.java Outdated

@peco-review-bot peco-review-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: 1 Low

Looks good — a focused, well-tested change that correctly parses Auth_Scope into space-separated scopes for client-secret M2M and U2M, preserving the all-apis/sql offline_access defaults on blank input, and wraps lists in mutable ArrayList before setScopes (avoiding the known SDK sortScopes immutability issue). The updated U2M Javadoc now matches the actual all-clouds default behavior. One low-severity consistency note: the JWT-assertion M2M path still uses singletonList(getAuthScope()) and does not benefit from the new splitting.

@peco-review-bot peco-review-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No issues identified by the review bot.

@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown

JDBC integration tests triggered (replay, thrift + sea). View workflow runs.

@nktkhndlwl

Copy link
Copy Markdown

many thanks for taking this up so quickly @vuanhphung
the fix looks sound

Signed-off-by: Vu Anh Phung <vu.phung@databricks.com>
Signed-off-by: Vu Anh Phung <vu.phung@databricks.com>
Signed-off-by: Vu Anh Phung <vu.phung@databricks.com>
Signed-off-by: Vu Anh Phung <vu.phung@databricks.com>
Signed-off-by: Vu Anh Phung <vu.phung@databricks.com>
@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown

Integration test approval reset.

New commits were pushed to this PR. Label(s) integration-test were removed for security.

A maintainer must re-review and re-add a label to preview tests again. (The real gate runs in the merge queue.)

Latest commit: 71292c0

@vuanhphung
vuanhphung enabled auto-merge October 5, 2026 07:15

@peco-review-bot peco-review-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: 1 Low

Looks good — a clean, well-tested fix that unifies Auth_Scope parsing across client-secret M2M, JWT-assertion M2M, and U2M. Scopes are correctly wrapped in mutable ArrayLists where the SDK sorts in place, blank values fall back to the right defaults per flow, and the stale Azure-null Javadoc is corrected to match code that already returned uniform defaults for all clouds. One low-severity test-coverage note (F1) on verifying the client-secret M2M scope actually reaches the token request.

+ "OAuth2ClientId=client-id;OAuth2Secret=client-secret;Auth_Scope= sql ";
IDatabricksConnectionContext connectionContext =
DatabricksConnectionContextFactory.create(jdbcUrl, new Properties());
assertEquals(" sql ", connectionContext.getAuthScope());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Low — The new client-secret M2M scope tests assert only databricksConfig.getScopes() (the config field), not that the scope actually reaches the OAuth token request. The JWT-assertion path tests (assertTokenRequestScope) go further and capture the outbound HTTP request's scope parameter via URLEncodedUtils. For client-secret M2M the driver relies on the SDK's OAuthM2MServicePrincipalCredentialsProvider to translate config.setScopes(...) into the token request — which this PR does not exercise (the author notes a live scoped-secret connection was not tested). Consider adding an end-to-end-style assertion that the configured scope is sent on the wire for the client-secret path too, to guard against the SDK silently ignoring the field.

@vuanhphung
vuanhphung added this pull request to the merge queue Oct 5, 2026
Merged via the queue into main with commit a64ae0e Oct 5, 2026
27 checks passed
@vuanhphung
vuanhphung deleted the fix/m2m-auth-scope-1706 branch October 5, 2026 08:02
@cathleeny cathleeny mentioned this pull request Oct 6, 2026
1 of 3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] M2M (client-credentials) OAuth always requests all-apis scope, ignoring scoped service-principal secrets

3 participants