runtime: Simple .NET app throws `(407) Proxy Authentiation Required`

Related to https://github.com/PowerShell/PowerShell/issues/9495#issuecomment-627207665

Why

I was requested to create a .NET app as I’m having this issue.

The context of that request has to come from the fact that PowerShell uses .NET Core internally.

The issue summarized

In PowerShell v7.1 preview 2. On a company network, where direct access to the Internet is not allowed and a PAC file, distributed via DHCP, is used to to set the proxy that the computer should use. This gives issues in PowerShell. Namely this error:

```
VERBOSE: Repository details, Name = 'PSGallery', Location = 'https://www.powershellgallery.com   /api/v2'; IsTrusted = 'False'; IsRegistered = 'True'.
VERBOSE: Using the provider 'PowerShellGet' for searching packages.
VERBOSE: Using the specified source names : 'PSGallery'.
VERBOSE: Getting the provider object for the PackageManagement Provider 'NuGet'.
VERBOSE: The specified Location is 'https://www.powershellgallery.com/api/v2' and PackageManagementProvider is 'NuGet'.
WARNING: Unable to resolve package source 'https://www.powershellgallery.com/api/v2'.
VERBOSE: Total package yield:'0' for the specified package 'invokebuild'.
Install-Package: C:\program files\powershell\7-preview\Modules\PowerShellGet \PSModule.psm1:9709
Line |
9709 |  … talledPackages = PackageManagement\Install-Package @PSBoundParameters
| 
| No match was found for the specified search criteria and module name 'invokebuild'. Try
| Get-PSRepository to see all available registered module repositories.
```

When executing the Install-Module -name invokebuild -Verbose -Scope CurrentUser -Repository PSGallery -Force PowerShell cmdlet.

As described in the issue on the PowerShell repo that I link to in the beginning. I’ve tried setting the below in a PowerShell session (quickly listed).

  • [System.AppContext]::SetSwitch("System.Net.Http.UseSocketsHttpHandler", $false)
  • [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12]
  • [system.net.webrequest]::defaultwebproxy = new-object   system.net.webproxy('http://10.90.100.24:8080')
    [system.net.webrequest]::defaultwebproxy.credentials =                                                                                    [System.Net.CredentialCache]::DefaultNetworkCredentials
    [system.net.webrequest]::defaultwebproxy.BypassProxyOnLocal = $true
    

Simple .NET app

using System;
namespace test
{
    class Program
    {
        static void Main(string[] args)
        {
            var a = System.Net.WebRequest.Create("https://ya.ru");
            var b = a.GetResponse();
            //Console.WriteLine("b");
        }
    }
}

Executing the above app (the project was created with dotnet new console, result in the following err:

Unhandled exception. System.Net.WebException: The remote server returned an error: (407) Proxy Authentication Required.
   at System.Net.HttpWebRequest.GetResponse()
   at test.Program.Main(String[] args) in C:\WORK\repos\test\Program.cs:line 10

From here

If any additional info is needed I’ll happily provide it. To the extent of my power and allowances. Also the PAC script in use might return more than one proxy addresses. But according to the issue (in the PowerShell repo) which I link to in the beginning, this should now be solved. So why could this error be occurring?

Thank you and looking forward to hear from you.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 27 (22 by maintainers)

Most upvoted comments

unfortunately I’m not familiar with PowerShell code. Perhaps it should surface better error.

Reading the docs I expect that UseDefaultCredentials applies implicitly CredentialCache.DefaultCredentials.

Yes, it does imply CredentialCache.DefaultCredentials. However, it only applies for server credentials and not proxy credentials.

So, without the code changes I suggested to the PowerShell module, the proxy will not receive any credentials.

I wonder if it is “by-design”. The documentation says nothing about it:

This is good feedback. We will work on improving our documentation in this area to be more explicit.

@karelz

@larssb

I think only second line enough to have.

[System.Net.Http.HttpClient]::DefaultProxy = New-Object System.Net.WebProxy('http://PROXY_IP:PROXY_PORT', $true)

You don’t need this line if automatic proxy discovery is working correctly, i.e. WPAD protocol, PAC files, etc. However, if it is not working, then setting an explicit proxy is ok too.

I got it to work by using the following code in my PowerShell profile script:

# For PowerShell to use the Proxy system settings. The bewlow is PS 6 core + compatible
# $true to the System.Net.WebProxy constructor is to indicate that the proxy should be bypassed for local addresses
[System.Net.Http.HttpClient]::DefaultProxy = New-Object System.Net.WebProxy('http://PROXY_IP:PROXY_PORT', $true)
[System.Net.Http.HttpClient]::DefaultProxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials

Thank you guys. I can finally install PowerShell modules in PS7 Core. Greatness achieved 💯

@iSazonov cool if a solution/fix will be ported into a coming PS7 release.

I’ll try to use the HttpClient tomorrow, when I’m back at work. To see if that fixes the issue. Sounds very plausible from the great walk-through in this issue. Great stuff. Thank you very much.

And as I understand it @iSazonov … there is something that gives you info for a potential fix, to be back-ported into the PowerShell repo? Or am I too hasty here?

It seems that the remaining work is to document that UseDefaultCredentials does NOT affect proxy credentials and that devs should set DefaultProxyCredentials if they desire so. We may add comment that UseDefaultCredentials is just shortcut for handler.Credentials = CredentialsCache.DefaultCredentials.

Is that correct summary?

Also:

handler.UseDefaultCredentials = true;

is really just a shortcut to doing this:

handler.Credentials = CredentialsCache.DefaultCredentials;

Is there a reason CredentialCache.DefaultCredentials cannot be used by default for proxy?

It would be a breaking change in behavior to do that. And having any option to pass credentials by default has security concerns.