2

I would like to authenticate using Windows Integrated Authentication on a single controller action instead of the global application. I have read many articles online and StackOverflow, but have not found an answer. Note, I'm developing in Web API 2.0 and not MVC.

That said, typically to enable Windows Authentication on your whole application, you'd do something like Web API documentation describes:

<system.web>
    <authentication mode="Windows" />
</system.web>

Under the covers, I'm not sure what this does exactly, but I have a suspicion I may be able to replicate it on a single controller action by implementing IAuthenticationFilter as described by Web API documentation. However, I have not found a conclusive article explaining how do to this for Windows Integrated Authentication.

Example of my goal:

At the end of the day, I would like my single web API to accept a request from a client configured to use windows authentication in either of the following client scenarios:

C#

var handler = new HttpClientHandler()
{
    UseDefaultCredentials = true
};

var client = new HttpClient(handler);

Browser

$.ajax({
    url: 'api/testauthentication',
    type: 'GET',
    dataType: 'json',
    xhrFields: {
        withCredentials: true
    }
})

Edit #1

It has come to my attention it's worth noting I would like to accomplish the above programmatically and not through configuration files such as web.config, IIS settings, etc. Also, I'm using OWIN to host the application on my servers.

Scott Lin
  • 1,532
  • 1
  • 18
  • 28
  • Do you mean authentication or authorization? I.M.H.O. you **authenticate** on application level and **authorize** per method. – Caspar Kleijne Jul 18 '16 at 15:01
  • Gotcha. Sounds like if what you're describing is true, then what I'm after is not possible. I desire authentication and not authorization. – Scott Lin Jul 18 '16 at 17:04

2 Answers2

4

Answer is based on this MSDN article.

Essentially, you can define a custom delegate method which specifies which requests to authenticate using Integrated Windows Authentication.

builder in the following code refers to the IAppBuilder instance used in "Startup" code of OWIN self-hosting. See OWIN self-host article for more details on this related topic.

OwinHttpListener httpListener = (OwinHttpListener)builder.Properties[typeof(OwinHttpListener).FullName];
httpListener.Listener.AuthenticationSchemeSelectorDelegate = new AuthenticationSchemeSelector(DetermineAuthenticationScheme);

Then define DetermineAuthenticationScheme delegate method similar to the following:

AuthenticationSchemes DetermineAuthenticationScheme( HttpListenerRequest request )
{
    if ( request == null )
    {
        throw new ArgumentNullException( "request" );
    }

    if ( request.RawUrl.IndexOf( "v1/foo", StringComparison.OrdinalIgnoreCase ) >= 0 )
    {
        return AuthenticationSchemes.IntegratedWindowsAuthentication;
    }

    return AuthenticationSchemes.Anonymous;
}
Scott Lin
  • 1,532
  • 1
  • 18
  • 28
-2

Have you seen the following post? http://www.scip.be/index.php?Page=ArticlesNET38. It appears to be fairly step by step. You didn't mention if you had deployed this or had this in IIS Express running through visual studio but the one part that stuck out to me was the setting change that was required in the IIS Configuration in “My Documents\IISExpress\config

  <windowsAuthentication enabled="true">

Note that it appears this solution only covers the browser based portion of your question. For the non browser based portion, I am assuming that you would have to have the application receive the 401 response.

It looks like there is already a stackoverflow post that covers the HttpClient authentication using local windows credentials

How to get HttpClient to pass credentials along with the request?

Community
  • 1
  • 1
Bill
  • 1,241
  • 17
  • 25
  • I don't see how this solves the ask of requiring authentication on a single API as opposed to the whole application. – Scott Lin Jul 15 '16 at 19:52
  • You must not know web api that well. You decorate the controller actions with the [authorize] attribute. The other actions that do not need authorization should be wide open. – Bill Jul 15 '16 at 20:41
  • Unfortunately, your proposed solution requires that an authorization header be present on every request to the service; otherwise, an Unauthorized response will be returned to the client. My goal is to only authenticate the authorization header for a single controller action as stated in the question. Thanks. – Scott Lin Jul 19 '16 at 21:40
  • Agreed. The architecture can't be achieved. I thought that was too obvious and that I had misread the question, but apparently not. – Bill Jul 19 '16 at 23:55