-
Notifications
You must be signed in to change notification settings - Fork 102
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 packagesActual 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 : WSManStackVersionVisuals
No response