Token based authentication with flask-security extension

user2483431 picture user2483431 · Dec 8, 2014 · Viewed 9.1k times · Source

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 :-)

Answer

Sebastian picture Sebastian · Mar 27, 2015

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');
            }