Flask-Security CSRF token

2019-03-25 15:27发布

I have a flask app that serves as REST API backend. I would like to implement token based authentication for the backend but in order to do that I need to retrieve the user token. Flask-Security documentation clearly says that to retrieve the token one needs to perform an HTTP POST with the authentication details as JSON data to the authentication endpoint. Unfortunately I don't understand how to retrieve the CSRF token needed to perform such request.

If I use the login page/template provided with the extension the CSRF token is passed to the client in the hidden field in the form. The question is:

how do I retrieve the CSRF token without accessing and parsing the login page, like for example from an angularJS app using $http methods or a mobile app?

Obviously I could avoid using Flask-Security and implement the pieces myself but I'm relatively inexperienced with webapps and I feel I might be approaching this the wrong way.

5条回答
一纸荒年 Trace。
2楼-- · 2019-03-25 15:51

I fought with this problem for hours last night. Here's what ended up working for me:

When I create my app instance:

app = Flask(__name__)
app.config.from_object(config_by_name[config_name])

# Create database connection object
app.db = db
app.db.init_app(app)

CsrfProtect(app)

In my /login HTML:

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

From Postman:

enter image description here

Here was an alternative I tried, and maybe this will be more successful? This is basically the same reply that the flask-security example apps give:

enter image description here

查看更多
Bombasti
3楼-- · 2019-03-25 16:06

I had a similar use case and ended solving it by following this example from the Flask-WTF docs: https://flask-wtf.readthedocs.org/en/latest/csrf.html#ajax

So by CSRF Protecting the app via CsrfProtect(app), the csrf_token() becomes available in all templates. Then you can easily make it available via a script tag:

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

Now add the token to your post data for the Flask-Security /login endpoint.

查看更多
趁早两清
4楼-- · 2019-03-25 16:09

I haven't tested that this works, but from briefly inspecting the source code it appears you have to send a GET request to the login URL with the content type set to application/json. Flask-Security responds to this request with a JSON version of the login form and that includes the token. Once you have the token you can send the POST request.

查看更多
beautiful°
5楼-- · 2019-03-25 16:12

Well, there is a simple way. Visit. A configuration item WTF_CSRF_ENABLED could be set to False to disable the csrf. Then everything goes as you wish.

查看更多
对你真心纯属浪费
6楼-- · 2019-03-25 16:16

[Writing as an an answer since I do not have enough reputation to comment]

I have run into exact same problem as Jacopo, in that - request.json is empty and thus get_auth_token() is not triggered.

BTW - Flask Security documentation says :

Token based authentication is enabled by retrieving the user auth token by performing an HTTP POST with the authentication details as JSON data against the authentication endpoint.

So I tried POST, not GET (Still same problem of empty request.json) I called /login with json data as :

{"email": "test@example.com", "password": "test123"}

and sent a request using Postman client in Google Chrome.

Yet, request.json is empty :(

Edit : I was able to move forward using python's request module. Details here

查看更多
登录 后发表回答