PowerShell / PowerShell/PSResourceGet

PAT authentication failing with Azure Devops on premise Artifacts feed

Open
#1,593 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Area-Install Issue-Bug
Dominant language
C#
Stars
576
Forks
114
Avg merge
1d 2h
Merged PRs (30d)
7

Description

Prerequisites
  • Write a descriptive title.
  • Make sure you are able to repro it on the latest released version
  • Search the existing issues.
Steps to reproduce

Access to onprem Azure Devops Artifacts feed failed when authenticating using a PAT token, created by Azure Devops.

$Token = "...TOKEN..." | ConvertTo-SecureString -AsPlainText -Force
$Credential = New-Object System.Management.Automation.PSCredential('PAT', $Token)
Set-Secret -Name AzureArtifactToken -Secret $Credential
$CredentialInfo = New-Object Microsoft.PowerShell.PSResourceGet.UtilClasses.PSCredentialInfo ("MySecrets", "AzureArtifactToken")

$Params = @{
Name = 'RepoName'
Uri = 'https://mydomain.org/org/grp/_packaging/grp/nuget/v3/index.json'
Trusted = $true
CredentialInfo = $CredentialInfo
ApiVersion = 'v3'
}
Set-PSResourceRepository @Params

After examine this issue further, we found out that the API server calls were performed by a HttpClient class method, using 'negotiate' authentication by default (in our situation). As the PAT token in the SecretStore is retreived as a PSCredential, PSResourceGet passes this PAT token as a 'NetworkCredential' to the ServerApiCalls class methods (incl. v3).

        HttpClientHandler handler = new HttpClientHandler()
        {
            AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
            Credentials = networkCredential
        };

But, a PAT token requires 'Basic authentication' to succeed. See https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=Windows#use-a-pat-in-your-code. To test this, I modified the API calls (incl. V3) with a token detection (username = 'PAT') and added a HttpClient AuthenticationHeader with Basic authentication. After rebuilding and testing this code, the Authentication was successful!

    public ServerApiCall(PSRepositoryInfo repository, NetworkCredential networkCredential)
    {
        this.Repository = repository;
        
        HttpClientHandler handler = new HttpClientHandler();
        bool token = false;

        if(networkCredential != null) 
        {
            if (String.Equals("PAT", networkCredential.UserName))
            {
                token = true;
            } 
        };

        if (token)
        {
            string credString = string.Format(":{0}", networkCredential.Password);
            byte[] byteArray = Encoding.ASCII.GetBytes(credString);

            _sessionClient = new HttpClient(handler);
            _sessionClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));

        } else {

            handler.Credentials = networkCredential;
            
            _sessionClient = new HttpClient(handler);
        };
    }
Expected behavior
Find-PSResource -> list of requested packages
Actual behavior
Find-PSResource: 'Response status code does not indicate success: 401 (Unauthorized).' Re-run the command with -Credential.
Error details

No response

Environment data
ModuleType Version    PreRelease Name                                ExportedCommands
---------- -------    ---------- ----                                ----------------
Binary     1.0.2                 Microsoft.PowerShell.PSResourceGet  {Find-PSResource, Get-InstalledPSResource, Get-PSResourceRepository, Get-PSScriptFileInfo…}

Key   : PSVersion
Value : 7.3.2
Name  : PSVersion


Key   : PSEdition
Value : Core
Name  : PSEdition


Key   : GitCommitId
Value : 7.3.2
Name  : GitCommitId


Key   : OS
Value : Microsoft Windows 10.0.14393
Name  : OS


Key   : Platform
Value : Win32NT
Name  : Platform


Key   : PSCompatibleVersions
Value : {1.0, 2.0, 3.0, 4.0…}
Name  : PSCompatibleVersions


Key   : PSRemotingProtocolVersion
Value : 2.3
Name  : PSRemotingProtocolVersion


Key   : SerializationVersion
Value : 1.1.0.1
Name  : SerializationVersion


Key   : WSManStackVersion
Value : 3.0
Name  : WSManStackVersion
Visuals

No response

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

Begin at the ServerApiCall constructor and its HttpClientHandler setup described in the report; trace the v3 API path and credential handling. Verify that Find-PSResource against the on-premise Azure DevOps feed succeeds with the PAT while ordinary credentials retain their existing behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
azure, csharp, powershell
Domain
api, authentication, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.