pallets-eco/flask-jwt

Example return specificy Json with token!

johndiego opened this issue · 4 comments

In Documentation are
def _default_auth_response_handler(access_token, identity): return jsonify({'access_token': access_token.decode('utf-8')})
how i can return User wiith acess token?
thanks for advanced!

Perhaps check out Flask-JWT-Extended (https://github.com/vimalloc/flask-jwt-extended), it make doing stuff like this a breeze (full disclosure, I'm the author of the extension).

Here are examples of how this would be accomplished in that extension:
http://flask-jwt-extended.readthedocs.io/en/latest/add_custom_data_claims.html
http://flask-jwt-extended.readthedocs.io/en/latest/tokens_from_complex_object.html

I installed this is my code!
my server.py


from flask import Flask,render_template, request, redirect,jsonify
from flask_security import Security, logout_user, login_required,auth_token_required
from flask_security.utils import encrypt_password, verify_password
from flask_restless import APIManager
from flask_jwt import JWT, jwt_required,current_identity
from flask_jwt_extended import JWTManager, jwt_required, create_access_token, get_jwt_identity
from database import db
from application import app
from models import User, Role,user_datastore,security

@app.route('/')
@auth_token_required
def home():
    return jsonify('working')

def authenticate(username, password):
    user = user_datastore.find_user(email=username)
    if user and username == user.email and verify_password(password, user.password):
        return user
    return None

def load_user(payload):
    user = user_datastore.find_user(id=payload['identity'])
    return user

jwt = JWT(app, authenticate, load_user)

@jwt.user_claims_loader
def add_claims_to_access_token(user):
    return {'roles': user.roles}


@jwt_required()
def auth_func(**kw):
    pass

manager = APIManager(app, flask_sqlalchemy_db=db)
#manager.create_api(User,methods=['GET', 'POST', 'DELETE', 'PUT'],preprocessors=dict(GET_SINGLE=[auth_func], GET_MANY=[auth_func]))
#manager.create_api(Role,methods=['GET', 'POST', 'DELETE', 'PUT'],preprocessors=dict(GET_SINGLE=[auth_func], GET_MANY=[auth_func]))
manager.create_api(Role,methods=['GET', 'POST', 'DELETE', 'PUT'])
manager.create_api(User,methods=['GET', 'POST', 'DELETE', 'PUT'])

@app.before_first_request
def create_user():
    if not User.query.first():
        view_user = user_datastore.find_or_create_role(name='View-user', description='View-user')
        edit_user = user_datastore.find_or_create_role(name='Edit-user', description='Edit-user')
        add_user = user_datastore.find_or_create_role(name='Add-user', description='Add-user')
        update_user = user_datastore.find_or_create_role(name='update-user', description='update-user')
        delete_user = user_datastore.find_or_create_role(name='delete-user', description='delete-user')
        a = 0       
        while a < 5:    
            a = a + 1  
            user = user_datastore.create_user(email='test'+str(a)+'@example.com', password=encrypt_password('test'+str(a)),user_login='USER '+str(a))
            user_datastore.add_role_to_user(user,view_user)
        db.session.commit()

if __name__ == '__main__':
    db.init_app(app)
    with app.app_context():
        db.create_all()
    app.run()


I run the command
python server.py

Traceback (most recent call last):
  File "server.py", line 28, in <module>
    @jwt.user_claims_loader
AttributeError: 'JWT' object has no attribute 'user_claims_loader'

How i can used?

The @jwt.user_claims_loader is part of a totally different extension, flask-jwt-extended (instead of this extension, which is flask-jwt). You would need to migrate your code to that extension for it to work. These links explain the basics flask-jwt-extended:

http://flask-jwt-extended.readthedocs.io/en/latest/installation.html
http://flask-jwt-extended.readthedocs.io/en/latest/basic_usage.html

In flask-jwt-extended, your posted code might look something like this:

from flask import Flask,render_template, request, redirect,jsonify
from flask_security import Security, logout_user, login_required,auth_token_required
from flask_security.utils import encrypt_password, verify_password
from flask_restless import APIManager
from flask_jwt_extended import JWTManager, jwt_required, create_access_token, get_jwt_identity
from database import db
from application import app
from models import User, Role,user_datastore,security

jwt = JWTManager(app)


@app.route('/')
@auth_token_required  # Not sure about this, guessing it's part of flask-security?
#@jwt_required  # In plain Flask-JWT-Extended land, this is the decorator you would use
def home():
    return jsonify('working')


@jwt.user_claims_loader
def add_claims_to_access_token(user):
    return {'roles': user.roles}


@jwt.user_identity_loader
def get_identity_for_access_token(user):
    return user.name


@app.route('/auth', methods=['POST'])
def authenticate():
    username = request.json.get('username', None)
    password = request.json.get('password', None)
    user = user_datastore.find_user(email=username)
    if user and username == user.email and verify_password(password, user.password):
	ret = {'access_token': create_access_token(user)}
	return jsonify(ret), 200
    else:
        return jsonify({"msg": "Bad username or password"}), 401

@jwt_required
def auth_func(**kw):
    pass

manager = APIManager(app, flask_sqlalchemy_db=db)
#manager.create_api(User,methods=['GET', 'POST', 'DELETE', 'PUT'],preprocessors=dict(GET_SINGLE=[auth_func], GET_MANY=[auth_func]))
#manager.create_api(Role,methods=['GET', 'POST', 'DELETE', 'PUT'],preprocessors=dict(GET_SINGLE=[auth_func], GET_MANY=[auth_func]))
manager.create_api(Role,methods=['GET', 'POST', 'DELETE', 'PUT'])
manager.create_api(User,methods=['GET', 'POST', 'DELETE', 'PUT'])

@app.before_first_request
def create_user():
    if not User.query.first():
        view_user = user_datastore.find_or_create_role(name='View-user', description='View-user')
        edit_user = user_datastore.find_or_create_role(name='Edit-user', description='Edit-user')
        add_user = user_datastore.find_or_create_role(name='Add-user', description='Add-user')
        update_user = user_datastore.find_or_create_role(name='update-user', description='update-user')
        delete_user = user_datastore.find_or_create_role(name='delete-user', description='delete-user')
        a = 0
        while a < 5:
            a = a + 1
            user = user_datastore.create_user(email='test'+str(a)+'@example.com', password=encrypt_password('test'+str(a)),user_login='USER '+str(a))
            user_datastore.add_role_to_user(user,view_user)
        db.session.commit()

if __name__ == '__main__':
    db.init_app(app)
    with app.app_context():
        db.create_all()
    app.run()

I haven't personally used flask_security or flask_restless before, so I couldn't comment on their usage in this code. But for the flask-jwt-extended, I think everything looks in order there (note, it is untested, so don't hold me to that).

My code


from flask import Flask,render_template, request, redirect,jsonify
from flask_security import Security, logout_user, login_required,auth_token_required
from flask_security.utils import encrypt_password, verify_password
from flask_restless import APIManager
from flask_jwt_extended import JWTManager,jwt_required, create_access_token, get_jwt_identity
from database import db
from application import app
from models.models import User, Role,user_datastore,security

jwt = JWTManager(app)

@jwt.user_claims_loader
def add_claims_to_access_token(user):
    print(user.email)
    return {'roles': user.roles}

@jwt.user_identity_loader
def get_identity_for_access_token(user):
    return user.email





@app.route('/auth', methods=['POST'])
def login():
    username = request.json.get('username', None)
    password = request.json.get('password', None)
    user = user_datastore.find_user(email=username)
    
    if user and username == user.email and password == user.password:
        access_token = create_access_token(identity=user)
        ret = {'access_token': access_token}
        return jsonify(ret), 200
    return jsonify({"msg": "Bad username or password"}), 401




@jwt_required
def auth_func(**kw):
    pass

manager = APIManager(app, flask_sqlalchemy_db=db)
manager.create_api(User,methods=['GET', 'POST', 'DELETE', 'PUT'],preprocessors=dict(GET_SINGLE=[auth_func], GET_MANY=[auth_func]))
#manager.create_api(Role,methods=['GET', 'POST', 'DELETE', 'PUT'],preprocessors=dict(GET_SINGLE=[auth_func], GET_MANY=[auth_func]))
manager.create_api(Role,methods=['GET', 'POST', 'DELETE', 'PUT'])
#manager.create_api(User,methods=['GET', 'POST', 'DELETE', 'PUT'])

@app.before_first_request
def create_user():
    if not User.query.first():
        edit = user_datastore.find_or_create_role(name='Edit', description='edit')
        update = user_datastore.find_or_create_role(name='Update', description='update')
        delete = user_datastore.find_or_create_role(name='Delete', description='delete')
        view = user_datastore.find_or_create_role(name='view', description='view')
        a = 0
        while a < 5:
            a = a + 1
            user = user_datastore.create_user(email='test'+str(a)+'@example.com', password='test'+str(a),user_login='USER '+str(a))
            user_datastore.add_role_to_user(user,edit)
            user_datastore.add_role_to_user(user,update)
            user_datastore.add_role_to_user(user,delete)
            user_datastore.add_role_to_user(user,view)
        db.session.commit()

if __name__ == '__main__':
    db.init_app(app)
    with app.app_context():
        db.create_all()
    app.run()

My Error


Traceback (most recent call last):
  File "/home/john/Desktop/Projetos/NextInfo-ERP/server/Nextinnfo/lib/python3.5/site-packages/flask/app.py", line 1994, in __call__
    return self.wsgi_app(environ, start_response)
  File "/home/john/Desktop/Projetos/NextInfo-ERP/server/Nextinnfo/lib/python3.5/site-packages/flask/app.py", line 1985, in wsgi_app
    response = self.handle_exception(e)
  File "/home/john/Desktop/Projetos/NextInfo-ERP/server/Nextinnfo/lib/python3.5/site-packages/flask_cors/extension.py", line 161, in wrapped_function
    return cors_after_request(app.make_response(f(*args, **kwargs)))
  File "/home/john/Desktop/Projetos/NextInfo-ERP/server/Nextinnfo/lib/python3.5/site-packages/flask/app.py", line 1540, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/home/john/Desktop/Projetos/NextInfo-ERP/server/Nextinnfo/lib/python3.5/site-packages/flask/_compat.py", line 33, in reraise
    raise value
  File "/home/john/Desktop/Projetos/NextInfo-ERP/server/Nextinnfo/lib/python3.5/site-packages/flask/app.py", line 1982, in wsgi_app
    response = self.full_dispatch_request()
  File "/home/john/Desktop/Projetos/NextInfo-ERP/server/Nextinnfo/lib/python3.5/site-packages/flask/app.py", line 1614, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/home/john/Desktop/Projetos/NextInfo-ERP/server/Nextinnfo/lib/python3.5/site-packages/flask_cors/extension.py", line 161, in wrapped_function
    return cors_after_request(app.make_response(f(*args, **kwargs)))
  File "/home/john/Desktop/Projetos/NextInfo-ERP/server/Nextinnfo/lib/python3.5/site-packages/flask/app.py", line 1517, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/home/john/Desktop/Projetos/NextInfo-ERP/server/Nextinnfo/lib/python3.5/site-packages/flask/_compat.py", line 33, in reraise
    raise value
  File "/home/john/Desktop/Projetos/NextInfo-ERP/server/Nextinnfo/lib/python3.5/site-packages/flask/app.py", line 1612, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/john/Desktop/Projetos/NextInfo-ERP/server/Nextinnfo/lib/python3.5/site-packages/flask/app.py", line 1598, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/home/john/Desktop/Projetos/NextInfo-ERP/server/server.py", line 32, in login
    access_token = create_access_token(identity=user)
  File "/home/john/Desktop/Projetos/NextInfo-ERP/server/Nextinnfo/lib/python3.5/site-packages/flask_jwt_extended/utils.py", line 340, in create_access_token
    fresh=fresh, user_claims=user_claims)
  File "/home/john/Desktop/Projetos/NextInfo-ERP/server/Nextinnfo/lib/python3.5/site-packages/flask_jwt_extended/utils.py", line 67, in _encode_access_token
    raise JWTEncodeError('Error json serializing user_claims: {}'.format(str(e)))
flask_jwt_extended.exceptions.JWTEncodeError: Error json serializing user_claims: <sqlalchemy.orm.dynamic.AppenderBaseQuery object at 0x7f3cf538ff60> is not JSON serializable