Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Token based authentication with flask-security extension

I am currently looking for a way to secure a REST API using token based authentication. I am developing the API in Python using Flask and have discovered the flask-security extension which seems to have a lot of interesting features.

One of the features mentioned in the documentation is Token Authentication.

According to the documentation:

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. A successful call to this endpoint will return the user’s ID and their authentication token. This token can be used in subsequent requests to protected resources.

I am however still a bit confused on how to implement this feature using flask-security. Some online research has led me to using things such as @auth_token_required but I am having some trouble to put everything together. The flask-security documentation itself is not very helpful.

For example, how can a user get an authentication token? what is the authentication endpoints?

It would be great if you could lead me in the right direction. Code examples would be awesome too :-)

like image 279
user2483431 Avatar asked Dec 08 '14 11:12

user2483431


People also ask

How do I get my authorization token in Flask?

To install it, type sudo apt install python3-venv in your terminal and then you are good to go. If you are on windows then use something like virtualenv to make a virtual environment. This will create a folder named venv in the flask project which will contain the project specific libraries.

Does Flask have security?

Flask-Security allows you to quickly add common security mechanisms to your Flask application. They include: Session based authentication. Role management.

How do I secure a Flask API?

Integrate the Security Library The code for a working OAuth secured Python Flask API is provided below: The OAuth filter is configured to run before API requests. The filter verifies the token signature and the expected issuer / audience claims. API routes can then access JWT claims in the request object.


3 Answers

Endpoint is /login, you post your credentials as json request body:

{'email':'[email protected]', 'password':'1234'}

However for this to work you need to disable the csrf tokens in your flask app (thanks Mandar Vaze):

app.config['WTF_CSRF_ENABLED'] = False

Then you do each request with the token in the HTTP headers:

Authentication-Token:WyI1NTE1MjhmNDMxY2Q3NTEwOTQxY2ZhYTgiLCI2Yjc4NTA4MzBlYzM0Y2NhZTdjZjIxNzlmZjhiNTA5ZSJd.B_bF8g.t1oUMxHr_fQfRUAF4aLpn2zjja0

Or as query string:

http://localhost:5000/protected?auth_token=WyI1NTE1MjhmNDMxY2Q3NTEwOTQxY2ZhYTgiLCI2Yjc4NTA4MzBlYzM0Y2NhZTdjZjIxNzlmZjhiNTA5ZSJd.B_bF8g.t1oUMxHr_fQfRUAF4aLpn2zjja0

Client example in python 3:

import requests
import json

#do the login
r = requests.post('http://localhost:5000/login', 
                    data=json.dumps({'email':'[email protected]', 'password':'1234'}), 
                    headers={'content-type': 'application/json'})
response = r.json()
print(response) #check response
token = response['response']['user']['authentication_token']    #set token value

#Now you can do authorised calls
r = requests.get('http://localhost:5000/protected', 
                headers={'Authentication-Token': token})
print(r.text)

Angular example snippet to obtain the token:

$http.post('/login', {"email": $scope.formdata.login,"password":$scope.formdata.password}).
            success(function(results) {
            $window.sessionStorage.token = results.response.user.authentication_token;
            });

Angular example snippet to visit protected pages:

 if ($window.sessionStorage.getItem('token')) {
                config.headers['Authentication-Token'] = $window.sessionStorage.getItem('token');
            }
like image 95
Sebastian Avatar answered Sep 29 '22 09:09

Sebastian


I found Flask-Security's token-based not a good candidate for my project. I recommend using JWT token instead.

The problems with Flask-Security's token based authentication.

  1. Need to disable CSRF globally, this is not good when you also have a traditional web application in which CSRF token is desirable
  2. No easy way to renew the token ( without submitting password again )
  3. Can not control the payload of the token, there's no API to put/get data to/from the token
  4. That token, by design, only works with one Flask app. So if your frontend app needs to talk with multiple restful apis, this wont work well

Check out JWT (pyjwt or flask-jwt) token, it solves all the above problems and more.

like image 11
David Lin Avatar answered Sep 29 '22 09:09

David Lin


Authentication endpoint is /login

Look at the code of flask-security here specifically views.py: _render_json()

login() calls _render_json which in turn calls get_auth_token() - and returns the auth token.

Problem (for me) is to get this to work. For me request.json seems empty (hence this does not work)

{"email": "[email protected]", "password": "test123"}

Hopefully this helps you move forward a little.

like image 2
Mandar Vaze Avatar answered Sep 29 '22 08:09

Mandar Vaze