Search code examples
javascriptreactjsflask-wtformscsrf-protection

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}

Solution

  • 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