Search code examples
c#asp.net-coreantiforgerytoken

Enabling antiForgery on .Net Core 3.1 results in BadRequest


I'm trying to implement the antiforgery mechanism provided in the .net Core 3.1 framework, however I'm always getting a 400 Bad Request when trying to send a Request that requires validation. The application is a web api that uses Odata, Entity Framework, Oracle. It uses JWT for authentication and authorization. It currently works as expected but I was asked to save the JWT within a cookie and therefore I need to implement some sort of security against XSRF attacks.

I know this seems like a duplicate question but I think I've followed every suggested answer I've come across but to no avail.

In the ConfigureServices I have

services.AddCors(c =>
        {
            c.AddPolicy("AllowOrigin", options => options
                //.AllowAnyOrigin()
                .WithOrigins("https://localhost:5001") 
                .AllowAnyHeader()
                .AllowAnyMethod()
                .AllowCredentials()
                );
        });

        services.AddAntiforgery(options =>
        {
            // Set Cookie properties using CookieBuilder properties†.
            options.HeaderName = "X-XSRF-TOKEN";
            options.SuppressXFrameOptionsHeader = false;
            //options.Cookie.Name = "XSRF-TOKEN";
        });

        services.AddMvc(o =>
        {
            o.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
        });

I have a dedicated endpoint that allows the user to log in and it generates the cookies required by the software, including the antiforgery cookies (XSRF-TOKEN and .AspNetCore.Antiforgery.IwdqSLfpWIs)

var aft = _antiForgery.GetAndStoreTokens(HttpContext);
                Response.Cookies.Append("XSRF-TOKEN", aft.RequestToken, new CookieOptions
                {
                    HttpOnly = false
                    //,IsEssential = true
                    ,Secure = true
                    //TODO: Varias de entorno
                    ,Domain = "localhost"
                });

When using postman, I can log in and I get the cookies. I can successfully make GET requests but everytime I try to do a POST Request that requires the antiForgeryValidation I get a 400 Bad Request response. If I disable the validation for a particular POST endpoint, such endpoint works correctly.

In each request I'm setting the header X-XSRF-TOKEN and the value I'm assigning to it is equal to the value of the XSRF-TOKEN. Something like

CfDJ8LjjmjsmmflNk1FyHauE92b4PAjyLk1a1uwJhdrkDydkihsu5yBE3K54ZmF2dl6716tjhpmHUzukg1aW1ubXQzCrZjO0xIgrw-282MH2CLrHcPavgtTJ2TnrYnALJz-mUKiMqkIQHYpicnO9jJaGZrA

The Request in postman looks something like this:

PostManRequest

When doing requests like that I can see the tokens in the context.Request (all 4 cookies, including the X-XSRF-TOKEN and values it's the one I set up in PostMan)

I'm totally confused, this implementation seems particuarly easy yet I'm unable to do it right. Please help.


Solution

  • My mistake was trying to do the login and set the antiforgery cookie "all at once" in a single request. Once I did the login in one request and set the cookies in another request, everything worked as expected.