Closed johndiego closed 12 months ago
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
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!