runtime: AddJwtBearer doesn't consider system proxy settings

Description

When we have an Authority to validate the access token and environment variables for proxy settings have been defined (HTTP_PROXY, HTTPS_PROXY, NO_PROXY), the HttpClient which is responsible to make a request to the Authority url seems doesn’t consider system proxy settings.

Reproduction Steps

    builder.Services
      .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
      .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
        {
          options.Authority = JWT_AUTHORITY;
          options.SaveToken = true;
          options.TokenValidationParameters = new TokenValidationParameters
          {
            ValidateIssuer = false,
            ValidateAudience = false,
            RequireAudience = false,
          };
        }
      );

Expected behavior

The request should be successful.

Actual behavior

System.InvalidOperationException: IDX20803: Unable to obtain configuration from: '[PII of type 'System.String' is hidden. For more details, see https://aka.ms/IdentityModel/PII.]'.
 ---> System.IO.IOException: IDX20804: Unable to retrieve document from: '[PII of type 'System.String' is hidden. For more details, see https://aka.ms/IdentityModel/PII.]'.
 ---> System.Net.Http.HttpRequestException: The proxy tunnel request to proxy 'http://proxy.site.net:8080/' failed with status code '503'."
   at System.Net.Http.HttpConnectionPool.EstablishProxyTunnelAsync(Boolean async, HttpRequestHeaders headers, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.AddHttp11ConnectionAsync(HttpRequestMessage request)
   at System.Threading.Tasks.TaskCompletionSourceWithCancellation`1.WaitWithCancellationAsync(CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.GetHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
   at Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(String address, CancellationToken cancel)
   --- End of inner exception stack trace ---
   at Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(String address, CancellationToken cancel)
   at Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectConfigurationRetriever.GetAsync(String address, IDocumentRetriever retriever, CancellationToken cancel)
   at Microsoft.IdentityModel.Protocols.ConfigurationManager`1.GetConfigurationAsync(CancellationToken cancel)
   --- End of inner exception stack trace ---
   at Microsoft.IdentityModel.Protocols.ConfigurationManager`1.GetConfigurationAsync(CancellationToken cancel)
   at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
   at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
   at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.AuthenticateAsync()
   at Microsoft.AspNetCore.Authentication.AuthenticationService.AuthenticateAsync(HttpContext context, String scheme)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Company.ExceptionHandlingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) in

Regression?

No response

Known Workarounds

We had to set the proxy settings directly and it worked

    builder.Services
      .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
      .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
        {
          options.Authority = JWT_AUTHORITY;
          options.BackchannelHttpHandler = new HttpClientHandler
          {
            UseProxy = true,
            Proxy = new WebProxy
            {
              Address = new Uri("http://proxy.site.net:8080"),
              BypassProxyOnLocal = true,
              BypassList = new string[] { "localhost" },
            }
          };
          options.SaveToken = true;
          options.TokenValidationParameters = new TokenValidationParameters
          {
            ValidateIssuer = false,
            ValidateAudience = false,
            RequireAudience = false,
          };
        }
      );

Configuration

  • .NET 6.0
  • Windows 10 Enterprise
  • x64

Other information

No response

About this issue

  • Original URL
  • State: closed
  • Created 10 months ago
  • Comments: 19 (13 by maintainers)

Most upvoted comments

From the exception, it seems proxy is being taken into account, it just return 503 HTTP status code. That looks like proxy issue, not client issue.

I think the exception posted does not make it clear that we do not expect the request to go through the proxy in the first place, so the 503 status code is misleading.

In the original code (without defining a WebProxy), the endpoint being requested as JWT_AUTHORITY is https://localhost:4444/. And we have a NO_PROXY environment variable defined as localhost. But the original code still results in a request to https://localhost:4444/ being routed through the system proxy, which fails as expected with 503 error.

Also, I did NOT understand clearly what is the original report about – from reply #90985 (comment) it seems that the KEY problem is that NO_PROXY is being ignored for localhost, while HTTPS_PROXY works correctly. Is that good summary?

Yes, that is correct.

It would be great to see if vanilla HttpClient works. That will tell us if this is the right place to file an issue. Can you folks give it a try?

Thank you, we will check this again and get back to you.