Role based authorization in flask-login
10,592
The more common method of dealing with role based permissions is to use Flask Principal.
In the main app:
from flask_principal import Principal
# load the extension
principals = Principal(app)
@identity_loaded.connect_via(app)
def on_identity_loaded(sender, identity):
# Set the identity user object
identity.user = current_user
# Add the UserNeed to the identity
if hasattr(current_user, 'employee_id'):
identity.provides.add(UserNeed(current_user.employee_id))
# Assuming the User model has a list of roles, update the
# identity with the roles that the user provides
if hasattr(current_user, 'position'):
# for role in current_user.role:
identity.provides.add(RoleNeed(str(current_user.position)))
admin_permission = Permission(RoleNeed('admin'))
And then in the route:
@app.route("/admin-restricted"):
@login_required
@admin_permission.require(http_exception=403)
def admin_resource():
return "Hello admin"
Docs: https://pythonhosted.org/Flask-Principal/
Related videos on Youtube
Comments
-
Grzegorz Pudłowski almost 2 years
I need to introduce role-based authorization in existing Flask application. Because of that I can't just swap currently used flask-login package with flask-user for example. Nevertheless I have to restrict access to some endpoints to "admin" users without rebuilding entire code base.
I came up with a decorator like this:
def admin_required(func): """ Modified login_required decorator to restrict access to admin group. """ @wraps(func) def decorated_view(*args, **kwargs): if current_user.group != 0: # zero means admin, one and up are other groups flash("You don't have permission to access this resource.", "warning") return redirect(url_for("main.home")) return func(*args, **kwargs) return decorated_view
I use it with original
login_required
decorator like so:@app.route("/admin-restricted"): @login_required @admin_required def admin_resource(): return "Hello admin"
Everything works as expected BUT I have two concerns:
- Is my method safe? Have I missed something which is potential security flaw? Unfortunately I have limited knowledge about Flask internals.
- Is there more simple/safe/pythonic way to do that? It just doesn't feel right to me.
-
Grzegorz Pudłowski almost 4 yearsThat's cool. I've read documentation a bit and only one thing isn't obvious to me. Is there easy way to
flash
a message andredirect
somewhere instead of throwing 403? -
RyanH almost 4 yearsI'm sure there's a way to extend the functionality but I admittedly took the easier approach and rather than use the decorator, I replaced it with this in the first line of the view function:
if not admin_permission.require().can():
then flash and redirect. You can make a custom decorator that wraps the Flask-Principal logic. Here's an example of a custom decorator you can model after to accomplish the desired effect: gist.github.com/ryan-hallman/c6fa18d6847ef06d548f8de94ec29102