Skip to content

Handle MSAL token cache persistence failures gracefully (WSL support)#6079

Open
lewing wants to merge 2 commits intodotnet:mainfrom
lewing:fix/darc-wsl-keyring-fallback
Open

Handle MSAL token cache persistence failures gracefully (WSL support)#6079
lewing wants to merge 2 commits intodotnet:mainfrom
lewing:fix/darc-wsl-keyring-fallback

Conversation

@lewing
Copy link
Copy Markdown
Member

@lewing lewing commented Mar 10, 2026

Summary

darc login and all authenticated darc commands fail hard on WSL when the D-Bus secrets service (org.freedesktop.secrets / gnome-keyring) is unavailable. MSAL's VerifyPersistence() throws MsalCachePersistenceException before any authentication can occur, with no recovery.

Fixes #6060

Changes

CachedInteractiveBrowserCredential.cs

  • Catch MsalCachePersistenceException in GetToken/GetTokenAsync (not just in CacheAuthenticationRecord) and recreate credentials without TokenCachePersistenceOptions (in-memory only token cache)
  • After persistence fallback, if interactive auth also fails, throw CredentialUnavailableException so ChainedTokenCredential can try the next credential
  • Extract RecreateCredentialsWithoutPersistence() and IsMsalCachePersistenceException() as shared helpers (previously the recreation was inline and the exception check was a local function)

AppCredential.cs

  • Chain AzureCliCredential after the interactive credential in CreateUserCredential() via ChainedTokenCredential, so users with az login can authenticate without interactive flows when the keyring is unavailable

Behavior

Scenario Before After
WSL, no keyring, no az login Hard crash with MsalCachePersistenceException Falls back to in-memory cache, prompts device code
WSL, no keyring, az login active Hard crash Falls back to AzureCliCredential silently
Normal desktop (keyring available) Works No change — keyring used as before
User cancels interactive auth Error shown Error shown (NOT wrapped as CredentialUnavailable)

Security Notes

  • Dropping TokenCachePersistenceOptions means tokens are held in-memory only when the keyring is unavailable — this is more secure (no persistence), at the cost of re-authentication per session
  • AzureCliCredential reuses the user's existing az login session — no new credential storage introduced
  • The CredentialUnavailableException wrapping is scoped narrowly: only when the persistence fallback path also fails at interactive auth, not on all AuthenticationFailedException

When the D-Bus secrets service (gnome-keyring) is unavailable — common in
WSL environments — MSAL's VerifyPersistence() throws
MsalCachePersistenceException before any authentication can occur, causing
darc login and all authenticated commands to fail hard.

Changes:
- CachedInteractiveBrowserCredential: catch MsalCachePersistenceException
  in GetToken/GetTokenAsync and recreate credentials without
  TokenCachePersistenceOptions (in-memory only). Extract shared
  RecreateCredentialsWithoutPersistence() and IsMsalCachePersistenceException()
  helpers.
- AppCredential: chain AzureCliCredential after the interactive credential
  via ChainedTokenCredential so users with 'az login' can authenticate
  without interactive flows when the keyring is unavailable.

Fixes dotnet#6060

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 10, 2026 15:01
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Improves darc authentication reliability on WSL by handling MSAL token cache persistence failures (e.g., missing org.freedesktop.secrets) and introducing an Azure CLI-based fallback path.

Changes:

  • Catch MsalCachePersistenceException during token acquisition and fall back to non-persistent (in-memory) credentials.
  • Convert certain post-fallback interactive failures into CredentialUnavailableException so credential chaining can continue.
  • Add AzureCliCredential into the user credential chain to enable az login reuse.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
src/Maestro/Maestro.Common/AppCredentials/CachedInteractiveBrowserCredential.cs Adds persistence-failure handling around GetToken/GetTokenAsync, refactors helpers for recreating credentials and detecting persistence exceptions.
src/Maestro/Maestro.Common/AppCredentials/AppCredential.cs Wraps the interactive credential in a ChainedTokenCredential with AzureCliCredential as an additional option.

Comment thread src/Maestro/Maestro.Common/AppCredentials/AppCredential.cs
…lation

- RecreateCredentialsWithoutPersistence now preserves _options.AuthenticationRecord
  to avoid extra consent/device-code prompts when an auth record exists on disk
- Retry path exception filter now checks cancellationToken.IsCancellationRequested
  and inner OperationCanceledException to let user-initiated cancellations propagate
  instead of wrapping them as CredentialUnavailableException
- Add explanatory comment on ChainedTokenCredential ordering rationale

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment thread src/Maestro/Maestro.Common/AppCredentials/AppCredential.cs
@premun
Copy link
Copy Markdown
Member

premun commented Mar 11, 2026

LGTM

@lewing did you test this?

@lewing
Copy link
Copy Markdown
Member Author

lewing commented Mar 11, 2026

LGTM

@lewing did you test this?

partially, I can do a full test before merging though.

@premun
Copy link
Copy Markdown
Member

premun commented Mar 12, 2026

Please run one if you have the environment ready.
It's easy to run darc - you just dotnet build the csproj and then run it. Building it should just work out of the box even in WSL if you have .NET 10.

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.

darc login fails on WSL when gnome-keyring/D-Bus secrets service is unavailable

3 participants