简体   繁体   中英

How to send API requests with Windows Authentication enabled?

I'm creating an application built with React, where API requests will be sent from http://localhost:3000 to a .NET server at https://localhost:5000 . This works when windows authentication is disabled, but when windows authentication is enabled using IIS, any request, return 401 unauthorized.

I've done quite a bit of research and found that I can send a GET request fine by sending the axios request with { withCredentials: true }. If I send a POST request, this would still return 401 unauthorized from the server, unless I make the request a "simple-request", by setting the content type to application/x-www-form-urlencoded, according to these specifications: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS .

Is there something I need to have in the web config for these requests to work, when windows authentication is enabled?

An answer to a similar question here, does not help me: Angular 5: Post-request & windows authentication , since having both anonymous and windows authentication enabled, will result in the initial GET request to the server, not being able to get the Active Directory username, using windows authentication, since it seems like the Anonymous Authentication takes precedence.

I can make the POST request with the content type set to application/x-www-form-urlencoded, but this seems like the wrong way to go about it. Is there some way I can set some setting on the server, so that when windows authentication is enabled, the server at https://localhost:5000 will accept any API request from http://localhost:3000 with content type of JSON?

You need to setup CORS on the server.

Here are some resources how to do it in Web API 2

Also according W3C spec CORS-preflight request never includes credentials so you might need to enable Anonymous for OPTIONS requests in IIS

UPDATE: Windows Auth vs OPTIONS requests

As I had struggled with the same issue recently, here is a small update.

Solution 1 (which I linked originally) - adding <allow verbs="OPTIONS" users="*"/> really does not work. Or better say it "sort of works" as it requires Anonymous authentication enabled in IIS which is something you don't want when using Windows Auth

Solution 2 actually really works. Key point is the code inside Application_AuthenticateRequest . Also important is that it works only when using integrated pipeline . It solves the problem of OPTIONS requests being stopped by Windows Auth (which happens if you have Anonymous authentication disabled no matter what you do)

Last solution mentioned by some MS employees here and here is to use IIS module (plugin) IIS CORS . Here is a configuration reference and short but useful introduction .

Obvious disadvantage of this is it needs to be installed on every server including your own dev machine. And apparently there is no easy way to install it into IIS Express. Luckily the "The Half-Blood Programmer" has created set of PowerShell scripts to automate this. Tested it and it works pretty well - just don't forget that Visual Studio creates a copy of the main applicationHost.config (usually located in the MyDocuments\\IISExpress\\config\\ folder) in the solution folder .vs\\%projectname%\\config so you might need to run the script again for this copy....

It turned out to be a CORS issue. The interesting thing I found was that enabling CORS in the following two ways do not work when windows authentication is enabled:

WebApiConfig.cs :

// Web API configuration and services
var cors = new EnableCorsAttribute("*", "*", "*") { SupportsCredentials = true };
config.EnableCors(cors);

Web.config :

<system.webServer>
    <httpProtocol>
        <customHeaders>
            <add name = "Access-Control-Allow-Credentials" value="true" />
            <add name = "Access-Control-Allow-Headers" value="Origin, Accept, Content-Type, X-Auth-Token" />
            <add name = "Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
            <add name = "Access-Control-Max-Age" value="86400" />
        </customHeaders>
    </httpProtocol>
</system.webServer>

This is the only way in which I would not get 401 unauthorized back from the API, was when I enabled CORS in the following way by putting it into the Global.asax.cs file, by returning 200 back for OPTIONS requests during the preflight check:

public void Application_BeginRequest(object sender, EventArgs e)
{
    string httpOrigin = Request.Params["HTTP_ORIGIN"];
    if (httpOrigin == null) httpOrigin = "*";
    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", httpOrigin);
    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, X-Token");
    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true");

    if (Request.HttpMethod == "OPTIONS")
    {
        HttpContext.Current.Response.StatusCode = 200;
        var httpApplication = sender as HttpApplication;
        httpApplication.CompleteRequest();
    }
}

In addition to including the withCredentials: true option in the JavaScript call, you must add a few settings in the REST API configuration. If you only enable Windows authentication for the REST API from IIS, you are likely to get the 401 error from the client, since browsers make an OPTIONS call before making the original call to validate CORS access.

来自浏览器的 OPTIONS 方法调用

To enable this validation, you must also enable Anonymous Authentication in your REST API from IIS.

从 IIS 启用身份验证

And add this exception in the web.config file of the REST API:

<system.webServer>
.....
<security>
 <authorization>
    <add accessType="Allow" verbs="OPTIONS" users="?" />
    <add accessType="Deny" verbs="GET, PUT, POST, DELETE" users="?" />
 </authorization>
</security>
</system.webServer>

Where Anonymous Authentication is allowed for OPTIONS type requests, in order to allow CORS validation from the browser. And Anonymous Authentication is denied for the rest of the operations: GET , PUT , POST , DELETE .

You must consider that the OPTIONS method will be enabled for all anonymous calls and you should not use it in your REST API if you are going to validate the authentication.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM