Swimburger

Configure CORS using AppSettings or Custom Configuration Sections in ASP.NET Web API

Niels Swimberghe

Niels Swimberghe - - .NET

Follow me on Twitter, buy me a coffee

Skip the basics and go straight to the 'AppSettingsCorsAttribute' implementation or the 'ConfigCorsPolicyAttribute' implementation.

Browsers don't allow you to make AJAX requests from one origin to another, also referred to as 'Cross Origin Resource Sharing' (CORS). An origin in this context means the combination of domain, protocol, and port.
If CORS wasn't a thing, any website could make AJAX requests to your bank's website. If you happen to be signed in, websites could potentially make transactions without your knowledge. Luckily CORS does exists and won't allow this.

This security measure does mean it is harder for the front-end of websites to communicate with a back-end hosted on a different origin. The back-end can explicitly allow cross-origin resource requests by using the following headers:

Access-Control-Allow-Origin
A comma separated list of origins you want to allow cross origin requests from. Instead of allowing origins explicitly, you can use '*' as a wildcard for all websites. You cannot use the wildcard option in combination with Access-Control-Allow-Credentials.
Access-Control-Expose-Headers
A comma separated list of headers that the client can access when receiving the response. Instead of allowing headers explicitly, you can use '*' as a wildcard to expose all headers.
Access-Control-Allow-Headers
A comma separated list of headers that the client can access when receiving the response. Instead of allowing headers explicitly, you can use '*' as a wildcard to allow all headers.
Access-Control-Allow-Methods
A comma separated list of HTTP methods that the client are allowed to use for the CORS request. Instead of allowing methods explicitly, you can use '*' as a wildcard to allow all methods.
Access-Control-Allow-Credentials
By default, CORS requests will not pass credentials. The client needs to explicitly set the property withCredentials to true on XMLHttpRequest objects. Additionally, the server also needs to return the following header Access-Control-Allow-Credentials: true.
Access-Control-Max-Age
Before sending the actual CORS request, the browser will send a pre-flight request to check the CORS headers. This header will determine how long the pre-flight request will be cached

There's a lot more details to how CORS functions and how implementations differ among browsers which is very well document by Mozilla.

Add CORS support to ASP.NET Web API #

Install the following package into your Web API project:

Call the EnableCors function on your HttpConfiguration on startup. Usually this is done in the WebApiConfig.Register function:

Add the following attribute to the controller or action you want to enable CORS for:

Now webpages hosted on 'https://localhost:44310' can make AJAX requests to your controller/action.
You can also define CORS globally by passing the attribute to EnableCors:

For more details on how to use the Microsoft provided CORS support, check out 'Enable cross-origin requests in ASP.NET Web API 2'.

Use AppSettings to configure CORS #

All code in this article can be found on this GitHub repository.

The attributes provided by the CORS library work well, but you do have to hardcode the values into the attribute. Only constants are allowed in attributes, so when you have to change the parameters, you have to update the attribute parameters manually and recompile. Having to recompile to update the CORS policy may be a deal breaker if:

  • If you have to move your API to a different origin (domain, protocol, and port)
  • If you have you need to change CORS policy when deploying your app to a different location (DEV vs staging vs prod)
  • If you have an API used by more and more clients over time.

Instead of hardcoding the CORS policy into the attribute, you can create your own attribute implementing the ICorsPolicyProvider interface.
The library will automatically pick up on the attribute and call the interface method Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request, CancellationToken cancellationToken).
Add the following class to your project:

The attribute above will accept the AppSetting keys in the constructor and extract the CORS policy configuration from the configuration AppSettings.

Note: The less commonly used CORS headers are not configurable by the above attribute. The CorsPolicy class does support them, so if you need them you can add support by extending the attribute.

Replace the EnableCors attribute with the following attribute:

Add the following AppSettings to your web.config:

Now you can update the CORS policy without having to recompile, though the IIS website will be recycled when you modify the web.config file.

A big advantage of using AppSettings is that many platforms such as Azure App Service allow you to override the AppSettings with App Service Configuration or App Configuration.

To make the CORS policy even more reusable, you can create attributes inheriting from AppSettingsCorsAttribute and specify the AppSetting keys in the constructor as shown below:

Now you can simply decorate your controller and actions with CorsPolicyAAttribute or CorsPolicyBAttribute. Here's an example:

Use a Custom Configuration Section to configure CORS #

All code in this article can be found on this GitHub repository.

Using AppSettings to configure CORS is a huge improvement over hardcoding, though you may prefer a more purpose made configuration section. 

Add the following code to your project:

This configuration section will allow you to create CORS policies in a more structured way in your configuration file.

Add the following attribute to your project:

This attribute will read the custom configuration section and configure the CORS policy from the config file.

Update your web.config with the following custom configuration section:

Now you can decorate your controllers and actions using the ConfigCorsPolicyAttribute by passing in the key of the policy into the constructor. Here's an example:

With this approach you have a more structured configuration, but the drawback is that you cannot override the policies like you could with AppSettings in Azure.

Note: The less commonly used CORS headers are not configurable in the implementation above. The CorsPolicy class does support them, so if you need them you can add support for them in the attribute.

Summary #

In this article you learned the very basics of CORS and how to add CORS support to ASP.NET Web API using

  • out-of-the box EnableCors attribute
  • Custom AppSettingsCors attribute that pulls the policy configuration from web.config AppSettings
  • Custom ConfigCorsPolicy attribute that pulls the policy configuration from a web.config custom configuration section

Warning: Although CORS headers allow you to use a wildcard (*), it is not recommended. Please explicitly specify which origins you want to allow if possible.

Related Posts

Related Posts