Vijo
Vijo

Reputation: 45

CSRF Token always empty (Flask-WTF, Jinja, Axios, JavaScript)

I've been trying to integrate CSRF into my Flask app. It consists of a bunch of Python code, some HTML and some JavaScript files.

The initial setup went fine (init.py):

from flask_wtf.csrf import CSRFProtect
csrf = CSRFProtect()
csrf.init_app(app)

This does what it should, requests are blocked/require a CSRF-Token.

However, when I go into the JavaScript files to adjust them accordingly, referencing the csrf token like this:

content= "{{ csrf_token() }}"

only returns "csrf_token()" as the token, but not an actual value.

I assume it's a problem with Jinja (like I have to tell it something, so the method returns a proper value, but I lack knowledge in that aspect).

Upvotes: 0

Views: 883

Answers (1)

santi
santi

Reputation: 169

You mentioned you added the {{ csrf_token() }} line in one of your JavaScript files; however, what Jinja actually takes into account when parsing these kinds of arguments is the explicit HTML file's contents, and thus not accessing external JavaScript files, even though you import them in your HTML file.

Therefore, if you try using it in an implicit script in your HTML, it should work:

main.py:

from flask import Flask, render_template
from flask_wtf import CSRFProtect

csrf = CSRFProtect()
app = Flask(__name__)
app.config.update(
SECRET_KEY='flask_rocks'
)
csrf.init_app(app)

@app.route("/")
def index():
    return render_template("index.html")

if __name__ == "__main__":
    app.run(debug=True, port=8080)

static/script.js:

var mytoken = "{{ csrf_token() }}"

templates/index.html:

<html>
        <head>
                <title>Whatever</title>
        </head>
        <body>
                <script src="{{ url_for('static',filename='script.js') }}"></script>
                <script>
                var myactualtoken = "{{ csrf_token() }}";
                console.log("This will work: " + myactualtoken);
                console.log("This won't work: " + mytoken);
                </script>
        </body>
</html>

Console Output:

This will work: ImZhYWFlMDY5MTEyNzZkODRlNWQ1Y2MyZjAwY2QxZDY2MzJmOTQ1ZDEi.YNnSlQ.MI8T3MbsFAROy81IFCrdESF85rA
This won't work: {{ csrf_token() }}

I suggest looking into the official docs for more insight.

Upvotes: 1

Related Questions