3

I am not sure how to use AntiForgeryToken for my Fetch call. For AJAX example I found here: include antiforgerytoken in ajax post ASP.NET MVC

Can I implement it same way for Fetch? I could not find any example for that. Any help will be appreciated.

My controller`s method looks like:

[Route("comments/new")]
        public ActionResult AddComment(Survey survey)
        {
            survey.Time = DateTime.Now;
            _context.Surveys.Add(survey);
            _context.SaveChanges();
            return Content("Added");
        }

And frontend:

const queryParams = `Name=${this.state.surveyState.name}&Change=${this.state.surveyState.change}&Opinion=${this.state.surveyState.opinion}`;
                    fetch(`/comments/new?${queryParams}`)
                        .then(res => res.json())
                        .then(res => {
                            console.log(res);
                        })
                        .catch(error => {
                            console.error(error);
                        });
mvermef
  • 3,814
  • 1
  • 23
  • 36

1 Answers1

3

My final solution. In Startup.cs need to add:

//config found in some tutorial, sometimes you can find with z X-XSRF-TOKEN, didnt test it
public void ConfigureServices(IServiceCollection services)
{
(...)
services.AddAntiforgery(x => x.HeaderName = "X-CSRF-TOKEN");
services.AddMvc();
}
(...)
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IAntiforgery antiforgery)
        {
            (...)
            app.Use(next => context =>
            {
                if (context.Request.Path == "/")
                {
                    //send the request token as a JavaScript-readable cookie
                    var tokens = antiforgery.GetAndStoreTokens(context);
                    context.Response.Cookies.Append("CSRF-TOKEN", tokens.RequestToken, new CookieOptions { HttpOnly = false });
                }
                return next(context);
            });
            app.UseAuthentication();
            app.UseStaticFiles(); //new configs supposed to be before this line

My POST in SurveyController.cs:

[HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult AddComment(Survey survey)
        {
            if (survey == null)
            {
                return BadRequest();
            }
            survey.Time = DateTime.Now;
            _context.Surveys.Add(survey);
            _context.SaveChanges();

            return Ok();
        }

In JS file, that I have Dialog.js, need to create function getting cookies:

//it is similar like here: https://www.w3schools.com/js/js_cookies.asp
function getCookie(name) {
    if (!document.cookie) {
        return null;
    }
    const csrfCookies = document.cookie.split(';')
        .map(c => c.trim())
        .filter(c => c.startsWith(name + '='));
    if (csrfCookies.length === 0) {
        return null;
    }
    return decodeURIComponent(csrfCookies[0].split('=')[1]);
}

next, when Fetch is triggered:

var csrfToken = getCookie("CSRF-TOKEN");
                    //recommended way in documentation
                    var url = new URL("http://localhost:58256/Survey/AddComment"),
                        params = { Name: this.state.surveyState.name, Change: this.state.surveyState.change, Opinion: this.state.surveyState.opinion };
                    Object.keys(params).forEach(key => url.searchParams.append(key, params[key]));
                    fetch(url,
                        {
                            method: 'POST',
                            headers: {
                                'Content-Type': 'application/json',
                                "X-CSRF-TOKEN": csrfToken //sending token with request
                            },
                            contentType: "application/json; charset=utf-8",
                            credentials: 'include'
                        }
                    )
                        .then(res => res.json())
                        .then(res => {
                            console.log(res);
                        })
                        .catch(error => {
                            console.error(error);
                        });
  • The one issue I can see here is that from a security perspective, your cookies should be secure so you or no one else would be able to read cookies via JavaScript. This is considered a security vulnerability. I have an example that uses a Secure cookie and it works. I'll provide the configuration I have in the Startup file. – Charles Owen Jul 13 '22 at 16:08