FlaskWTF how to send CSRF token to Vue front-end

Mat*_*att 3 javascript python flask flask-wtforms vue.js

I'm working on an app with Vue frontend and Flask backend.

I am writing my forms in Vue but I'm trying to use FlaskWTF for CSRF/XSRF security and for form validation on the back-end.

I've wrapped my app in CSRFProtect() as they say to do in the FlaskWTF docs, if using AJAX.

from flask_wtf.csrf import CSRFProtect

app = build_app()
csrf = CSRFProtect(app)
Run Code Online (Sandbox Code Playgroud)

But I'm stuck on how to send over the CSRF token in a form that is readable for Vue. In their docs they suggest rendering a template with the following script:

<form method="post">
    <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
</form>
Run Code Online (Sandbox Code Playgroud)

And then settings headers on future post request with the following code:

<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>
Run Code Online (Sandbox Code Playgroud)

However, I'm not using jQuery, and I'm stuck on how to even access the token when it's sent as a giant script tag in my response payload (see more details on this problem in this question that I posted).

With all that in mind -- what is the best practice for handling CSRF using FlaskWTF+Vue? How should I be sending over my CSRF token and how should I be receiving it with Vue?

Nic*_*ick 6

This is a fairly opinionated question with no "right" answer. My preference for SPAs is to do a cookie-to-header token flow, meaning your backend issues a csrf token cookie and your front-end sends it back as a header. This is a fairly prevalent pattern and fetch libraries like axios will automatically find your CSRF token cookie and append it to requests to your backend as a header.

It looks like in Flask-WTF you can generate a csrf token and add it as a cookie yourself:

from flask_wtf.csrf import generate_csrf

@app.after_request
def set_xsrf_cookie(response):
    set_cookie('CSRF-TOKEN', generate_csrf())
    return response
Run Code Online (Sandbox Code Playgroud)

At this point, you'll want to make sure you see a "CSRF-TOKEN" cookie being set from the server. If so, you're good to move on to the next step, which is sending this token back as a header.

为此,您可以将获取客户端配置为始终将相同的令牌作为X-CSRF-TOKEN标头发送回来,但我个人喜欢 axios 获取客户端,因为它会自动为您执行此操作。

  • 如果您只是将 cookie 不变地发回,那么您实际上并没有消除攻击向量。通过强制客户端将 cookie 转换为标头,您可以验证客户端是否允许读取 cookie,这对于攻击者来说是不可能的 (3认同)