Skip to content

Invalidate cached OAuth tokens when profiles change - #6427

Open
mihaimitrea-db wants to merge 14 commits into
mainfrom
auth-profile-fingerprint
Open

mihaimitrea-db wants to merge 14 commits into
mainfrom
auth-profile-fingerprint

Conversation

@mihaimitrea-db

@mihaimitrea-db mihaimitrea-db commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Summary

Bind cached OAuth credentials to the profile configuration used during login.

When the profile changes, the CLI rejects the cached token and asks the user to log in again. This prevents a token created for one profile configuration from being reused with another.

How it works

Login

After login finishes saving the profile, the CLI computes a fingerprint from every field in the simplified profile and stores it with the cached token.

Token use and refresh

Before auth token or another command uses the cached token, the CLI computes the current fingerprint and compares it with the stored value.

  • Matching fingerprint: use or refresh the token normally.
  • Changed profile: reject the token and ask the user to log in again.
  • Deleted or renamed profile: reject the profile-keyed token.
  • Token created before fingerprints were introduced: ask for one new login.

Refreshed tokens keep the fingerprint.

Dependency loop

Fingerprint validation requires the auth package to use the simplified profile type. The profile package previously imported auth only for the legacy workspace_id = none value, which would make the two packages depend on each other.

The shared value now lives in the parent databrickscfg package, so profiles no longer need to import auth and the dependency only goes in one direction.

Configuration behavior

Ordinary commands resolve the profile by also taking into account environment variables. An environment variable that changes a fingerprinted profile field is treated like temporarily editing that field in .databrickscfg and invalidates the cached token.

Hostless profiles remain usable with other authentication methods, such as an environment-provided PAT or client credentials. Cached databricks-cli OAuth profiles are expected to have a host because login always saves one.

@eng-dev-ecosystem-bot

eng-dev-ecosystem-bot commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator

Integration test report

Commit: a1df656

Run: 34373848570

Env 🔄​flaky 💚​RECOVERED ✅​pass 🙈​skip Time
🔄​ aws linux 1 1 274 22 10:27
💚​ aws windows 1 277 20 9:26
💚​ azure linux 1 274 22 9:59
💚​ azure windows 1 276 20 8:32
💚​ gcp linux 1 275 22 11:53
💚​ gcp windows 1 277 20 9:35
Test Name aws linux aws windows azure linux azure windows gcp linux gcp windows
💚​ TestAccept 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
🔄​ TestSyncIncrementalSyncPythonNotebookToFile 🔄​f ✅​p ✅​p ✅​p ✅​p ✅​p
Top 15 slowest tests (at least 2 minutes):
duration env testname
4:17 azure windows TestAccept
4:15 gcp windows TestAccept
4:09 gcp windows TestFilerRecursiveDelete/workspace_files_extensions
4:01 aws windows TestAccept
3:07 gcp linux TestFilerWorkspaceNotebook/pythonJupyterNb.ipynb
2:54 gcp linux TestImportDirDoesNotOverwrite
2:34 azure linux TestFilerWorkspaceFilesExtensionsRead
2:17 gcp windows TestFilerWorkspaceFilesExtensionsRead
2:15 azure windows TestImportDirDoesNotOverwrite
2:13 gcp windows TestImportDirDoesNotOverwrite
2:11 aws linux TestAccept
2:09 azure linux TestAccept
2:08 gcp linux TestAccept
2:04 azure windows TestFilerWorkspaceFilesExtensionsReadDir
2:03 aws windows TestFilerWorkspaceFilesExtensionsReadDir

@mihaimitrea-db
mihaimitrea-db marked this pull request as ready for review August 31, 2026 10:41
@github-actions

github-actions Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Approval status: pending

/cmd/auth/ - needs approval

5 files changed
Suggested: @simonfaltum
Also eligible: @renaudhartert-db, @tanmay-db, @tejaskochar-db, @Divyansh-db, @hectorcast-db, @parthban-db, @chrisst, @rauchy

/cmd/root/ - needs approval

Files: cmd/root/auth_test.go
Suggested: @simonfaltum
Also eligible: @renaudhartert-db, @tanmay-db, @tejaskochar-db, @Divyansh-db, @hectorcast-db, @parthban-db, @chrisst, @rauchy

/libs/auth/ - needs approval

10 files changed
Suggested: @simonfaltum
Also eligible: @renaudhartert-db, @tanmay-db, @tejaskochar-db, @Divyansh-db, @hectorcast-db, @parthban-db, @chrisst, @rauchy

/libs/databrickscfg/ - needs approval

6 files changed
Suggested: @simonfaltum
Also eligible: @renaudhartert-db, @tanmay-db, @tejaskochar-db, @Divyansh-db, @hectorcast-db, @parthban-db, @chrisst, @rauchy

General files (require maintainer)

21 files changed
Based on git history:

  • @simonfaltum -- recent work in cmd/auth/, libs/auth/storage/, libs/auth/

Any maintainer (@andrewnester, @anton-107, @denik, @pietern, @shreyas-goenka, @simonfaltum, @renaudhartert-db, @janniklasrose, @lennartkats-db, @rugpanov, @rclarey) can approve all areas.
See OWNERS for ownership rules.

@mihaimitrea-db
mihaimitrea-db force-pushed the auth-profile-fingerprint branch from db84530 to c69fa5d Compare September 7, 2026 11:23

@renaudhartert-db renaudhartert-db left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks @mihaimitrea-db, first small round.

Comment thread libs/databrickscfg/profilehash/profilehash.go Outdated
Comment thread libs/databrickscfg/profile/profile.go Outdated
Comment thread libs/auth/credentials_test.go Outdated
Comment on lines +9 to +12
type ProfileFingerprintError struct {
Profile string
Missing bool
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could this be two different errors so that we can easily test them with errors.Is?

Comment thread libs/auth/arguments.go
// WorkspaceIDNone is a sentinel value persisted to .databrickscfg when the
// user explicitly skips workspace selection for SPOG account-level access.
const WorkspaceIDNone = "none"
const WorkspaceIDNone = databrickscfg.WorkspaceIDNone

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should we just use databricks.WorkspaceIDNone everywhere WorkspaceIDNone is used?


// ProfileFingerprintStore stamps token writes and rejects reads whose metadata
// does not match the current profile.
type ProfileFingerprintStore struct {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm not sure this type actually makes the code easier to follow. It is weird to me that the fingerprint is passed at the construction level but not at the lookup level. I wonder if the we should adapt the Store interface directly. You could also keep a wrapper if you want but that wrapper does not have to actually implement the Store interface.

Comment thread cmd/auth/login.go
Comment on lines +92 to +93
// setTokenProfileFingerprint runs after profile saving because OAuth-dependent
// workspace and compute selection can change the final profile contents.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should this be a call site comment? It does not tell me much about the function itself.

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