Skip to content

Fix auth logout failing to clear token for workspace profiles with account ID#4853

Open
mihaimitrea-db wants to merge 1 commit intomainfrom
mihaimitrea-db/logout-workspace-accountid-bug
Open

Fix auth logout failing to clear token for workspace profiles with account ID#4853
mihaimitrea-db wants to merge 1 commit intomainfrom
mihaimitrea-db/logout-workspace-accountid-bug

Conversation

@mihaimitrea-db
Copy link
Copy Markdown
Contributor

Summary

Fix auth logout failing to clear cached tokens for workspace profiles that carry an account_id in ~/.databrickscfg.

Background

The CLI's auth flow uses the host type (workspace vs. account) to decide the shape of the token-cache key. Workspace hosts get a plain host key; account/unified hosts get host/oidc/accounts/<id>. However, auth logout was making this decision based on whether account_id was non-empty on the profile. A workspace profile that had an account_id would get an account-style cache key that didn't match the key the CLI actually wrote, so the token was never deleted and the profile stayed valid after logout.

Changes

hostCacheKeyAndMatchFn now populates a config.Config with the full profile fields and calls config.HostType() to decide the cache-key shape, matching the CLI own routing logic. Workspace hosts are treated as workspace profiles regardless of leftover account metadata.

Why

The previous account_id != "" check was a proxy for "is this an account profile" that breaks when config entries carry account IDs. HostType() is the authoritative answer the CLI already provides.

Tests

  • Added a unit test case (existing workspace profile with stale account id) to the TestLogout table in cmd/auth/logout_test.go.
  • Added an acceptance test (acceptance/cmd/auth/logout/stale-account-id-workspace-host) that sets up a workspace profile with a stale
    account_id, runs auth logout, and verifies both the profile-keyed and host-keyed token cache entries are removed.
  • go test ./cmd/auth passes.

…ale account_id

logout derived the token-cache key by checking whether `account_id` was
set on the profile, but a workspace profile can carry a stale
`account_id` from an earlier account-level login. This caused logout to
build an account-style cache key (`host/oidc/accounts/<id>`) that did
not match the workspace-style key the SDK actually wrote, so the cached
token was never deleted.

Use `config.HostType()` instead to decide the cache-key shape, which
matches the SDK's own OAuth routing logic and correctly treats workspace
hosts as workspace profiles regardless of leftover account metadata.

Co-authored-by: Isaac
@mihaimitrea-db mihaimitrea-db changed the title Fix auth logout failing to clear token for workspace profiles with st… Fix auth logout failing to clear token for workspace profiles with account ID Mar 26, 2026
@eng-dev-ecosystem-bot
Copy link
Copy Markdown
Collaborator

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

Commit: 4a4b68e

Run: 23604929804

