Setting WWW-Authenticate response header in DelegatingHandler causes chaos on w2k3

I use my own authentication mechanism by sending a session token. The presence of a token is checked in the DelegatingHandler, which sets the current main principle. If the principal is not allowed to call the ApiController method, the controller sends an unauthorized status of 401. Since RFC 2616 requires setting the WWW-Authenticate header always when sending a 401 response, my DelegatingHandler will take care of this.

Now, in a self-service web API scenario, a request that should respond 401 works correctly in Windows 7, but in Windows Server 2003 it dies with the exception "the existing connection was forcibly closed by the remote host." Further, I noticed that the breakpoint in the controller method hits twice on W2k3, unlike once in Win7, as if HttpClient somehow repeated the request after receiving a 401 response.

When I uncomment the line with the WWW-Authenticate heading, the program works correctly. Please see the code examples below for a minimalist example of playback in a console application.

TestController.cs:

public class TestController : ApiController { public HttpResponseMessage Get() { return Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "go away"); } } 

AuthenticationHandler.cs:

 public class AuthenticationHandler : DelegatingHandler { protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { return base.SendAsync(request, cancellationToken).ContinueWith<HttpResponseMessage>(task => { HttpResponseMessage response = task.Result; if ( response.StatusCode == HttpStatusCode.Unauthorized && !response.Headers.Contains("WWW-Authenticate") ) { // comment out this line and the code works response.Headers.Add("WWW-Authenticate", "SessionToken"); } return response; }); } } 

Program.cs:

  static void Main(string[] args) { HttpSelfHostConfiguration config = new HttpSelfHostConfiguration("http://localhost:81"); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}" ); config.MessageHandlers.Add(new AuthenticationHandler()); using ( HttpSelfHostServer server = new HttpSelfHostServer(config) ) using ( HttpClient client = new HttpClient() ) { server.OpenAsync().Wait(); try { HttpResponseMessage response = client.GetAsync("http://localhost:81/api/test").Result; Console.Out.WriteLine(response.StatusCode); } catch ( AggregateException ex ) { Console.Out.WriteLine(ex.ToString()); } server.CloseAsync().Wait(); } Console.In.ReadLine(); } 

Am I calling the API correctly? Any ideas what could be wrong?

+6
source share
1 answer

You need to install the .NET Framework 4.0.3. Previous versions of the .net framework could not set the www-authenticate header. Get here , more information on this subject is located in KB2600211 .

+3
source

Source: https://habr.com/ru/post/946764/


All Articles