I am trying to use the ASP.NET Web API Self-Host option with Windows authentication so I can determine the logged on user and ultimately accept or reject the user based on their identity. Here is my console application code:
using System; using System.Web.Http; using System.Web.Http.SelfHost; namespace SelfHost { class Program { static void Main(string[] args) { var config = new HttpSelfHostConfiguration("http://myComputerName:8080"); config.UseWindowsAuthentication = true; config.Routes.MapHttpRoute( "API Default", "api/{controller}/{id}", new { id = RouteParameter.Optional }); using (HttpSelfHostServer server = new HttpSelfHostServer(config)) { server.OpenAsync().Wait(); Console.WriteLine("Press Enter to quit."); Console.ReadLine(); } } } }
Here is the controller:
[Authorize] public class HelloController : ApiController { public string Get() { // This next line throws an null reference exception if the Authorize // attribute is commented out. string userName = Request.GetUserPrincipal().Identity.Name; return "Hello " + userName; } }
Edit - I added the Authorize attribute, and the debugger shows that the code inside the Get action method is never invoked. The following HTML is returned:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML><HEAD> <META content="text/html; charset=windows-1252" http-equiv=Content-Type></HEAD> <BODY></BODY></HTML>
If the Authorize attribute is commented out, Request.GetUserPrincipal().Identity.Name
throws a null reference exception since Request.GetUserPrincipal()
yields null.
Web API assumes that authentication happens in the host. For web-hosting, the host is IIS, which uses HTTP modules for authentication. You can configure your project to use any of the authentication modules built in to IIS or ASP.NET, or write your own HTTP module to perform custom authentication.
ASP.NET Web API can be either be hosted in IIS or in a separate host process. The former approach is usually appropriate when the Web API is part of a web application and one or more web applications are going to consume it.
I've hit this issue as well and the only solution I've came up with is to deliver dedicated HttpSelfHostedConfiguration:
public class NtlmSelfHostConfiguration : HttpSelfHostConfiguration { public NtlmSelfHostConfiguration(string baseAddress) : base(baseAddress) { } public NtlmSelfHostConfiguration(Uri baseAddress) : base(baseAddress) { } protected override BindingParameterCollection OnConfigureBinding(HttpBinding httpBinding) { httpBinding.Security.Mode = HttpBindingSecurityMode.TransportCredentialOnly; httpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm; return base.OnConfigureBinding(httpBinding); } }
To use it you just need to change one line (you don't need to set UseWindowsAuthentication anymore):
var config = new NtlmSelfHostConfiguration("http://myComputerName:8080");
The only issue with this approach is that authentication is now required for every request made to server which is using this configuration.
i have hosted "Web API" in windows service and this is what i did to support windows authentication (basically based on above question, answers, some related articles - i am just consolidating as it may be helpful for others)
@HTTP Server (web api):
Set (reference: http://msdn.microsoft.com/en-us/library/system.web.http.selfhost.httpselfhostconfiguration.clientcredentialtype(v=vs.118).aspx),
HttpSelfHostConfiguration.ClientCredentialType = System.ServiceModel.HttpClientCredentialType.Windows;
@Client:
And then as Allan mentioned (above) set UseDefaultCredentials to true.
Using HttpClient:
var handler = new HttpClientHandler(); handler.UseDefaultCredentials = true; _httpClient = new HttpClient(handler);
Using WebClient (reference: http://msdn.microsoft.com/en-us/library/system.net.webclient.usedefaultcredentials.aspx )
set webclient's usedefaultcrednetials to 'true'.
Best Regards!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With