Skip to content

entra: serialize interactive sign-in across GCM processes - #2471

Open
cveld wants to merge 1 commit into
git-ecosystem:mainfrom
cveld:poc/serialize-entra-interactive-auth
Open

cveld wants to merge 1 commit into
git-ecosystem:mainfrom
cveld:poc/serialize-entra-interactive-auth

Conversation

@cveld

@cveld cveld commented Oct 13, 2026

Copy link
Copy Markdown

Problem

When a cached token expires, every GCM process that needs it (one per Git worktree, one per parallel fetch, an IDE autofetch, ...) falls back to interactive authentication on its own. They share one MSAL token cache, so one sign-in is enough, but after it completes the other processes never look at the cache again. They keep prompting or waiting. In one environment a single token expiry left 189 stray git fetch / git-credential-manager get processes behind.

Discussed in #1555 (see my two comments there) and related to #2288.

Change

In EntraAuthentication.GetTokenForUserAsync, after silent authentication fails and interaction is allowed:

  1. Take a lock file entra-signin-<hash>.lock in the GCM data directory (hash of client ID, authority and cache type).
  2. Once the lock is held, resolve the account again and retry silent authentication, so a token stored by another process is used without a second prompt.
  3. Otherwise run the interactive/broker flow as before, holding the lock until it finishes.

Waiting honours cancellation and gives up after 5 minutes. If the lock cannot be taken, authentication continues exactly as before. A file handle is used rather than a named mutex (thread affinity across await); the OS releases it if the process exits.

Verification

  • 7 unit tests for the lock (EntraAuthenticationInteractiveLockTests).
  • Full dotnet test run on Windows: everything passes except 6 Trace2MessageTests.BuildTimeSpan cases that fail on a Dutch locale (decimal comma) on main as well; they pass with DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1.
  • Four parallel get processes for an account missing from the cache (GCM_MSAUTH_FLOW=devicecode): main starts 4 device-code flows, this branch starts 1 and the other 3 wait.

Not verified

  • A real sign-in completing and the waiters picking the token up from the cache.
  • Broker and browser flows (only device code was exercised), macOS and Linux.
  • The wait timeout and what waiters should do if the first user cancels are my own choices and open for discussion.

Opened as a draft: the maintainers have said serialization is planned for 3.0, so this is meant as a concrete proposal to react to.

🤖 Generated with Claude Code

When a cached token expires, every GCM process that needs it (for
example one per Git worktree, or one per parallel fetch) falls back to
interactive authentication on its own. They share one MSAL token cache,
so only one sign-in is needed, but after it completes the other
processes never look at the cache again and keep prompting or waiting.

Take a per-client, per-authority lock file in the GCM data directory
before starting an interactive or broker flow. Once the lock is held,
resolve the account again and retry silent authentication, so a token
stored by another process is used without a second prompt. Waiting
honours cancellation and gives up after five minutes. If the lock
cannot be taken, authentication continues as before.

Verified with four parallel `get` requests against an expired account:
before, four device-code flows started; now one starts and three wait.

Assisted-by: Claude Sonnet 5.5
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@cveld
cveld marked this pull request as ready for review October 13, 2026 11:46
@cveld
cveld requested a review from a team as a code owner October 13, 2026 11:46

This branch has not been deployed

No deployments
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.

1 participant