Skip to content

azrepos: fall back to OAuth when org DisablePatCreationPolicyViolation policy is set#2346

Open
p00j4 wants to merge 1 commit into
git-ecosystem:mainfrom
p00j4:fix/azrepos-pat-policy-violation-oauth-fallback
Open

azrepos: fall back to OAuth when org DisablePatCreationPolicyViolation policy is set#2346
p00j4 wants to merge 1 commit into
git-ecosystem:mainfrom
p00j4:fix/azrepos-pat-policy-violation-oauth-fallback

Conversation

@p00j4
Copy link
Copy Markdown

@p00j4 p00j4 commented May 17, 2026

Problem

When an Azure DevOps organization disables PAT creation via policy, GCM surfaces a raw fatal error with no recovery path:

fatal: Failed to create PAT: DisablePatCreationPolicyViolation
image

The user has no indication what to do. The documented fix (git config --global credential.azreposCredentialType oauth) is buried in docs.

The reason is, after installing the Extension and trying to clone a repo, it ends-up creating teh PAT with "package" only permissions because the org's default PAT creation policy is been disabled. And it's not there in the default allowed list (AZDO PAT Allowlist - CORP Tenant - SERVICE ACCOUNTS ONLY)

Fix/WorkAround

In AzureReposHostProvider.GetCredentialAsync, wrap PAT creation in a catch that recognizes the DisablePatCreationPolicyViolation error and:

  1. Falls back to OAuth for the current invocation
  2. Prints a clear warning with the exact git config command to make it permanent

A _forcedOAuth instance flag propagates the fallback to StoreCredentialAsync and EraseCredentialAsync within the same process (necessary because Settings caches git config entries on first read and won't pick up a disk write mid-invocation).

Deliberately not done: auto-writing credential.azreposCredentialType = oauth to global git config — that setting affects all Azure DevOps orgs, not just the one with the policy, which would be too broad.

User experience after this change

warning: PAT creation is disabled by your Azure DevOps organization policy.
hint: To permanently use OAuth, run:
hint:   git config --global credential.azreposCredentialType oauth

The clone then succeeds via OAuth without any user action needed for that invocation.

Test plan

  • Clone from an org with DisablePatCreationPolicyViolation policy — should fall back to OAuth and print the hint
  • Clone from a normal org — PAT path unchanged
  • After running the hinted git config command, subsequent clones go directly to OAuth (no policy call at all)

When an Azure DevOps organization has disabled PAT creation via the
DisablePatCreationPolicyViolation policy, GCM previously surfaced a raw
fatal error with no guidance. This change catches that specific error,
falls back to OAuth for the current invocation, and prints a clear
warning with the exact git config command needed to make OAuth permanent.

A `_forcedOAuth` instance flag ensures that StoreCredentialAsync and
EraseCredentialAsync use the OAuth path consistently within the same
process, working around the Settings cache which is populated once per
invocation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@p00j4 p00j4 requested review from a team as code owners May 17, 2026 01:18

return new GetCredentialResult(credential);
}
else
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

when removing this else you should clean up curly braces also or just leave the else.

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