Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -924,8 +924,7 @@ internal virtual void PrepareSession()
if (Credential is not null && Authentication == WebAuthenticationType.None)
{
// Get the relevant NetworkCredential
NetworkCredential netCred = Credential.GetNetworkCredential();
WebSession.Credentials = netCred;
WebSession.SetCredential(Credential.GetNetworkCredential(), CheckProtocol(Uri), PreserveAuthorizationOnRedirect);

// Supplying a credential overrides the UseDefaultCredentials setting
WebSession.UseDefaultCredentials = false;
Expand All @@ -937,6 +936,7 @@ internal virtual void PrepareSession()
else if (UseDefaultCredentials)
{
WebSession.UseDefaultCredentials = true;
WebSession.SetCredential(CredentialCache.DefaultNetworkCredentials, CheckProtocol(Uri), PreserveAuthorizationOnRedirect);
}

if (CertificateThumbprint is not null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,30 @@ internal bool NoProxy
}
}

internal void SetCredential(NetworkCredential cred, Uri uri, bool preserveAuthOnRedirect)
{
if (preserveAuthOnRedirect)
{
Credentials = cred;
return;
}

Uri origin = new(uri.GetLeftPart(UriPartial.Authority));
CredentialCache cache = new();

// DefaultCredentials only supports a limited subset of schemes.
string[] schemes = ReferenceEquals(cred, CredentialCache.DefaultNetworkCredentials)
? new[] { "NTLM", "Kerberos", "Negotiate" }
: new[] { "Basic", "Digest", "NTLM", "Kerberos", "Negotiate" };

foreach (string scheme in schemes)
{
cache.Add(origin, scheme, cred);
}

Credentials = cache;
}

/// <summary>
/// Add a X509Certificate to the Certificates collection.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1988,16 +1988,38 @@ Describe "Invoke-WebRequest tests" -Tags "Feature", "RequireAdminOnWindows" {
{ Invoke-WebRequest @params } | Should -Throw -ErrorId "WebCmdletAllowUnencryptedAuthenticationRequiredException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
}

It "Verifies Invoke-WebRequest Negotiated -Credential Can use HTTP with -AllowUnencryptedAuthentication" {
It "Verifies Invoke-WebRequest Negotiated -Credential Can use HTTP with -AllowUnencryptedAuthentication (WithoutScheme: <WithoutScheme>, PreserveAuthorizationOnRedirect: <PreserveAuthorizationOnRedirect>)" -TestCases @(
@{WithoutScheme = $false; PreserveAuthorizationOnRedirect = $false}
@{WithoutScheme = $true; PreserveAuthorizationOnRedirect = $false}
@{WithoutScheme = $false; PreserveAuthorizationOnRedirect = $true}
@{WithoutScheme = $true; PreserveAuthorizationOnRedirect = $true}
) {
param($WithoutScheme, $PreserveAuthorizationOnRedirect)

$params = @{
Uri = $httpBasicUri
Credential = $credential
AllowUnencryptedAuthentication = $true
Uri = if ($WithoutScheme) { $httpBasicUri -replace '^http://', '' } else { $httpBasicUri }
Credential = $credential
AllowUnencryptedAuthentication = $true
SessionVariable = 'credentialSession'
PreserveAuthorizationOnRedirect = $PreserveAuthorizationOnRedirect
}
$Response = Invoke-WebRequest @params
$result = $response.Content | ConvertFrom-Json

$result.Headers.Authorization | Should -BeExactly "Basic dGVzdHVzZXI6dGVzdHBhc3N3b3Jk"

foreach ($scheme in 'Basic', 'Digest', 'NTLM', 'Negotiate') {
$otherPath = [uri]::new([uri]$httpBasicUri, '/other-directory/resource')
$credentialSession.Credentials.GetCredential($otherPath, $scheme).UserName | Should -BeExactly 'testuser'
$otherOrigin = [System.UriBuilder]::new($otherPath)
$otherOrigin.Host = 'different.invalid'
if ($PreserveAuthorizationOnRedirect) {
$credentialSession.Credentials.GetCredential($otherOrigin.Uri, $scheme).UserName | Should -BeExactly 'testuser'
} else {
$credentialSession.Credentials.GetCredential($otherOrigin.Uri, $scheme) | Should -BeNullOrEmpty
}
}
$credentialSession.Dispose()
}

# UseDefaultCredentials is only reliably testable on Windows
Expand Down Expand Up @@ -4031,15 +4053,37 @@ Describe "Invoke-RestMethod tests" -Tags "Feature", "RequireAdminOnWindows" {
{ Invoke-RestMethod @params } | Should -Throw -ErrorId "WebCmdletAllowUnencryptedAuthenticationRequiredException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand"
}

It "Verifies Invoke-RestMethod Negotiated -Credential Can use HTTP with -AllowUnencryptedAuthentication" {
It "Verifies Invoke-RestMethod Negotiated -Credential Can use HTTP with -AllowUnencryptedAuthentication (WithoutScheme: <WithoutScheme>, PreserveAuthorizationOnRedirect: <PreserveAuthorizationOnRedirect>)" -TestCases @(
@{WithoutScheme = $false; PreserveAuthorizationOnRedirect = $false}
@{WithoutScheme = $true; PreserveAuthorizationOnRedirect = $false}
@{WithoutScheme = $false; PreserveAuthorizationOnRedirect = $true}
@{WithoutScheme = $true; PreserveAuthorizationOnRedirect = $true}
) {
param($WithoutScheme, $PreserveAuthorizationOnRedirect)

$params = @{
Uri = $httpBasicUri
Credential = $credential
AllowUnencryptedAuthentication = $true
Uri = if ($WithoutScheme) { $httpBasicUri -replace '^http://', '' } else { $httpBasicUri }
Credential = $credential
AllowUnencryptedAuthentication = $true
SessionVariable = 'credentialSession'
PreserveAuthorizationOnRedirect = $PreserveAuthorizationOnRedirect
}
$result = Invoke-RestMethod @params

$result.Headers.Authorization | Should -BeExactly "Basic dGVzdHVzZXI6dGVzdHBhc3N3b3Jk"

foreach ($scheme in 'Basic', 'Digest', 'NTLM', 'Negotiate') {
$otherPath = [uri]::new([uri]$httpBasicUri, '/other-directory/resource')
$credentialSession.Credentials.GetCredential($otherPath, $scheme).UserName | Should -BeExactly 'testuser'
$otherOrigin = [System.UriBuilder]::new($otherPath)
$otherOrigin.Host = 'different.invalid'
if ($PreserveAuthorizationOnRedirect) {
$credentialSession.Credentials.GetCredential($otherOrigin.Uri, $scheme).UserName | Should -BeExactly 'testuser'
} else {
$credentialSession.Credentials.GetCredential($otherOrigin.Uri, $scheme) | Should -BeNullOrEmpty
}
}
$credentialSession.Dispose()
}

# UseDefaultCredentials is only reliably testable on Windows
Expand Down
Loading