vazun
vazun

Reputation: 214

Getting CORS error rather than expected 429 response when rate limit is reached

In my backend I implemented an IpRateLimit middleware with the AspNetCoreRateLimit package in my .net core entity framework backend. When an IP Address x makes y calls in a specific time, it gets blocked for a certain time and the backend should return an 429 error and this works fine when testing with postman. But when the I make an request with axios, that is supposed to get blocked because of the ip rate limiter, I receive an axios error:

"Access to XMLHttpRequest at 'https://localhost:44372/api/Users/Login/' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource."
"POST https://localhost:44372/api/Users/Login/ net::ERR_FAILED"

After receiving this error, I have added the needed header, but it hasn't changed the result. Other axios requests to my backend (also post, put and delete) work fine, but when the ip rate limiter hits, I just get the cors error.

I implemented the limiter in my application as in the following tutorial: https://edi.wang/post/2019/6/16/ip-rate-limit-for-aspnet-core

React axios request:

 async function buildPostAndFetch(url, param, header) {
            const finalurl = `${BASE_URL}${url}`;
            return axios.post(finalurl, param, {headers:{"Access-Control-Allow-Origin": "*"}})
            .then(res => {
                response(res);
                return res.data ? res.data : true;
            })
            .catch(err => {              
                handleError(err);
                return false;
            })        
    }

handleError() {
 const handleError = err => {
        setError(true);
   
        if(err.request?.status === 0) {
            console.log("*********************************************")
            console.log(err.request);
            console.log("*********************************************")
            // throw new Error("API is currently offline or you are not connected to the internet:(");
        } else if(err.response.status === 429) {
            console.log("*********************************************")
            console.log(err.response);
            console.log("*********************************************")
        }
    }
}

When requestion and limiter hits I always get in the err.request.status === 0 path.

Upvotes: 4

Views: 2793

Answers (4)

nart
nart

Reputation: 21

Came across the same error. Im my case the problem was in the wrong order of my middleware components in Startup.Configure pipeline. My RateLimit middleware was placed before UseCors component, so it was short-circued request before it could reach the cors middleware. Therefore no cors header in response.

Correct older should be:

public void Configure(WebApplication app, IWebHostEnvironment env)
        {

            //.... other middleware

            app.UseRouting();

            //....

            app.UseCors("YourPolicyName");
            app.UseMiddleware<RequestRateLimitMiddleware>();

            //....
            app.UseAuthentication();
            app.UseAuthorization();

            //....
        }

Upvotes: 2

sideshowbarker
sideshowbarker

Reputation: 88066

Most server systems/runtimes by default don’t add application-set headers to 4xx and 5xx responses but instead only add them to 2xx success responses and maybe to 3xx redirects.

So you may need to do explicit config to force headers to get added to 4xx responses, in order for that 429 response end up with the Access-Control-Allow-Origin header.

In Apache and nginx for example, that’s done by adding the always keyword to the header-setting directive. Maybe your server system has some similar thing.

You get a CORS error because that 429 error has no Access-Control-Allow-Origin header.

Upvotes: 3

mj1313
mj1313

Reputation: 8459

Try:

app.UseCors(opt => opt
    .WithOrigins("http://localhost:3000"")
    .AllowAnyHeader()
    .AllowAnyMethod());

The protocol (http/https) can not be omitted. Also, the cors middleware should be placed after app.UseRouting but before UseAuthorization.

You can see Middleware Order .

Upvotes: -1

GanHJ
GanHJ

Reputation: 330

Firstly, ensure that you have Install-Package Microsoft.AspNetCore.Cors from NuGet.

Then, please add the following to your Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    // Put it before AddMvc() if there's any
    services.AddCors();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    // Put it before UseMvc() if there's any
    app.UseCors(
        options => options
            .WithOrigins("http://localhost:3000")
            .AllowAnyHeader()
            .AllowAnyMethod()
    );

    app.UseMvc();
}

After finish the above configuration, by inspecting on your network tab (Browser's developer tools) you may see the one of the returned response header is access-control-allow-origin : http://localhost:3000.

Upvotes: 0

Related Questions