Tuesday, May 17, 2022

CORS with Windows Authentication in IIS

This post is about web security. How to enable CORS when the producer uses Windows authentication¹. The primary technology stack used here is Microsoft.Net.

Background

The web works on WebAPIs. WebAPIs are the entry points to consume services produced by producers. Often, the WebAPIs are exposed to the web applications published by the same producer. Say, Yahoo Finance is exposing WebAPIs to retrieve financial data. If they don't protect the API, anyone can build a web application by consuming the Yahoo Finance API. They can place Google ads for monetization.

To prevent that, browsers have a mechanism. That will allow sites to call APIs having the same domain name. But, there will be genuine situations to allow cross-domain access. An application needs to call a WeatherAPI exposed in a different domain name..

CORS

Cross-Origin Resource Sharing comes to help when we want to control who can call our APIs. It is based on headers. We can summarize as follows
  1. The browser asks the producer whether it allows the current application's domain name to call API
    1. It's called preflight using the HTTP OPTIONS verb.
  2. The producer responds to the browser with whether it allows calls from the current domain name. Including what HTTP verbs are supported. 
Read the Mozilla docs² for a better understanding.

If the producer is using ASP.Net Framework technology, they can specify who can access it by having the below web.config entries.

<system.webServer>
    <httpProtocol>
      <customHeaders>
        <clear />
        <add name="Access-Control-Allow-Origin" value="https://consumer.com" />
        <add name="Access-Control-Allow-Methods" value="GET,POST,OPTIONS" />
        <add name="Access-Control-Allow-Headers" value="*" />
        <add name="Access-Control-Allow-Credentials" value="true" />
      </customHeaders>
    </httpProtocol>  
 
Hope the above code snippet is self-explanatory. It allows the https://consumer.com domain to access the producer's APIs only using HTTP GET, and POST verbs. It is possible as the producer is sending these custom headers whenever any call is made to it.

The same can be done using C# or VB.Net code as well.

Problem

This works great for most of the scenarios other than Windows authentication. When the producer is using Windows Authentication, things go wrong. The reason is preflight request doesn't have any authentication information. The producer will fail the preflight request. Causing the browser to cancel any further requests.

Solution

The Windows authentication is normally enabled at the webserver level. If it's ASP.Net on .Net Framework, there will be web.config. Follow the below steps
  • The preflight requests should be anonymous
  • To do that have <authorization> tag as follows 
<authorization>
      <allow verbs="OPTIONS" users="*"/>
      <deny users="?" />
</authorization>

Now anyone who is hitting the OPTIONS endpoint will have the custom headers even if the authentication is windows.

How to do this in ASP.Net Core?

The ASP.Net Core model uses middleware technology to achieve the CORS headers³. The <authorization> tag mechanism is achieved by Authorization middleware. 

References

No comments: