2

According to the Flask-WTF documentation

this is how to pass the CSRF Token when using AJAX

<script type="text/javascript">
    var csrf_token = "{{ csrf_token() }}";

    $.ajaxSetup({
        beforeSend: function(xhr, settings) {
            if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
                xhr.setRequestHeader("X-CSRFToken", csrf_token);
            }
        }
    });
</script>

Is there a way to implement the CSRF protection when using fetch API?

Also tried adding the credentials: 'include',

*Edit I am getting 2 errors:

the CSRF token is missing 
The CSRF session token is missing

Here is my code

  let csrf_token = "{{ csrf_token() }}";
 let payload = {
        // some data
        "csrf_token": csrf_token
      }

let header = {   'content-type': 'application/json','accept': 'application/json',"X-CSRFToken": csrf_token}
paypal.Buttons({

    createOrder: function(data, actions) {
                return fetch(prefix.concat("/payment/paypalCreate"), {
                  method: "POST",
                  headers: header ,
                  body:JSON.stringify(payload),
                  credentials: 'include',
                  })
                    .then(function(res) {
                        return res.json();
                    }).then(function(data) {
                      console.log(typeof(data))
                        return data.id
                    })
                .catch(err => {
                  console.log(err);
                });
        }
Reub
  • 665
  • 2
  • 18
  • 35
  • Not an exact duplicate as it is a Django question but see https://stackoverflow.com/questions/43606056/proper-django-csrf-validation-using-fetch-post-request – Selcuk Oct 14 '19 at 02:26
  • @Selcuk doesnt seem to work. – Reub Oct 14 '19 at 02:43

2 Answers2

1

I found a way around this and I don't know if anyone needs it but... I just passed the csrf token to the javascript function Here is my javascript.

function deleteUser(userId, csrf) {
  fetch('/admin/deleteUser', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-CSRF-TOKEN': csrf
      },
      body: JSON.stringify({
        userId: userId
      })
    }).then(response => response.json())
    .then(data => {
      console.log('Success:', data);
      window.location.href = data
    })
}
Then in my template where I passed the csrf token to the function
<button onclick="deleteUser({{ User.id }}, '{{ csrf_token() }}')">
 from flask_wtf.csrf import CSRFProtect
    #depending on how you define app 
    #either 
    CSRFProtect(app) 
    #or 
    csrf = CSRFProtect()
    csrf.init_app(app)
Dharman
  • 30,962
  • 25
  • 85
  • 135
0

I know it is old question but it might help if needed.

from flask_wtf.csrf import CSRFProtect
#depending on how you define app 
#either 
CSRFProtect(app) 
#or 
csrf = CSRFProtect()
csrf.init_app(app)

And add a onsubmit="fetchSumbitWtf(event)" to the form element and fetch function would be

function fetchSumbitWtf(e) {
    e.preventDefault();
    data = {"first": "first", "second": "second"}
    var url = "/some/";
    console.log(e.target.csrf_token.value)
    fetch(url, {
        method: 'POST', 
        headers: {
          'Content-Type': 'application/json',
          'X-CSRF-TOKEN': e.target.csrf_token.value
        },
        body: JSON.stringify(data),
        credentials: 'same-origin'
      })
      .then(response => response.json())
        .then(data => {
            console.log(data)
        })
        .catch((error) => {
            console.log("error happened")
        });
}

flask view function could be

@app.route("/some/", methods=["POST"])
def fetch_form():
    form = SomeFlaskForm()
    if form.validate_on_submit():
        print("validated")
        return jsonify({"Success": True}), 200