Skip to content

Add --force-refresh flag to auth token command - #4767

Merged
mihaimitrea-db merged 6 commits into
mainfrom
mihaimitrea-db/token-force-refresh
Mar 27, 2026
Merged

Add --force-refresh flag to auth token command#4767
mihaimitrea-db merged 6 commits into
mainfrom
mihaimitrea-db/token-force-refresh

Conversation

@mihaimitrea-db

@mihaimitrea-dbmihaimitrea-db commented Mar 17, 2026

Copy link
Copy Markdown
Contributor

Wire a new --force-refresh CLI flag that delegates to the SDK's ForceRefreshToken() method, bypassing the cached token validity check. The default path through Token() is unchanged.

Note: this will not compile until the SDK ships ForceRefreshToken() (databricks/databricks-sdk-go#1552) and the CLI''s Go SDK dependency is bumped to v0.126.

Changes

  • Add a --force-refresh boolean flag to databricks auth token. When set, the command calls PersistentAuth.ForceRefreshToken() instead of PersistentAuth.Token(), which always performs a token refresh against the IdP regardless of the cached token's remaining TTL.
  • The error handling is shared between both paths: invalid refresh tokens produce the same actionable "To reauthenticate, run..." message, and the backward-compat cache.ErrNotFound rewrite is preserved.
  • Add three acceptance tests covering the force-refresh flag end-to-end:
    • force-refresh-success: pre-populated cache with a valid token, --force-refresh returns the server's new token (not the cached one).
    • force-refresh-invalid-refresh-token: server returns 401 with invalid refresh token; asserts the actionable re-login error message.
    • force-refresh-no-cache: no cached token exists; asserts the backward-compat error message is preserved for --force-refresh.
  • Add unit tests verifying the default path still returns a cached valid token without refreshing, and that --force-refresh correctly delegates to ForceRefreshToken() for both success and failure cases.

Why

#4564 reports that external consumers using databricks auth token as a credential helper (e.g. Claude Code via apiKeyHelper) can receive near-expired tokens that expire before they can be used.

databricks/databricks-sdk-go#1535 addressed the common case by adding a 5-minute proactive refresh buffer to Token(). However, that proactive refresh is intentionally best-effort: Token() still returns the existing access token when it is valid and a proactive refresh fails, because callers did not explicitly ask for a fresh token.

For integrations that treat the CLI as a token minter or want to manage their own cache/TTL policy, "return a still-usable token" is different from "refresh now and give me a newly minted token or fail." The --force-refresh flag gives those integrations an explicit way to guarantee a fresh token.

Tests

  • Unit tests in cmd/auth/token_test.go: table-driven cases covering default-path cache reuse, force-refresh success, and force-refresh error preservation.
  • Acceptance tests in acceptance/cmd/auth/token/force-refresh-{success,invalid-refresh-token,no-cache}/: end-to-end tests against the mock OIDC server, run for both terraform and direct engine variants.

@mihaimitrea-db
mihaimitrea-dbforce-pushed the mihaimitrea-db/token-force-refresh branch from f78303b to c2ce190CompareMarch 17, 2026 12:54
@eng-dev-ecosystem-bot

eng-dev-ecosystem-bot commented Mar 17, 2026

Copy link
Copy Markdown
Collaborator

Commit: 4994c99

Run: 23649228110

Env🟨​KNOWN💚​RECOVERED🙈​SKIP✅​pass🙈​skipTime
🟨​aws linux7102708106:51
🟨​aws windows7102728086:06
💚​aws-ucws linux7103667268:01
💚​aws-ucws windows7103687246:50
💚​azure linux1122738084:53
💚​azure windows1122758066:17
💚​azure-ucws linux1123717228:12
💚​azure-ucws windows1123737206:22
💚​gcp linux1122698115:01
💚​gcp windows1122718095:55
17 interesting tests: 10 SKIP, 7 KNOWN
Test Nameaws linuxaws windowsaws-ucws linuxaws-ucws windowsazure linuxazure windowsazure-ucws linuxazure-ucws windowsgcp linuxgcp windows
🟨​TestAccept🟨​K🟨​K💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R
🙈​TestAccept/bundle/resources/permissions🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S
🟨​TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions🟨​K🟨​K💚​R💚​R🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S
🟨​TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions/DATABRICKS_BUNDLE_ENGINE=direct🟨​K🟨​K💚​R💚​R
🟨​TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions/DATABRICKS_BUNDLE_ENGINE=terraform🟨​K🟨​K💚​R💚​R
🟨​TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions🟨​K🟨​K💚​R💚​R🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S
🟨​TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions/DATABRICKS_BUNDLE_ENGINE=direct🟨​K🟨​K💚​R💚​R
🟨​TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions/DATABRICKS_BUNDLE_ENGINE=terraform🟨​K🟨​K💚​R💚​R
🙈​TestAccept/bundle/resources/postgres_branches/basic🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S
🙈​TestAccept/bundle/resources/postgres_branches/recreate🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S
🙈​TestAccept/bundle/resources/postgres_branches/update_protected🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S
🙈​TestAccept/bundle/resources/postgres_branches/without_branch_id🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S
🙈​TestAccept/bundle/resources/postgres_endpoints/basic🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S
🙈​TestAccept/bundle/resources/postgres_endpoints/recreate🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S
🙈​TestAccept/bundle/resources/postgres_projects/update_display_name🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S
🙈​TestAccept/bundle/resources/synced_database_tables/basic🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S
🙈​TestAccept/ssh/connection🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S
Top 20 slowest tests (at least 2 minutes):
durationenvtestname
4:16azure windowsTestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
4:15gcp windowsTestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:41azure windowsTestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:38gcp windowsTestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:20azure-ucws linuxTestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:15gcp linuxTestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:14aws linuxTestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:12aws-ucws windowsTestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:11aws windowsTestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:10gcp linuxTestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:09aws-ucws linuxTestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:49azure-ucws linuxTestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:48aws linuxTestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:44aws-ucws linuxTestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:44aws-ucws windowsTestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:44aws windowsTestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:16azure linuxTestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:13azure-ucws windowsTestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:08azure linuxTestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:08azure-ucws windowsTestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct

Wire a new --force-refresh CLI flag that delegates to the SDK's
ForceRefreshToken() method, bypassing the cached token validity
check. The default path through Token() is unchanged.
Note: this will not compile until the SDK ships ForceRefreshToken().
@mihaimitrea-db
mihaimitrea-dbforce-pushed the mihaimitrea-db/token-force-refresh branch from c2ce190 to 807421aCompareMarch 17, 2026 13:14
@mihaimitrea-dbmihaimitrea-db linked an issue Mar 17, 2026 that may be closed by this pull request
@mihaimitrea-dbmihaimitrea-db self-assigned this Mar 17, 2026
Comment threadNEXT_CHANGELOG.md Outdated
- Add failOnCallTransport to assert no network call when reusing cached token
- Remove inherited Ignore from force-refresh-invalid-refresh-token test.toml
- Add explanatory comment in force-refresh-success script
- Tighten --force-refresh description in Long help text
- Rename resp -> got in validateToken callbacks for consistency
- Fix inMemoryTokenCache to copy tokens on Lookup/Store, matching
file-backed cache semantics and preventing cross-test corruption
@github-actions

Copy link
Copy Markdown
Contributor

Suggested reviewers

Based on git history of the changed files, these people are best suited to review:

Confidence: high

Eligible reviewers

Based on CODEOWNERS, these people or teams could also review:

@andrewnester, @anton-107, @denik, @pietern, @shreyas-goenka

Suggestions based on git history of 15 changed files (4 scored). See CODEOWNERS for path-specific ownership rules.

@simonfaltumsimonfaltum left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good.

@mihaimitrea-db
mihaimitrea-db added this pull request to the merge queueMar 27, 2026
mihaimitrea-db added a commit to databricks/databricks-sdk-py that referenced this pull request Apr 24, 2026
Pass --force-refresh to the Databricks CLI auth token command when the
CLI supports it (>= v0.296.0), bypassing the CLI's internal token cache.
The SDK manages its own token caching. When the SDK considers its token
stale and shells out to `databricks auth token`, the CLI may return a
cached token that is about to expire from the SDK's perspective. The
--force-refresh flag guarantees a freshly minted token.
With the version detection infrastructure from the parent commit, adding
--force-refresh is a one-constant, one-if change.
See: databricks/cli#4767
mihaimitrea-db added a commit to databricks/databricks-sdk-py that referenced this pull request Apr 24, 2026
Pass --force-refresh to the Databricks CLI auth token command when the
CLI supports it (>= v0.296.0), bypassing the CLI's internal token cache.
The SDK manages its own token caching. When the SDK considers its token
stale and shells out to `databricks auth token`, the CLI may return a
cached token that is about to expire from the SDK's perspective. The
--force-refresh flag guarantees a freshly minted token.
With the version detection infrastructure from the parent commit, adding
--force-refresh is a one-constant, one-if change.
See: databricks/cli#4767
mihaimitrea-db added a commit to databricks/databricks-sdk-py that referenced this pull request Apr 24, 2026
Pass --force-refresh to the Databricks CLI auth token command when the
CLI supports it (>= v0.296.0), bypassing the CLI's internal token cache.
The SDK manages its own token caching. When the SDK considers its token
stale and shells out to `databricks auth token`, the CLI may return a
cached token that is about to expire from the SDK's perspective. The
--force-refresh flag guarantees a freshly minted token.
With the version detection infrastructure from the parent commit, adding
--force-refresh is a one-constant, one-if change.
See: databricks/cli#4767
mihaimitrea-db added a commit to databricks/databricks-sdk-py that referenced this pull request Apr 24, 2026
Pass --force-refresh to the Databricks CLI auth token command when the
CLI supports it (>= v0.296.0), bypassing the CLI's internal token cache.
The SDK manages its own token caching. When the SDK considers its token
stale and shells out to `databricks auth token`, the CLI may return a
cached token that is about to expire from the SDK's perspective. The
--force-refresh flag guarantees a freshly minted token.
With the version detection infrastructure from the parent commit, adding
--force-refresh is a one-constant, one-if change.
See: databricks/cli#4767
mihaimitrea-db added a commit to databricks/databricks-sdk-py that referenced this pull request Apr 24, 2026
Pass --force-refresh to the Databricks CLI auth token command when the
CLI supports it (>= v0.296.0), bypassing the CLI's internal token cache.
The SDK manages its own token caching. When the SDK considers its token
stale and shells out to `databricks auth token`, the CLI may return a
cached token that is about to expire from the SDK's perspective. The
--force-refresh flag guarantees a freshly minted token.
With the version detection infrastructure from the parent commit, adding
--force-refresh is a one-constant, one-if change.
See: databricks/cli#4767
mihaimitrea-db added a commit to databricks/databricks-sdk-py that referenced this pull request Apr 24, 2026
Pass --force-refresh to the Databricks CLI auth token command when the
CLI supports it (>= v0.296.0), bypassing the CLI's internal token cache.
The SDK manages its own token caching. When the SDK considers its token
stale and shells out to `databricks auth token`, the CLI may return a
cached token that is about to expire from the SDK's perspective. The
--force-refresh flag guarantees a freshly minted token.
With the version detection infrastructure from the parent commit, adding
--force-refresh is a one-constant, one-if change.
See: databricks/cli#4767
mihaimitrea-db added a commit to databricks/databricks-sdk-py that referenced this pull request Apr 28, 2026
Pass --force-refresh to the Databricks CLI auth token command when the
CLI supports it (>= v0.296.0), bypassing the CLI's internal token cache.
The SDK manages its own token caching. When the SDK considers its token
stale and shells out to `databricks auth token`, the CLI may return a
cached token that is about to expire from the SDK's perspective. The
--force-refresh flag guarantees a freshly minted token.
With the version detection infrastructure from the parent commit, adding
--force-refresh is a one-constant, one-if change.
See: databricks/cli#4767
mihaimitrea-db added a commit to databricks/databricks-sdk-py that referenced this pull request Apr 28, 2026
Pass --force-refresh to the Databricks CLI auth token command when the
CLI supports it (>= v0.296.0), bypassing the CLI's internal token cache.
The SDK manages its own token caching. When the SDK considers its token
stale and shells out to `databricks auth token`, the CLI may return a
cached token that is about to expire from the SDK's perspective. The
--force-refresh flag guarantees a freshly minted token.
With the version detection infrastructure from the parent commit, adding
--force-refresh is a one-constant, one-if change.
See: databricks/cli#4767
mihaimitrea-db added a commit to databricks/databricks-sdk-py that referenced this pull request Apr 28, 2026
Pass --force-refresh to the Databricks CLI auth token command when the
CLI supports it (>= v0.296.0), bypassing the CLI's internal token cache.
The SDK manages its own token caching. When the SDK considers its token
stale and shells out to `databricks auth token`, the CLI may return a
cached token that is about to expire from the SDK's perspective. The
--force-refresh flag guarantees a freshly minted token.
With the version detection infrastructure from the parent commit, adding
--force-refresh is a one-constant, one-if change.
See: databricks/cli#4767
mihaimitrea-db added a commit to databricks/databricks-sdk-py that referenced this pull request Apr 28, 2026
Pass --force-refresh to the Databricks CLI auth token command when the
CLI supports it (>= v0.296.0), bypassing the CLI's internal token cache.
The SDK manages its own token caching. When the SDK considers its token
stale and shells out to `databricks auth token`, the CLI may return a
cached token that is about to expire from the SDK's perspective. The
--force-refresh flag guarantees a freshly minted token.
With the version detection infrastructure from the parent commit, adding
--force-refresh is a one-constant, one-if change.
See: databricks/cli#4767
mihaimitrea-db added a commit to databricks/databricks-sdk-py that referenced this pull request Apr 28, 2026
Pass --force-refresh to the Databricks CLI auth token command when the
CLI supports it (>= v0.296.0), bypassing the CLI's internal token cache.
The SDK manages its own token caching. When the SDK considers its token
stale and shells out to `databricks auth token`, the CLI may return a
cached token that is about to expire from the SDK's perspective. The
--force-refresh flag guarantees a freshly minted token.
With the version detection infrastructure from the parent commit, adding
--force-refresh is a one-constant, one-if change.
See: databricks/cli#4767
mihaimitrea-db added a commit to databricks/databricks-sdk-py that referenced this pull request Apr 28, 2026
Pass --force-refresh to the Databricks CLI auth token command when the
CLI supports it (>= v0.296.0), bypassing the CLI's internal token cache.
The SDK manages its own token caching. When the SDK considers its token
stale and shells out to `databricks auth token`, the CLI may return a
cached token that is about to expire from the SDK's perspective. The
--force-refresh flag guarantees a freshly minted token.
With the version detection infrastructure from the parent commit, adding
--force-refresh is a one-constant, one-if change.
See: databricks/cli#4767
mihaimitrea-db added a commit to databricks/databricks-sdk-py that referenced this pull request Apr 30, 2026
Pass --force-refresh to the Databricks CLI auth token command when the
CLI supports it (>= v0.296.0), bypassing the CLI's internal token cache.
The SDK manages its own token caching. When the SDK considers its token
stale and shells out to `databricks auth token`, the CLI may return a
cached token that is about to expire from the SDK's perspective. The
--force-refresh flag guarantees a freshly minted token.
With the version detection infrastructure from the parent commit, adding
--force-refresh is a one-constant, one-if change.
See: databricks/cli#4767
mihaimitrea-db added a commit to databricks/databricks-sdk-py that referenced this pull request Apr 30, 2026
Pass --force-refresh to the Databricks CLI auth token command when the
CLI supports it (>= v0.296.0), bypassing the CLI's internal token cache.
The SDK manages its own token caching. When the SDK considers its token
stale and shells out to `databricks auth token`, the CLI may return a
cached token that is about to expire from the SDK's perspective. The
--force-refresh flag guarantees a freshly minted token.
With the version detection infrastructure from the parent commit, adding
--force-refresh is a one-constant, one-if change.
See: databricks/cli#4767
mihaimitrea-db added a commit to databricks/databricks-sdk-py that referenced this pull request Apr 30, 2026
Pass --force-refresh to the Databricks CLI auth token command when the
CLI supports it (>= v0.296.0), bypassing the CLI's internal token cache.
The SDK manages its own token caching. When the SDK considers its token
stale and shells out to `databricks auth token`, the CLI may return a
cached token that is about to expire from the SDK's perspective. The
--force-refresh flag guarantees a freshly minted token.
With the version detection infrastructure from the parent commit, adding
--force-refresh is a one-constant, one-if change.
See: databricks/cli#4767
mihaimitrea-db added a commit to databricks/databricks-sdk-java that referenced this pull request Apr 30, 2026
The SDK manages its own token caching via `CachedTokenSource`. When
the SDK shells out to `databricks auth token`, the CLI may return a
token from *its* own cache that is about to expire (or has already
expired from the SDK's perspective), producing unnecessary refresh
failures and retry loops.
The CLI added `--force-refresh` in v0.296.0
(databricks/cli#4767) to let callers bypass
its cache. With the version-detection infrastructure from the parent
PR already in place, opting in is a one-constant, one-branch change:
* Introduce `CLI_VERSION_FOR_FORCE_REFRESH = v0.296.0`.
* Split `buildCliCommand` into the existing profile/host decision
(now `buildCoreCliCommand`) and a thin wrapper that appends
`--force-refresh` when supported and otherwise logs a precise
warning.
Future capability-gated flags slot into the same wrapper.
Mirrors:
* databricks/databricks-sdk-go#1628
* databricks/databricks-sdk-py#1378
Co-authored-by: Isaac
mihaimitrea-db added a commit to databricks/databricks-sdk-java that referenced this pull request Apr 30, 2026
The SDK manages its own token caching via `CachedTokenSource`. When
the SDK shells out to `databricks auth token`, the CLI may return a
token from *its* own cache that is about to expire (or has already
expired from the SDK's perspective), producing unnecessary refresh
failures and retry loops.
The CLI added `--force-refresh` in v0.296.0
(databricks/cli#4767) to let callers bypass
its cache. With the version-detection infrastructure from the parent
PR already in place, opting in is a one-constant, one-branch change:
* Introduce `CLI_VERSION_FOR_FORCE_REFRESH = v0.296.0`.
* Split `buildCliCommand` into the existing profile/host decision
(now `buildCoreCliCommand`) and a thin wrapper that appends
`--force-refresh` when supported and otherwise logs a precise
warning.
Future capability-gated flags slot into the same wrapper.
Mirrors:
* databricks/databricks-sdk-go#1628
* databricks/databricks-sdk-py#1378
Co-authored-by: Isaac
mihaimitrea-db added a commit to databricks/databricks-sdk-java that referenced this pull request Apr 30, 2026
The SDK manages its own token caching via `CachedTokenSource`. When
the SDK shells out to `databricks auth token`, the CLI may return a
token from *its* own cache that is about to expire (or has already
expired from the SDK's perspective), producing unnecessary refresh
failures and retry loops.
The CLI added `--force-refresh` in v0.296.0
(databricks/cli#4767) to let callers bypass
its cache. With the version-detection infrastructure from the parent
PR already in place, opting in is a one-constant, one-branch change:
* Introduce `CLI_VERSION_FOR_FORCE_REFRESH = v0.296.0`.
* Split `buildCliCommand` into the existing profile/host decision
(now `buildCoreCliCommand`) and a thin wrapper that appends
`--force-refresh` when supported and otherwise logs a precise
warning.
Future capability-gated flags slot into the same wrapper.
Mirrors:
* databricks/databricks-sdk-go#1628
* databricks/databricks-sdk-py#1378
Co-authored-by: Isaac
pullBot pushed a commit to Future-Outlier/databricks-sdk-py that referenced this pull request Apr 30, 2026
## 🥞 Stacked PR
Use this
[link](https://github.com/databricks/databricks-sdk-py/pull/1378/files)
to review incremental changes.
-
[stack/cli-force-refresh](databricks#1377)
[[Files
changed](https://github.com/databricks/databricks-sdk-py/pull/1377/files)]
[MERGED]
-
[**stack/cli-progressive-token-commands**](databricks#1378)
[[Files
changed](https://github.com/databricks/databricks-sdk-py/pull/1378/files)]
---------
## Summary
Append `--force-refresh` to the `databricks auth token` command when the
installed CLI is >= v0.296.0, so the CLI bypasses its internal token
cache and hands the SDK a freshly minted token every time.
Mirrors
[databricks/databricks-sdk-go#1628](databricks/databricks-sdk-go#1628).
Requires the version-detection infrastructure from the parent PR
[databricks#1377](databricks#1377).
## Why
The SDK already manages its own token caching via `oauth.Refreshable`.
When the SDK decides it needs a new token and shells out to `databricks
auth token`, the CLI may return a token from *its* own cache that is
about to expire (or that has already expired from the SDK's
perspective). That produces unnecessary refresh failures and retry loops
on top of a value that the SDK was confident was fresh.
The CLI added `--force-refresh` in
[databricks/cli#4767](databricks/cli#4767)
(motivated by
[databricks/cli#4564](databricks/cli#4564))
specifically to let callers bypass the CLI's cache. With the
version-detection infrastructure from the parent PR already in place,
opting in is a one-constant, one-branch change.
## What changed
### Interface changes
None. `CliTokenSource` is not part of the public API surface.
### Behavioral changes
- `databricks auth token` invocations now end with `--force-refresh`
whenever the detected CLI is >= v0.296.0. Callers on older CLIs see no
change.
- On older CLIs, a `WARNING` is logged: `"Databricks CLI <ver> does not
support --force-refresh (requires >= v0.296.0). The CLI's token cache
may provide stale tokens."`
`AzureCliTokenSource` is unaffected — it does not pass through
`DatabricksCliTokenSource` and does not opt into version-gated flag
selection.
### Internal changes
- New constant `DatabricksCliTokenSource._CLI_VERSION_FOR_FORCE_REFRESH
= CliVersion(0, 296, 0)`.
- `_build_cli_command` is split into two helpers, matching the shape the
Go SDK settled on after the same PR there:
- **`_build_core_cli_command(cli_path, cfg, version)`** — holds the
existing profile-vs-host decision (moved out of `_build_cli_command`).
- **`_build_cli_command(cli_path, cfg, version)`** — now a thin wrapper
that calls `_build_core_cli_command`, appends `--force-refresh` when
`version >= _CLI_VERSION_FOR_FORCE_REFRESH`, and otherwise logs the
unsupported-version `WARNING`.
Future version-gated flags slot into the same pattern: add a
`_CLI_VERSION_FOR_<flag>` constant and an `if version >= ...` block in
`_build_cli_command`.
## How is this tested?
Unit tests in `tests/test_credentials_provider.py`:
- Additional `test_build_cli_command` cases covering the full matrix:
- `--host` + v0.296.0 → appends `--force-refresh`.
- account `--host` + v0.296.0 → appends `--force-refresh`.
- `--profile` + v0.296.0 → `--profile` + `--force-refresh`.
- `--profile` + v0.207.1 → `--profile` only (too old for
`--force-refresh`).
- `--profile`-only + v0.296.0 → `--profile` + `--force-refresh` even
without a host.
- zero version (detection failure) → `--host` only, no
`--force-refresh`.
- `test_build_cli_command_force_refresh_unsupported_logs_warning` —
asserts the `WARNING` log is emitted when `version <
_CLI_VERSION_FOR_FORCE_REFRESH`.
All parent-PR tests continue to pass unchanged.
mihaimitrea-db added a commit to databricks/databricks-sdk-java that referenced this pull request May 4, 2026
The SDK manages its own token caching via `CachedTokenSource`. When
the SDK shells out to `databricks auth token`, the CLI may return a
token from *its* own cache that is about to expire (or has already
expired from the SDK's perspective), producing unnecessary refresh
failures and retry loops.
The CLI added `--force-refresh` in v0.296.0
(databricks/cli#4767) to let callers bypass
its cache. With the version-detection infrastructure from the parent
PR already in place, opting in is a one-constant, one-branch change:
* Introduce `CLI_VERSION_FOR_FORCE_REFRESH = v0.296.0`.
* Split `buildCliCommand` into the existing profile/host decision
(now `buildCoreCliCommand`) and a thin wrapper that appends
`--force-refresh` when supported and otherwise logs a precise
warning.
Future capability-gated flags slot into the same wrapper.
Mirrors:
* databricks/databricks-sdk-go#1628
* databricks/databricks-sdk-py#1378
Co-authored-by: Isaac
mihaimitrea-db added a commit to databricks/databricks-sdk-java that referenced this pull request May 4, 2026
The SDK manages its own token caching via `CachedTokenSource`. When
the SDK shells out to `databricks auth token`, the CLI may return a
token from *its* own cache that is about to expire (or has already
expired from the SDK's perspective), producing unnecessary refresh
failures and retry loops.
The CLI added `--force-refresh` in v0.296.0
(databricks/cli#4767) to let callers bypass
its cache. With the version-detection infrastructure from the parent
PR already in place, opting in is a one-constant, one-branch change:
* Introduce `CLI_VERSION_FOR_FORCE_REFRESH = v0.296.0`.
* Split `buildCliCommand` into the existing profile/host decision
(now `buildCoreCliCommand`) and a thin wrapper that appends
`--force-refresh` when supported and otherwise logs a precise
warning.
Future capability-gated flags slot into the same wrapper.
Mirrors:
* databricks/databricks-sdk-go#1628
* databricks/databricks-sdk-py#1378
Co-authored-by: Isaac
mihaimitrea-db added a commit to databricks/databricks-sdk-java that referenced this pull request May 4, 2026
The SDK manages its own token caching via `CachedTokenSource`. When
the SDK shells out to `databricks auth token`, the CLI may return a
token from *its* own cache that is about to expire (or has already
expired from the SDK's perspective), producing unnecessary refresh
failures and retry loops.
The CLI added `--force-refresh` in v0.296.0
(databricks/cli#4767) to let callers bypass
its cache. With the version-detection infrastructure from the parent
PR already in place, opting in is a one-constant, one-branch change:
* Introduce `CLI_VERSION_FOR_FORCE_REFRESH = v0.296.0`.
* Split `buildCliCommand` into the existing profile/host decision
(now `buildCoreCliCommand`) and a thin wrapper that appends
`--force-refresh` when supported and otherwise logs a precise
warning.
Future capability-gated flags slot into the same wrapper.
Mirrors:
* databricks/databricks-sdk-go#1628
* databricks/databricks-sdk-py#1378
Co-authored-by: Isaac
mihaimitrea-db added a commit to databricks/databricks-sdk-java that referenced this pull request May 4, 2026
The SDK manages its own token caching via `CachedTokenSource`. When
the SDK shells out to `databricks auth token`, the CLI may return a
token from *its* own cache that is about to expire (or has already
expired from the SDK's perspective), producing unnecessary refresh
failures and retry loops.
The CLI added `--force-refresh` in v0.296.0
(databricks/cli#4767) to let callers bypass
its cache. With the version-detection infrastructure from the parent
PR already in place, opting in is a one-constant, one-branch change:
* Introduce `CLI_VERSION_FOR_FORCE_REFRESH = v0.296.0`.
* Split `buildCliCommand` into the existing profile/host decision
(now `buildCoreCliCommand`) and a thin wrapper that appends
`--force-refresh` when supported and otherwise logs a precise
warning.
Future capability-gated flags slot into the same wrapper.
Mirrors:
* databricks/databricks-sdk-go#1628
* databricks/databricks-sdk-py#1378
Co-authored-by: Isaac
mihaimitrea-db added a commit to databricks/databricks-sdk-java that referenced this pull request May 6, 2026
The SDK manages its own token caching via `CachedTokenSource`. When
the SDK shells out to `databricks auth token`, the CLI may return a
token from *its* own cache that is about to expire (or has already
expired from the SDK's perspective), producing unnecessary refresh
failures and retry loops.
The CLI added `--force-refresh` in v0.296.0
(databricks/cli#4767) to let callers bypass
its cache. With the version-detection infrastructure from the parent
PR already in place, opting in is a one-constant, one-branch change:
* Introduce `CLI_VERSION_FOR_FORCE_REFRESH = v0.296.0`.
* Split `buildCliCommand` into the existing profile/host decision
(now `buildCoreCliCommand`) and a thin wrapper that appends
`--force-refresh` when supported and otherwise logs a precise
warning.
Future capability-gated flags slot into the same wrapper.
Mirrors:
* databricks/databricks-sdk-go#1628
* databricks/databricks-sdk-py#1378
Co-authored-by: Isaac
alexott pushed a commit to alexott/databricks-sdk-go that referenced this pull request May 17, 2026
## Summary
Pass `--force-refresh` to the Databricks CLI `auth token` command when
the CLI supports it (>= v0.296.0), bypassing the CLI's internal token
cache.
## Why
The SDK manages its own token caching via `CachedTokenSource`. When the
SDK decides it needs a new token and shells out to `databricks auth
token`, the CLI may return a cached token that is about to expire (or
has already expired from the SDK's perspective). This creates
unnecessary refresh failures and retry loops.
The CLI added a `--force-refresh` flag
([databricks/cli#4767](databricks/cli#4767),
motivated by
[databricks/cli#4564](databricks/cli#4564))
that bypasses its internal cache. By using this flag, the SDK is
guaranteed a freshly minted token every time it asks for one.
With the version detection infrastructure from the parent PR (databricks#1605),
adding `--force-refresh` is a one-constant, one-`if` change.
## What changed
### Interface changes
None. `CliTokenSource` is not part of the public API surface.
### Behavioral changes
- The SDK now appends `--force-refresh` when invoking `databricks auth
token` if the CLI version is >= v0.296.0.
- A warning is logged when the CLI is too old for `--force-refresh`:
`"Databricks CLI v%s does not support --force-refresh (requires >= v%s).
The CLI's token cache may provide stale tokens."`
### Internal changes
- **`cliVersionForForceRefresh`**: new version constant `{0, 296, 0}`.
- **`buildCliCommand`**: adds a nil guard and appends `--force-refresh`
after the base command is resolved.
## How is this tested?
Additional test cases in `TestBuildCliCommand`:
- host + v0.296.0 → appends `--force-refresh`
- host + v0.200.0 → no `--force-refresh`
- account host + v0.296.0 → appends `--force-refresh`
- profile + v0.296.0 → `--profile` + `--force-refresh`
- profile + v0.207.1 → `--profile` only (no `--force-refresh`)
- profile-only + v0.296.0 → `--profile` + `--force-refresh`
- zero version → `--host` only, no `--force-refresh`
Signed-off-by: Mihai Mitrea <mihai.mitrea@databricks.com>
denik pushed a commit that referenced this pull request May 20, 2026
Wire a new `--force-refresh` CLI flag that delegates to the SDK's
`ForceRefreshToken()` method, bypassing the cached token validity check.
The default path through `Token()` is unchanged.
> **Note:** this will not compile until the SDK ships
`ForceRefreshToken()`
([databricks/databricks-sdk-go#1552](databricks/databricks-sdk-go#1552))
and the CLI''s Go SDK dependency is bumped to v0.126.
## Changes
- Add a `--force-refresh` boolean flag to `databricks auth token`. When
set, the command calls `PersistentAuth.ForceRefreshToken()` instead of
`PersistentAuth.Token()`, which always performs a token refresh against
the IdP regardless of the cached token's remaining TTL.
- The error handling is shared between both paths: invalid refresh
tokens produce the same actionable "To reauthenticate, run..." message,
and the backward-compat `cache.ErrNotFound` rewrite is preserved.
- Add three acceptance tests covering the force-refresh flag end-to-end:
- **`force-refresh-success`**: pre-populated cache with a valid token,
`--force-refresh` returns the server's new token (not the cached one).
- **`force-refresh-invalid-refresh-token`**: server returns 401 with
invalid refresh token; asserts the actionable re-login error message.
- **`force-refresh-no-cache`**: no cached token exists; asserts the
backward-compat error message is preserved for `--force-refresh`.
- Add unit tests verifying the default path still returns a cached valid
token without refreshing, and that `--force-refresh` correctly delegates
to `ForceRefreshToken()` for both success and failure cases.
## Why
[#4564](#4564) reports that
external consumers using `databricks auth token` as a credential helper
(e.g. Claude Code via `apiKeyHelper`) can receive near-expired tokens
that expire before they can be used.
[databricks/databricks-sdk-go#1535](databricks/databricks-sdk-go#1535)
addressed the common case by adding a 5-minute proactive refresh buffer
to `Token()`. However, that proactive refresh is intentionally
best-effort: `Token()` still returns the existing access token when it
is valid and a proactive refresh fails, because callers did not
explicitly ask for a fresh token.
For integrations that treat the CLI as a token minter or want to manage
their own cache/TTL policy, "return a still-usable token" is different
from "refresh now and give me a newly minted token or fail." The
`--force-refresh` flag gives those integrations an explicit way to
guarantee a fresh token.
## Tests
- Unit tests in `cmd/auth/token_test.go`: table-driven cases covering
default-path cache reuse, force-refresh success, and force-refresh error
preservation.
- Acceptance tests in
`acceptance/cmd/auth/token/force-refresh-{success,invalid-refresh-token,no-cache}/`:
end-to-end tests against the mock OIDC server, run for both `terraform`
and `direct` engine variants.
---------
Co-authored-by: simon <simon.faltum@databricks.com>
denik pushed a commit that referenced this pull request May 20, 2026
## Release v0.296.0
### Notable Changes
* Direct deployment engine for DABs is now in Public Preview. Documentation at [docs/direct.md](docs/direct.md).
### CLI
* Auth commands now error when --profile and --host conflict ([#4841](#4841))
* Add `--force-refresh` flag to `databricks auth token` to force a token refresh even when the cached token is still valid ([#4767](#4767))
### Bundles
* Deduplicate grant entries with duplicate principals or privileges during initialization ([#4801](#4801))
* Fix `bundle deployment bind` to always pull remote state before modifying ([#4892](#4892))
* engine/direct: Fix drift in grants resource due to privilege reordering ([#4794](#4794))
* engine/direct: Fix 400 error when deploying grants with ALL_PRIVILEGES ([#4801](#4801))
* engine/direct: Fix unwanted recreation of secret scopes when scope_backend_type is not set ([#4834](#4834))
* engine/direct: Fix bind and unbind for non-Terraform resources ([#4850](#4850))
* engine/direct: Fix deploying removed principals ([#4824](#4824))
* engine/direct: Fix secret scope permissions migration from Terraform to Direct engine ([#4866](#4866))
mkazia pushed a commit to mkazia/databricks-sdk-java that referenced this pull request May 30, 2026
## 🥞 Stacked PR
Use this
[link](https://github.com/databricks/databricks-sdk-java/pull/752/files)
to review incremental changes.
-
[stack/cli-force-refresh](databricks#751)
[[Files
changed](https://github.com/databricks/databricks-sdk-java/pull/751/files)]
-
[**stack/cli-attempt-chain**](databricks#752)
[[Files
changed](https://github.com/databricks/databricks-sdk-java/pull/752/files)]
---------
## Summary
Append `--force-refresh` to the `databricks auth token` command when the
installed CLI is >= v0.296.0, so the CLI bypasses its internal token
cache and hands the SDK a freshly minted token every time.
Mirrors
[databricks/databricks-sdk-go#1628](databricks/databricks-sdk-go#1628)
and
[databricks/databricks-sdk-py#1378](databricks/databricks-sdk-py#1378).
Requires the version-detection infrastructure from the parent PR
[databricks#751](databricks#751).
## Why
The SDK already manages its own token caching via `CachedTokenSource`.
When the SDK decides it needs a new token and shells out to `databricks
auth token`, the CLI may return a token from *its* own cache that is
about to expire (or that has already expired from the SDK's
perspective). That produces unnecessary refresh failures and retry loops
on top of a value that the SDK was confident was fresh.
The CLI added `--force-refresh` in
[databricks/cli#4767](databricks/cli#4767)
(motivated by
[databricks/cli#4564](databricks/cli#4564))
specifically to let callers bypass the CLI's cache. With the
version-detection infrastructure from the parent PR already in place,
opting in is a one-constant, one-branch change.
## What changed
### Interface changes
None. `CliTokenSource` is not part of the public API surface.
### Behavioral changes
- `databricks auth token` invocations now end with `--force-refresh`
whenever the detected CLI is >= v0.296.0. Callers on older CLIs see no
change.
- On older CLIs, a `WARNING` is logged: `"Databricks CLI <ver> does not
support --force-refresh (requires >= v0.296.0). The CLI's token cache
may provide stale tokens."`
`AzureCliCredentialsProvider` is unaffected — it does not pass through
`DatabricksCliCredentialsProvider` and does not opt into version-gated
flag selection.
### Internal changes
- New constant
`DatabricksCliCredentialsProvider.CLI_VERSION_FOR_FORCE_REFRESH = new
DatabricksCliVersion(0, 296, 0)`.
- `buildCliCommand` is split into two helpers, matching the shape the Go
and Python SDKs settled on after the same PR there:
- **`buildCoreCliCommand(cliPath, config, version)`** — holds the
existing profile-vs-host decision (moved out of `buildCliCommand`).
- **`buildCliCommand(cliPath, config, version)`** — now a thin wrapper
that calls `buildCoreCliCommand`, appends `--force-refresh` when
`version.atLeast(CLI_VERSION_FOR_FORCE_REFRESH)`, and otherwise logs the
unsupported-version `WARNING`.
Future version-gated flags slot into the same pattern: add a
`CLI_VERSION_FOR_<flag>` constant and an `if version.atLeast(...)` block
in `buildCliCommand`.
## How is this tested?
Additional `testBuildCliCommand` parameterized cases in
`DatabricksCliCredentialsProviderTest` cover the full matrix:
- `--host` + v0.296.0 → appends `--force-refresh`.
- account `--host` + v0.296.0 → appends `--force-refresh`.
- `--profile` + v0.296.0 → `--profile` + `--force-refresh`.
- `--profile` + v0.207.1 → `--profile` only (too old for
`--force-refresh`).
- `--host` + v0.295.0 → `--host` only (too old for `--force-refresh`).
- unknown version (detection failure) → `--host` only, no
`--force-refresh`.
- dev build → `--host` only, no `--force-refresh`.
All parent-PR tests continue to pass unchanged.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Please support customizing expiryDelta for auth token command

3 participants

@mihaimitrea-db@eng-dev-ecosystem-bot@simonfaltum