Env 💚​RECOVERED 🙈​SKIP ✅​pass 🙈​skip Time
💚​ aws linux 7 10 270 805 7:06
💚​ aws windows 7 10 272 803 5:29
💚​ aws-ucws linux 7 10 366 721 19:09
💚​ aws-ucws windows 7 10 368 719 17:12
💚​ azure linux 1 12 273 803 7:03
💚​ azure windows 1 12 275 801 4:50
💚​ azure-ucws linux 1 12 371 717 17:57
💚​ azure-ucws windows 1 12 373 715 15:26
💚​ gcp linux 1 12 269 806 6:41
💚​ gcp windows 1 12 271 804 6:42
17 interesting tests: 10 SKIP, 7 RECOVERED
Test Name aws linux aws windows aws-ucws linux aws-ucws windows azure linux azure windows azure-ucws linux azure-ucws windows gcp linux gcp windows
💚​ TestAccept 💚​R 💚​R 💚​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 💚​R 💚​R 💚​R 💚​R 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
💚​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions/DATABRICKS_BUNDLE_ENGINE=direct 💚​R 💚​R 💚​R 💚​R
💚​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions/DATABRICKS_BUNDLE_ENGINE=terraform 💚​R 💚​R 💚​R 💚​R
💚​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions 💚​R 💚​R 💚​R 💚​R 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
💚​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions/DATABRICKS_BUNDLE_ENGINE=direct 💚​R 💚​R 💚​R 💚​R
💚​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions/DATABRICKS_BUNDLE_ENGINE=terraform 💚​R 💚​R 💚​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 46 slowest tests (at least 2 minutes):
duration env testname
5:48 azure-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
5:30 gcp linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
5:21 azure-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
5:02 aws-ucws linux TestAccept/bundle/deploy/files/no-snapshot-sync/DATABRICKS_BUNDLE_ENGINE=terraform
4:47 gcp windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
4:31 aws-ucws windows TestAccept/bundle/resources/permissions/jobs/delete_one/cloud/DATABRICKS_BUNDLE_ENGINE=direct
3:52 aws-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:51 aws-ucws windows TestAccept/bundle/resources/model_serving_endpoints/basic/DATABRICKS_BUNDLE_ENGINE=terraform
3:49 gcp windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:41 azure-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:36 aws-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:31 azure-ucws windows TestAccept/bundle/destroy/jobs-and-pipeline/DATABRICKS_BUNDLE_ENGINE=direct
3:25 aws-ucws windows TestAccept/bundle/resources/volumes/recreate/DATABRICKS_BUNDLE_ENGINE=direct
3:24 aws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:21 aws-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:16 aws-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:15 aws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:11 azure-ucws linux TestAccept/bundle/deploy/files/no-snapshot-sync/DATABRICKS_BUNDLE_ENGINE=terraform
3:11 gcp linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:06 aws-ucws linux TestAccept/bundle/deployment/bind/job/generate-and-bind/DATABRICKS_BUNDLE_ENGINE=direct
2:57 azure-ucws linux TestAccept/bundle/resources/permissions/jobs/delete_one/cloud/DATABRICKS_BUNDLE_ENGINE=direct
2:54 aws-ucws linux TestAccept/bundle/resources/permissions/jobs/delete_one/cloud/DATABRICKS_BUNDLE_ENGINE=terraform
2:50 azure linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:48 aws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:48 azure windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:47 azure-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:46 aws-ucws linux TestAccept/bundle/resources/volumes/recreate/DATABRICKS_BUNDLE_ENGINE=direct
2:43 aws-ucws linux TestAccept/bundle/generate/auto-bind/DATABRICKS_BUNDLE_ENGINE=terraform
2:42 azure linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:39 azure-ucws linux TestAccept/bundle/resources/permissions/jobs/delete_one/cloud/DATABRICKS_BUNDLE_ENGINE=terraform
2:38 azure windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:35 azure-ucws windows TestAccept/bundle/deploy/files/no-snapshot-sync/DATABRICKS_BUNDLE_ENGINE=terraform
2:33 azure-ucws windows TestAccept/bundle/resources/permissions/jobs/delete_one/cloud/DATABRICKS_BUNDLE_ENGINE=terraform
2:29 aws-ucws windows TestFilerWorkspaceFilesExtensionsReadDir
2:29 aws-ucws linux TestFilerWorkspaceFilesExtensionsReadDir
2:29 aws-ucws windows TestFilerWorkspaceFilesExtensionsStat
2:28 aws-ucws windows TestAccept/bundle/resources/jobs/check-metadata/DATABRICKS_BUNDLE_ENGINE=direct
2:28 aws-ucws windows TestAccept/bundle/deploy/files/no-snapshot-sync/DATABRICKS_BUNDLE_ENGINE=terraform
2:20 azure-ucws windows TestAccept/bundle/resources/model_serving_endpoints/basic/DATABRICKS_BUNDLE_ENGINE=direct
2:17 aws-ucws linux TestAccept/bundle/resources/model_serving_endpoints/basic/DATABRICKS_BUNDLE_ENGINE=terraform
2:15 aws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:11 aws-ucws windows TestAccept/bundle/resources/volumes/recreate/DATABRICKS_BUNDLE_ENGINE=terraform
2:09 azure-ucws windows TestAccept/bundle/resources/model_serving_endpoints/basic/DATABRICKS_BUNDLE_ENGINE=terraform
2:07 aws-ucws linux TestFilerReadWrite/workspace_files_extensions
2:02 azure-ucws windows TestAccept/bundle/resources/permissions/jobs/delete_one/cloud/DATABRICKS_BUNDLE_ENGINE=direct
2:01 azure-ucws linux TestSparkJarTaskDeployAndRunOnVolumes/Databricks_Runtime_15.4_LTS

