Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSRF protection with a React Form, a Flask server, and Flask-WTF

TL;DR I need to protect my form from CSRF attacks and I want to use ReactJS for the frontend and Flask/Flask-WTF for the backend.

I’m refactoring a website built with Python, Flask, and Flask-WTF for forms and I want to use React for the frontend rather than Jinja2 through PyPugjs. I’m using Flask-WTF to render the forms and it takes care of the CSRF tokens and such. I know how to make a form with React but how do I get CSRF protection?

Right now my form rendering looks like this: (uses Pug)

mixin render_form(form, id='', action='Submit')
    form(method='POST', action='', id=id)
        =form.csrf_token

        each field in form
            fieldset
                if field.errors
                    each error in field.errors
                        .notification.error
                            #{error}

                #{field(placeholder=field.label.text)}

        button(type='submit') #{action}
like image 558
Hum4n01d Avatar asked Mar 24 '17 17:03

Hum4n01d


People also ask

How can we prevent CSRF in Flask?

To enable CSRF protection globally for a Flask app, register the CSRFProtect extension. CSRF protection requires a secret key to securely sign the token. By default this will use the Flask app's SECRET_KEY . If you'd like to use a separate token you can set WTF_CSRF_SECRET_KEY .

Does react protect against CSRF?

Luckily, it's easy to implement CSRF protection in React. You only have to store the CSRF token in your React app and generate relevant headers to send along with the request to the server. The server will quarantine all CSRF requests.

What is CSRF protection in Flask?

Cross-site request forgery (CSRF) is a web security liability. That permits an attacker to convince users to do actions that they do not offer to do. It lets an assailant to partially avoid the same origin policy that is planned to prevent diverse websites from interfering with each other.

What is WTF Flask?

WTF stands for WT Forms which is intended to provide the interactive user interface for the user. The WTF is a built-in module of the flask which provides an alternative way of designing forms in the flask web applications.


2 Answers

You'll need to send the csrf token as the header X-CSRFToken when you POST the form. See their docs here: http://flask-wtf.readthedocs.io/en/stable/csrf.html#javascript-requests

Their example w/ POSTing via jQuery sets the X-CSRFToken before sending any POST/PUT/DELETE ajax requests:

<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>

Depending on what library you're using to send the form POSTs back to the server, your implementation of setting the header X-CSRFToken will be different.

like image 182
kavun Avatar answered Sep 18 '22 00:09

kavun


You can throw {{ csrf_token() }} in a meta tag in index.html

 <meta  id="csrf-token" content={{csrf_token()}}>

then when you wanna post/fetch, just add it to ur headers with

export const post = (path, data={}) => {

const options = {
    method: 'POST', 
    headers: {
        // 'Accept': 'application/json; charset=utf-8',
        // 'Content-Type': 'application/json; charset=utf-8',
        // 'Cache': 'no-cache',
        // 'X-Requested-With': 'XMLHttpRequest', 
        'X-CSRFToken': document.getElementById("csrf-token").getAttribute("content")
    }, 
    body: data
};

return fetch(path, options);
}

p.s. this still feels hacky and I'm still looking for a more reacty way

like image 24
blah blah Avatar answered Sep 20 '22 00:09

blah blah