Flask-restful API Authorization. Access current_identity inside decorator Flask-restful API Authorization. Access current_identity inside decorator python python

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

https://github.com/mattupstate/flask-jwt/issues/37


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()}