@mihaimitrea-db mihaimitrea-db changed the title Fix auth logout failing to clear token for workspace profiles with account ID Fix auth logout failing to clear token for workspace profiles with account id Mar 30, 2026
@mihaimitrea-db mihaimitrea-db self-assigned this Mar 30, 2026
@mihaimitrea-db mihaimitrea-db changed the title Fix auth logout failing to clear token for workspace profiles with account id Fix auth logout failing to clear token for workspace profiles with account ID Mar 30, 2026
@mihaimitrea-db mihaimitrea-db marked this pull request as ready for review March 30, 2026 12:06
@github-actions
Copy link
Copy Markdown

Suggested reviewers

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

Confidence: low

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 5 changed files (2 scored). See CODEOWNERS for path-specific ownership rules.

Copy link
Copy Markdown
Member

@simonfaltum simonfaltum left a comment

Choose a reason for hiding this comment

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

Review from Isaac + Cursor (2-round deep review)

1 Critical | 1 Gap (Nit) | 1 Suggestion

The fix for the stale account_id case on classic workspace profiles looks correct. The concern is that switching to HostType() might regress SPOG/discovery-routed profiles. See inline comment for details.


[Gap - Nit] Missing test for the return "", nil branch
cmd/auth/logout_test.go: When HostType() returns AccountHost/UnifiedHost but p.AccountID is empty, the new code returns "", nil. This path doesn't have test coverage. It's an unlikely scenario (an accounts.* host with no account_id), but it's new behavior that differs from the old code (which would've fallen through to the workspace branch).

[Suggestion] Direct unit tests for hostCacheKeyAndMatchFn
This is a pure function with clear inputs/outputs, but it's only tested indirectly through runLogout. A table-driven TestHostCacheKeyAndMatchFn covering workspace, stale-account workspace, account, unified, and SPOG profiles would serve as documentation of the intended cache key shapes.

Comment on lines +293 to 301
switch cfg.HostType() {
case config.AccountHost, config.UnifiedHost:
if p.AccountID == "" {
return "", nil
}
return host + "/oidc/accounts/" + p.AccountID, profile.WithHostAndAccountID(host, p.AccountID)
default:
return host, profile.WithHost(host)
}
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.

[Critical] HostType() might regress logout for SPOG/discovery-routed profiles

HostType() classifies hosts by URL pattern: only accounts.* becomes AccountHost, only profiles with experimental_is_unified_host become UnifiedHost. Everything else is WorkspaceHost.

The problem is SPOG/discovery-routed profiles. During login, libs/auth/arguments.go ToOAuthArgument() routes SPOG hosts (e.g. https://spog.example.com) to unified OAuth when discovery returns an account-scoped OIDC endpoint. The token gets stored under host/oidc/accounts/<account_id>. But runHostDiscovery() does NOT set Experimental_IsUnifiedHost, and discoveryLogin() explicitly clears it when saving the profile.

So a valid SPOG profile has host + account_id + workspace_id but no unified flag. With this change, HostType() returns WorkspaceHost for these profiles, logout tries to delete just <host> instead of <host>/oidc/accounts/<account_id>, and the token is left behind. The old p.AccountID != "" check actually handled this correctly (for the wrong reasons).

I think the fix needs to account for profiles that carry workspace_id (indicating they went through discovery). Those should keep the account-style cache key. Only profiles with a stale account_id but no workspace_id should get downgraded to the plain host key. Adding regression tests for a SPOG profile (host + account_id + workspace_id, no unified flag) would be good.

Sign up for free to 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.

3 participants