Flask-restful API Authorization. Access current_identity inside decorator
Here is the combination of quickstarts of both Flask-JWT
and Flask-Restful
.
from flask import Flaskfrom flask_restful import Resource, Api, abortfrom functools import wrapsapp = Flask(__name__)api = Api(app)from flask_jwt import JWT, jwt_required, current_identityfrom werkzeug.security import safe_str_cmpclass User(object): def __init__(self, id, username, password): self.id = id self.username = username self.password = password def __str__(self): return "User(id='%s')" % self.idusers = [ User(1, 'user1', 'abcxyz'), User(2, 'user2', 'abcxyz'),]username_table = {u.username: u for u in users}userid_table = {u.id: u for u in users}def authenticate(username, password): user = username_table.get(username, None) if user and safe_str_cmp(user.password.encode('utf-8'), password.encode('utf-8')): return userdef identity(payload): user_id = payload['identity'] return userid_table.get(user_id, None)app.config['SECRET_KEY'] = 'super-secret'jwt = JWT(app, authenticate, identity)def checkuser(func): @wraps(func) def wrapper(*args, **kwargs): if current_identity.username == 'user1': return func(*args, **kwargs) return abort(401) return wrapperclass HelloWorld(Resource): decorators = [checkuser, jwt_required()] def get(self): return {'hello': current_identity.username}api.add_resource(HelloWorld, '/')if __name__ == '__main__': app.run(debug=True)
POST
{ "username": "user1", "password": "abcxyz"}
To localhost:5000/auth
and get the access_token
in response.
Then GET localhost:5000/
with header
Authorization: JWT `the access_token value above`
You would get
{ "hello": "user1"}
if you try to access localhost:5000/
with the JWT token of user2, you would get 401
.
The decorators are wrapped in this way:
for decorator in self.decorators: resource_func = decorator(resource_func)
https://github.com/flask-restful/flask-restful/blob/master/flask_restful/init.py#L445
So the later one in the decorators array gets to run earlier.
For more reference:
https://github.com/rchampa/timetable/blob/master/restful/users.py
My current solution looks like:
@app.before_requestdef detect_something(): header = request.headers.get('Authorization') if header: _, token = header.split() request.identity = identity(jwt.decode(token, app.config['SECRET_KEY']))
After it we can access identity in decorator via request.identity
. And I removed current_identity
everywhere from code. It's still messy way.
Use this:
from flask_jwt import current_identity@jwt_required()def get(self): return {'current_identity': current_identity.json()}