How to support multiple authentication in self host

Since we build web api self host story on top of WCF HttpTransportBindingElement, the multiple authentication is not support on WCF for 4.0. Here is the exception you will get if you tried to set the authentication scheme on httptransport binding element.

"System.ArgumentException: The 'Negotiate, Anonymous' authentication scheme has been specified on the HTTP factory. However, the factory only supports specification of exactly one authentication scheme. Valid authentication schemes are Digest, Negotiate, NTLM, Basic, or Anonymous."

The good news is that this has been fixed in .NET framework 4.5 Beta. This is the link https://msdn.microsoft.com/en-us/library/ms171868(v=vs.110).aspx#windows_communication_foundation.

"Ability to support multiple authentication modes on a single WCF endpoint when using the HTTP transport and transport security. "

 So with that fix in mind, web api now provides an extensibility point for people to set the authentication schemes.

 Step 1: Derive from HttpSelfHostConfiguration, and register an action to modify TransportBindingElement, and modify the authentication scheme in the action.

Code Snippet

  1. class MultipleAuthenticationHttpConfiguration : HttpSelfHostConfiguration
  2.         {
  3.             public MultipleAuthenticationHttpConfiguration(string baseAddress)
  4.                 : base(baseAddress)
  5.             {
  6.             }
  7.  
  8.             protected override BindingParameterCollection OnConfigureBinding(HttpBinding httpBinding)
  9.             {
  10.                 httpBinding.ConfigureTransportBindingElement = new Action<HttpTransportBindingElement>(ConfigureTransportBindingElement);
  11.                 return base.OnConfigureBinding(httpBinding);
  12.             }
  13.  
  14.             void ConfigureTransportBindingElement(HttpTransportBindingElement bindingElement)
  15.             {
  16.                 // uncomment the following line if running on 4.5
  17.                 // bindingElement.AuthenticationScheme = AuthenticationSchemes.Negotiate | AuthenticationSchemes.Anonymous;
  18.                 bindingElement.AuthenticationScheme = AuthenticationSchemes.Negotiate;
  19.             }
  20.         }
  

Step 2: use the derived the configuration object instead

Code Snippet

  1. var config = new MultipleAuthenticationHttpConfiguration(Program.BaseAddress);
  2.                 config.Routes.MapHttpRoute("Default", "{controller}", new { controller = "Sample" });
  3.  
  4.                 SetupConfig(config);
  5.  
  6.                 server = new HttpSelfHostServer(config);
  7.                 server.OpenAsync().Wait();
  8.                 Console.WriteLine("Service listening at: " + Program.BaseAddress);