flask-principal
flask-principal copied to clipboard
Add documentation for using with flask-jwt
Hi Matt,
since you are already the original author of flask-jwt and since flask-principal has the option to go without session, could you perhaps add a little example that goes beside the more classical flask-login example which shows how to properly use this with flask-jwt?
If you lack the time to do so properly, could you roughly describe me the process in this report for now?
I'm also interested in this.
@mattupstate can you just provide a general overview how one would approach using flask-princpal with flask-jwt? Thanks!
If this would still be valued, I'm going to tackle it over the next few weeks or so. I could write it up and do a PR if all goes well.
Here is how I do it:
JWT(app, authenticate, identity_loader)
def identity_loader(payload):
user_id = payload['identity']
try:
current_user = User.query.filter_by(id=user_id).first()
identity_changed.send(current_app._get_current_object(),
identity=Identity(user_id))
except Exception as e:
db_session.rollback()
db_session.flush()
raise e
return current_user
I'm using permissions and needs and adding the needs in the same place:
def identity_loader(payload):
"""Return user object referred to in payload."""
username = payload["identity"]["username"] or None
current_user = User(username=username)
identity = Identity(username)
if hasattr(current_user, "roles"):
for role in current_user.roles:
identity.provides.add(RoleNeed(role))
identity_changed.send(current_app._get_current_object(),
identity=identity)
return current_user
curator_permission = Permission(RoleNeed("Curator"))
curator_permission.description = "User must be a Curator"
@app.route("/projectEdit/<projectID>/<tableName>", methods=["POST"])
@jwt_required()
@curator_permission.require(http_exception=403)
def projectEdit(projectID, tableName):
""" Update specified table for specified project."""
Just make sure that @jwt_required()
comes ahead of the permission.
Is there any documentation on how to do this now ? Wanted to do the same thing and was hoping to read up on it :)
Would the following be a good identity loader as well?
@principal.identity_loader
def _identity_loader():
if hasattr(current_user, 'id'):
return Identity(current_user.id)
@user_loaded_from_request.connect_via(app)
def on_user_loaded_from_request(sender, user):
identity_changed.send(
flask.current_app._get_current_object(),
identity=Identity(user.id)
)
@identity_loaded.connect
def on_identity_loaded(sender, identity):
# Set the identity user object
identity.user = current_user
if not hasattr(current_user, 'id'):
return
# Add the UserNeed to the identity
identity.provides.add(UserNeed(current_user.id))
for role in current_user.roles:
identity.provides.add(RoleNeed(role.name))
Not quite sure why it's necessary to add an identity loader as Identity
is already being instantiated in the user_loaded_from_request
function when sending the identity_changed
signal and I check for the presence of id
in the identity_loaded
function already but otherwise it doesn't work.