Misconception about 'AllowedHosts' in a .NET C# Web API

Misconception about 'AllowedHosts' in a .NET C# Web API

08 Oct 2023

Did you ever come across the "AllowedHosts": "*" setting in a server-side .NET project and wondered what it does? I have. I did my due diligence on the subject, but once in production, I was proven wrong.

What is 'AllowedHosts'?

It is the configuration for the ASP.NET Core host filtering middleware. With this setting, you can specify one or more host names from which your project allows incoming HTTP requests. Requests without a matching host name will be refused.

A host name is the domain name of the target server, the request is sent to.

Let's say you have an API running on https://www.weather-api.com. The host name would be weather-api.com. You could specify to only allow requests with that host name.

{
    AllowedHosts: "weather-api.com"
}

Or to allow multiple host names semicolon delimited.

{
    AllowedHosts: "weather-api.com;v1.weather-api.com;v2.weather-api.com"
}

Or use a wildcard.

{
    AllowedHosts: "*.weather-api.com"
}

The above will allow requests with a correct host name and disallow requests without matching host names. A host name is set on a request as an HTTP header: Host: weather-api.com.

Doesn't this sound similar as CORS to you?

What is CORS?

In short, the ASP.NET Core CORS (Cross Origin Resource Sharing) middleware can be configured to allow requests originating from different domains to interact with server-side .NET project.

By default, without this middleware, a server-side project only allows same-origin requests. These are requests originating from the same domain as the one, the server-side project is running on.

So, the CORS middleware can be configured to enable cross-origin requests from applications deployed on a different domain. The originating domain name is also set on a request as an HTTP header: Origin: https://www.morning-walk.com.

The origin header is set to the domain, the request originated from

Allowing requests from the above origin can be configured as follows:

app.UseCors(options =>
        options.WithOrigins("https://www.morning-walk.com")
            .AllowAnyMethod()
            .AllowAnyHeader());

What's the difference?

Requests made by a browser usually sets both the Host and Origin headers. Requests made by tools like Postman or by someone running a project locally, will only set the Host header or none of the above.

When there is no Origin header present, the CORS middleware will not intervene. The host filtering middleware could intervene and return a 400 Bad Request when the host name does not match.

Got it! Both middlewares can allow or disallow requests based on their HTTP header. So ... I can protect my API from unwanted origins and unwanted hosts?

Not entirely ... Unfortunately the host filtering middleware cannot be used in the same way as the CORS middleware. The host filtering middleware allows any request as long as the Host header is correctly pointing to its target server.

Setting "AllowedHosts": "*" or "AllowedHosts": "weather-api.com" would not make much of a difference if the goal is to block requests.

Once in production, inspecting the HTTP headers:

Request 1:

Host: weather-api.com
Origin: https://www.morning-walk.com

Request 2:

Host: weather-api.com
Origin: https://kiss-code.com

Do you see how you could block requests based on its origin but not based on the host?

Misconception

I assumed the host name and origin name would come from the same domain, which is wrong. I approached the host filtering in the same way as the CORS configuration. I assumed the values below and tried to filter hosts based on it.

Request 1:

Host: morning-walk.com
Origin: https://www.morning-walk.com

Request 2:

Host: kiss-code.com
Origin: https://kiss-code.com

If you are interested in more of my work, you can find it:

Subscribe to my newsletter to stay up-to-date & receive discounts.


Join the community

I continuously build, learn and experiment with innovative technology. Allow me to share what I learn, with you.

Newsletter

Allow me to share what I learn, with you.

Share

Support

An error has occurred. 🗙