git-ecosystem / git-ecosystem/git-credential-manager

Azure Repos: Automatically fall back to OAuth tokens when PAT creation is blocked by org policy

Open
#2,344 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C#
Stars
9.3k
Forks
2.9k
Avg merge
7d 1h
Merged PRs (30d)
14

Description

Problem:-

When an Azure DevOps organization has a policy that disables PAT creation (disablePatCreationPolicy), GCM fails with an error during
GeneratePersonalAccessTokenAsync() with no recovery path. The user must manually discover and set:

git config --global credential.azreposCredentialType oauth

This is a poor experience because:-

  • The error message doesn't suggest the workaround
  • The user has already successfully authenticated via AAD/Entra ID (the OAuth token was obtained), but the subsequent PAT creation step fails
  • The fix is simple - use the OAuth token directly - but users don't know this
Current Behaviour:-
  1. GCM detects Azure DevOps host
  2. UsePersonalAccessTokens() returns true (default on non-DevBox platforms)
  3. GeneratePersonalAccessTokenAsync() successfully obtains an AAD access token
  4. CreatePersonalAccessTokenAsync() calls _apis/token/sessiontokens → fails due to org policy
  5. Trace2Exception propagates to the user — no fallback, no helpful guidance
Expected Behavior:-

When PAT creation fails due to an organization policy block, GCM should:

  1. Detect the specific policy-block failure (via HTTP status code and/or error message)
  2. Log a warning: "PAT creation blocked by organization policy, falling back to OAuth tokens"
  3. Fall back to returning the OAuth/AAD access token directly (same path as credential.azreposCredentialType=oauth)

Environment

  • OS: macOS (but affects all non-DevBox platforms)
  • GCM version: latest
  • Azure DevOps org: Has disablePatCreationPolicy enabled
  • Auth method: az login via Entra ID
Proposed Fix:-

In AzureReposHostProvider.cs → GetCredentialAsync(), wrap the GeneratePersonalAccessTokenAsync() call in a try/catch that detects the policy-block error and falls
back to GetAzureAccessTokenAsync().

_

I'm happy to submit a PR for this. Before I do, could you confirm:

_

  1. What HTTP status code / error message does _apis/token/sessiontokens return when blocked by org policy? (I can capture this with GCM_TRACE=1 if needed)
  2. Is this the right approach, or would you prefer a different fallback strategy?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in AzureReposHostProvider.cs and trace GetCredentialAsync() through GeneratePersonalAccessTokenAsync(), CreatePersonalAccessTokenAsync(), and GetAzureAccessTokenAsync(). Use GCM_TRACE=1 to identify the policy-block response from _apis/token/sessiontokens. Done means policy-block failures are recognized, a warning explains the fallback, and OAuth credentials are returned without affecting other PAT errors.

Written by the indexing model from the issue text.

Assessment

Tech stack
azure, csharp, git
Domain
api, authentication
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.