ASP.NET Web API Self-Host with Windows Authentication

☆樱花仙子☆ 提交于 2019-12-02 17:10:22

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!

I am a little late to this. However, if you are using Owin to self host and need windows auth. In your startup class you can add the following.

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        HttpListener listener = (HttpListener)app.Properties["System.Net.HttpListener"];
        listener.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication;
    }
}
Szilard Muzsi

Are you sure you're getting through the authentication part? You could use fiddler to check whether the requests are actually going through or whether the server always responds with 401 Unauthorized (since you're using authentication).

You could also try to implement your own custom AuthorizeAttribute and put breakpoints in it to make sure it gets hit (you'll want to override the OnAuthorization method and see if that gets hit).

using System.Web.Http;
public class MyAuth : AuthorizeAttribute
{
    public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        base.OnAuthorization(actionContext); //put breakpoint here
    }
}

Also, make sure you're using the Authorize attribute from System.Web.Http, and not from System.Web.Mvc. See here why.

Have you tried putting the [Authorize] attribute on your controller?

[Authorize]
public class HelloController : ApiController

Here is a link to a short video explaining how to use authorization.

http://www.asp.net/web-api/videos/getting-started/authorization

In essence use the [Authorize] attribute on the class, catch the error and return an HTTP 401 response and then have the client detect it and go to the login page

Just to add, if you're using tpeczek's solution and also using HttpClient, you might need to do this:

        var handler = new HttpClientHandler();
        handler.UseDefaultCredentials = true;
        _httpClient = new HttpClient(handler);
mheyman

Similar to tpeczek's answer but updated to reflect HTTPS usage. tpeczek's answer doesn't work for HTTPS because the call to base.OnConfigureBinding(httpBinding); with HTTPS overwrites the changes. Additionally, you cannot use httpBinding.Security.Mode = HttpBindingSecurityMode.TransportCredentialOnly; with HTTPS.

Use a custom HttpSelfHostConfiguration:

public class NtlmSelfHostConfiguration : HttpSelfHostConfiguration
{
    public NtlmSelfHostConfiguration(string baseAddress)
        : base(baseAddress)
    { }

    public NtlmSelfHostConfiguration(Uri baseAddress)
        : base(baseAddress)
    { }

    protected override BindingParameterCollection OnConfigureBinding(
        HttpBinding httpBinding)
    {
        if (this.BaseAddress.Scheme == Uri.UriSchemeHttps)
        {
            var ret = base.OnConfigureBinding(httpBinding);
            httpBinding.Security.Transport.ClientCredentialType =
                HttpClientCredentialType.Ntlm;
            return ret;
        }

        httpBinding.Security.Mode = HttpBindingSecurityMode.TransportCredentialOnly;
        httpBinding.Security.Transport.ClientCredentialType = 
            HttpClientCredentialType.Ntlm;
        return base.OnConfigureBinding(httpBinding);
    }
}

Then, you can do

var config = new NtlmSelfHostConfiguration("http://myComputerName:8080");

or

var config = new NtlmSelfHostConfiguration("https://myComputerName:8443");

to get a configuration to pass into new HttpSelfHostServer(config)

Related answer for whom need it, about basic auth with token

Merging some help, info, answers and a self auth system that I made for a real Web API I could finally use roles and attributes tags for this. Is made for Authorization tag in the header.

Server invocation:

 var config = new HttpSelfHostConfiguration("http://localhost:8080");
            config.UserNamePasswordValidator = new PHVValidator();
            config.Routes.MapHttpRoute(
                "API Default", "{controller}/{id}",
                new { id = RouteParameter.Optional });

            using (HttpSelfHostServer server = new HttpSelfHostServer(config))
            {
                server.OpenAsync().Wait();
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new DominusForm());
            }

Auth Method: (hardcoded for ex. only, choose user, pass and roles from anywhere)

    public class PHVValidator : System.IdentityModel.Selectors.UserNamePasswordValidator
    {
        public override void Validate(string userName, string password)
        {
            if (userName == "admin" && password == "123")
            {
                string[] rolarray = new string[] { "admin" };
               IPrincipal principal = new GenericPrincipal(new GenericIdentity(userName), rolarray);
                Thread.CurrentPrincipal = principal;
            }
        }
    }

Method:

[Authorize(Roles = "admin")]
public HttpResponseMessage Get()
{
     do things
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!