CORS in ASP.NET
Tags: programming, security, csharp, dotnet
Published: 2023-05-17 21:28:26

Cross-Origin Resource Sharing (CORS) is an HTTP-header based mechanism that enables a server to specify any origins (domain, scheme, or port) other than its own from which a browser should permit loading resources. It allows many resource requests, such as Ajax or Fetch, originating from a different domain (cross-origin) to be requested on a web domain (origin). CORS relies on a mechanism where browsers make a "preflight" request to the server hosting the cross-origin resource, to check if the server will allow the actual request. During this preflight, the browser sends headers indicating the HTTP method and headers that will be used in the actual request.

## Set up CORS

To set up CORS in ASP.NET, the following steps must be followed:

1. **Install middleware package**: Install the CORS middleware via the NuGet package manager with the command `Install-Package Microsoft.AspNetCore.Cors`.
2. **Add CORS service**: After installing the package, add the cross-origin resource sharing services to the specified `IServiceCollection`.
3. **Configure CORS policies**: Finally, build your policy within the CORS service.

```csharp
builder.Services.AddCors(options =>
{
    options.AddPolicy("MyCorsPolicy",
        builder =>
        {
            builder => builder.WithOrigins("https://example.com")
                .AllowAnyHeader()
                .WithMethods("GET", "POST", "PUT", "DELETE");
        });
});
```

In this example, we created a policy called "MyCorsPolicy" that allows access only to the `https://example.com` domain, makes sure to allow any header, and limits the allowed methods to `GET, POST, PUT, DELETE`.

## Enable CORS

Once the CORS policy has been created, there are several ways in which it can be enabled.

👉 **Using middleware**

Middleware components handle requests and responses in ASP.NET. CORS can be enabled in the middleware either using a named policy or a default policy.

- **Named policy**: You can define one or more named policies, and then select which policy to apply using the policy name at middleware.

```csharp
app.UseCors("MyCorsPolicy");
```

- **Default policy**: Instead of specifying a policy name, you can define a default policy that applies to every request.

```csharp
builder.Services.AddCors(options =>
{
    options.AddDefaultPolicy(
        builder =>
        {
            builder.WithOrigins("https://example.com");
        });
});

// ...

app.UseCors();
```

👉 **Using endpoint routing**

Endpoint routing provides more control over the application's routing. You can enable CORS for specific routes in your application.

```csharp
app.UseEndpoints(endpoints =>
{
    endpoints.MapGet("/test", TestAction).RequireCors("MyCorsPolicy");
    endpoints.MapControllers().RequireCors("MyCorsPolicy");
});
```

👉 **Using the `[EnableCors]` Attribute**

The `[EnableCors]` attribute allows you to enable CORS at a more granular level, specifically at the controller or action level. This attribute provides an alternative to applying CORS policies globally and offers finer control over where and how CORS is implemented within your application.

Utilization of the `[EnableCors]` attribute can be done in several ways:

- `[EnableCors]` applies the default policy.
- `[EnableCors("{Policy String}")]` applies a specific named policy.

The attribute can be applied to different components of your application:

- Razor Page PageModel
- Controller
- Controller action method

By using the `[EnableCors]` attribute, different policies can be applied to various components of your application. However, it's important to note that if the `[EnableCors]` attribute is applied to a controller, page model, or action method while CORS is also enabled in middleware, both policies will be applied. This can lead to unintended behaviors and security implications, so combining policies is generally discouraged. It is advisable to use either the `[EnableCors]` attribute or middleware, but not both in the same application.

```csharp
[EnableCors("MyCorsPolicy")]
public class TestController : ControllerBase
{
    // ...
}
```

In this example, the "MyCorsPolicy" is applied to all actions within the TestController.

## Disable CORS

If you want to disable CORS for specific actions or controllers, you can use the `[DisableCors]` attribute.

```csharp
[DisableCors]
public class NoCorsController : ControllerBase
{
    // ...
}
```

> ⚠️ **Warning**
> The `[DisableCors]` attribute does not disable CORS that has been enabled by endpoint routing.

## CORS criteria options

When defining CORS policies, you can use several methods to customize how the policy behaves:

- **WithOrigins**: Allows you to specify which origins should be allowed to access the resources. This is useful when you want to restrict access to specific domains.
- **WithMethods**: Allows you to specify which HTTP methods are allowed. This can help to tighten security by only allowing the necessary methods for a particular resource.
- **WithHeaders**: Allows you to specify which HTTP headers are allowed. This can be used to restrict which headers are accepted in a request.
- **AllowAnyOrigin**: Allows CORS requests from all origins with any scheme (`http` or `https`).
- **AllowAnyMethod**: Allows any HTTP method.
- **AllowAnyHeader**: Allows any HTTP header.

AllowAny options should be used with caution because they could cause potential security risks, such as allowing any source to access resources, allowing potentially malicious methods, or leading to unintended exposure of headers.

These policy options can be combined and tailored according to the specific needs of your application, providing a high degree of control over your CORS policies. However, it's important to understand the security implications of each option to ensure the safe handling of cross-origin requests.

## Conclusion

Understanding and implementing CORS in ASP.NET is crucial for the security of your web applications. CORS is a mechanism that allows your website to make secure requests to other domains, enhancing interoperability and allowing greater flexibility. However, it's important to remember that CORS must be configured carefully to prevent potential security vulnerabilities. It's crucial to limit access only to trusted origins and use the most restrictive method suitable for your specific needs. Thanks to ASP.NET, configuring CORS is a simple process that can be easily customized to fit various situations.

## References

- [Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)
- [Enable Cross-Origin Requests (CORS) in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-6.0)