diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs
index 70f03f5ddef..c0b237fb256 100644
--- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs
+++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs
@@ -107,6 +107,11 @@ public abstract class WebRequestPSCmdlet : PSCmdlet
///
internal int _maximumFollowRelLink = int.MaxValue;
+ ///
+ /// Maximum number of Redirects to follow.
+ ///
+ internal int _maximumRedirection;
+
///
/// Parse Rel Links.
///
@@ -549,6 +554,8 @@ protected override void ProcessRecord()
WriteVerbose(reqVerboseMsg);
+ _maximumRedirection = WebSession.MaximumRedirection;
+
using HttpResponseMessage response = GetResponse(client, request, handleRedirect);
string contentType = ContentHelper.GetContentType(response);
@@ -1230,7 +1237,7 @@ internal virtual HttpResponseMessage GetResponse(HttpClient client, HttpRequestM
response = client.SendAsync(currentRequest, HttpCompletionOption.ResponseHeadersRead, _cancelToken.Token).GetAwaiter().GetResult();
if (handleRedirect
- && WebSession.MaximumRedirection is not 0
+ && _maximumRedirection is not 0
&& IsRedirectCode(response.StatusCode)
&& response.Headers.Location is not null)
{
@@ -1238,9 +1245,9 @@ internal virtual HttpResponseMessage GetResponse(HttpClient client, HttpRequestM
_cancelToken = null;
// If explicit count was provided, reduce it for this redirection.
- if (WebSession.MaximumRedirection > 0)
+ if (_maximumRedirection > 0)
{
- WebSession.MaximumRedirection--;
+ _maximumRedirection--;
}
// For selected redirects, GET must be used with the redirected Location.
diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1
index 2da345fcd3a..d78f57141c6 100644
--- a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1
+++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1
@@ -617,7 +617,7 @@ Describe "Invoke-WebRequest tests" -Tags "Feature", "RequireAdminOnWindows" {
param($proxy_address, $name, $protocol)
# use external url, but with proxy the external url should not actually be called
- $command = "Invoke-WebRequest -Uri ${protocol}://httpbin.org -Proxy '${protocol}://${proxy_address}' -SkipCertificateCheck"
+ $command = "Invoke-WebRequest -Uri ${protocol}://httpbin.org -Proxy '${protocol}://${proxy_address}'"
$result = ExecuteWebCommand -command $command
$command = "Invoke-WebRequest -Uri '${protocol}://${proxy_address}' -NoProxy"
$expectedResult = ExecuteWebCommand -command $command
@@ -969,6 +969,42 @@ Describe "Invoke-WebRequest tests" -Tags "Feature", "RequireAdminOnWindows" {
$response.Content.Headers."Authorization" | Should -BeExactly "test"
}
+ It "Validates Invoke-WebRequest with -WebSession and -PreserveAuthorizationOnRedirect doesn't change session variable on multiple redirects: " -TestCases $redirectTests {
+ param($redirectType)
+
+ #[SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Demo/doc/test secret.")]
+ $token = "testpassword" | ConvertTo-SecureString -AsPlainText -Force
+ $credential = [pscredential]::new("testuser", $token)
+ $certificate = Get-WebListenerClientCertificate
+ $headers = @{"Authorization" = "test"}
+ $proxy = (Get-WebListenerUrl).Authority
+ $uri = Get-WebListenerUrl -Test 'Redirect' -TestValue 2 -Query @{type = $redirectType}
+
+ $session = [Microsoft.PowerShell.Commands.WebRequestSession]::new()
+ $session.MaximumRedirection = 2
+ $session.MaximumRetryCount = 2
+ $session.RetryIntervalInSeconds = 2
+ $session.UseDefaultCredentials = $true
+ $null = Invoke-WebRequest -Uri $uri -PreserveAuthorizationOnRedirect -WebSession $session -AllowUnencryptedAuthentication -Headers $headers
+ $session.MaximumRedirection | Should -BeExactly 2
+ $session.MaximumRetryCount | Should -BeExactly 2
+ $session.RetryIntervalInSeconds | Should -BeExactly 2
+ $session.UseDefaultCredentials | Should -BeExactly $true
+
+ $session = [Microsoft.PowerShell.Commands.WebRequestSession]::new()
+ $session.Credentials = $credential
+ $session.Certificates = [System.Security.Cryptography.X509Certificates.X509CertificateCollection]::new([X509Certificate]$certificate)
+ $null = Invoke-WebRequest -Uri $uri -PreserveAuthorizationOnRedirect -WebSession $session -SkipCertificateCheck -Headers $headers
+ $session.Credentials.UserName | Should -BeExactly $credential.UserName
+ $session.Credentials.Password | Should -BeExactly $credential.GetNetworkCredential().Password
+ $session.Certificates.Thumbprint | Should -BeExactly $certificate.Thumbprint
+
+ $session = [Microsoft.PowerShell.Commands.WebRequestSession]::new()
+ $session.Proxy = [System.Net.WebProxy]::new($proxy)
+ $null = Invoke-WebRequest -Uri $uri -PreserveAuthorizationOnRedirect -WebSession $session -Headers $headers
+ $session.Proxy.GetProxy($uri).Authority | Should -BeExactly $proxy
+ }
+
It "Validates Invoke-WebRequest strips the authorization header on various redirects: " -TestCases $redirectTests {
param($redirectType)
$uri = Get-WebListenerUrl -Test 'Redirect' -Query @{type = $redirectType}
@@ -2706,6 +2742,42 @@ Describe "Invoke-RestMethod tests" -Tags "Feature", "RequireAdminOnWindows" {
$response.Content.Headers."Authorization" | Should -BeExactly "test"
}
+ It "Validates Invoke-RestMethod with -WebSession and -PreserveAuthorizationOnRedirect doesn't change session variable on multiple redirects: " -TestCases $redirectTests {
+ param($redirectType)
+
+ #[SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Demo/doc/test secret.")]
+ $token = "testpassword" | ConvertTo-SecureString -AsPlainText -Force
+ $credential = [pscredential]::new("testuser", $token)
+ $certificate = Get-WebListenerClientCertificate
+ $headers = @{"Authorization" = "test"}
+ $proxy = (Get-WebListenerUrl).Authority
+ $uri = Get-WebListenerUrl -Test 'Redirect' -TestValue 2 -Query @{type = $redirectType}
+
+ $session = [Microsoft.PowerShell.Commands.WebRequestSession]::new()
+ $session.MaximumRedirection = 2
+ $session.MaximumRetryCount = 2
+ $session.RetryIntervalInSeconds = 2
+ $session.UseDefaultCredentials = $true
+ $null = Invoke-RestMethod -Uri $uri -PreserveAuthorizationOnRedirect -WebSession $session -AllowUnencryptedAuthentication -Headers $headers
+ $session.MaximumRedirection | Should -BeExactly 2
+ $session.MaximumRetryCount | Should -BeExactly 2
+ $session.RetryIntervalInSeconds | Should -BeExactly 2
+ $session.UseDefaultCredentials | Should -BeExactly $true
+
+ $session = [Microsoft.PowerShell.Commands.WebRequestSession]::new()
+ $session.Credentials = $credential
+ $session.Certificates = [System.Security.Cryptography.X509Certificates.X509CertificateCollection]::new([X509Certificate]$certificate)
+ $null = Invoke-RestMethod -Uri $uri -PreserveAuthorizationOnRedirect -WebSession $session -SkipCertificateCheck -Headers $headers
+ $session.Credentials.UserName | Should -BeExactly $credential.UserName
+ $session.Credentials.Password | Should -BeExactly $credential.GetNetworkCredential().Password
+ $session.Certificates.Thumbprint | Should -BeExactly $certificate.Thumbprint
+
+ $session = [Microsoft.PowerShell.Commands.WebRequestSession]::new()
+ $session.Proxy = [System.Net.WebProxy]::new($proxy)
+ $null = Invoke-RestMethod -Uri $uri -PreserveAuthorizationOnRedirect -WebSession $session -Headers $headers
+ $session.Proxy.GetProxy($uri).Authority | Should -BeExactly $proxy
+ }
+
It "Validates Invoke-RestMethod strips the authorization header on various redirects: " -TestCases $redirectTests {
param($redirectType)
$uri = Get-WebListenerUrl -Test 'Redirect' -Query @{type = $redirectType}