Flask declarative authorization
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.



Flask declarative authorization leveraging bouncer

Build Status

flask-bouncer is an authorization library for Flask which restricts what resources a given user is allowed to access. All the permissions are defined in a single location.

Enough chit-chat – show me the code …


pip install flask-bouncer


from flask_bouncer import requires, ensure, Bouncer
app = Flask()
bouncer = Bouncer(app)

# Define your authorization in one place and in english ...
def define_authorization(user, they):
    if user.is_admin:
        they.can(MANAGE, ALL)
        they.can(READ, ('Article', 'BlogPost'))
        they.can(EDIT, 'Article', lambda a: a.author_id == user.id)

# Then decorate your routes with your conditions.
# If it fails it will return a 401
@requires(READ, Article)
def articles_index():
    return "A bunch of articles"

@requires(READ, TopSecretFile)
def topsecret_index():
    return "A bunch of top secret stuff that only admins should see"
  • When you are dealing with a specific resource, then use the ensure method
from flask_bouncer import requires, ensure
@requires(READ, Article)
def show_article(article_id):
    article = Article.find_by_id(article_id)

    # can the current user 'read' the article, if not it will throw a 401
    return render_template('article.html', article=article)
  • Check out bouncer with more details about defining Abilities
  • flask-bouncer by default looks for current_user or user stored in flask’s g

Lock It Down

You can use the ensure_authorization feature to ensure that all of your routes in your application have been authorized

bouncer = Bouncer(app, ensure_authorization=True)

This will check each request to ensure that an authorization check (either ensure or requires) has been made

If you want to skip a certain route, decorate your route with @skip_authorization. Like so:

def articles_index():
    return "A bunch of articles"

Flask-Classy Support

I ❤ Flask-Classy Like a lot. Flask-Classy is an extension that adds class-based REST views to Flask.

1) Define you View similarly as you would with flask-classy

from flask_classy import FlaskView
from yourapp.models import Article

class ArticleView(FlaskView)

    # an additional class attribute that you need to add for flask-bouncer
    __target_model__ = Article

    def index(self)
        return "Index"

    def get(self, obj_id):
        return "Get "

    # ... methods for post, delete (and even put, and patch if you so like

2) Register the View with flask and bouncer

# in your application.py or the like

app = Flask("classy")
bouncer = Bouncer(app)

# Which classy views do you want to lock down, you can pass multiple

Then voila – flask-bouncer will implicitly add the following conditions to the routes:

  • You need ‘READ’ privileges for ‘index’,‘show’ and ‘get’
  • You need ‘CREATE’ privileges for ‘new’,‘put’ and ‘post’
  • You need ‘UPDATE’ privileges for ‘edit’ and ‘patch’

If you want to over-write the default requirements, just add the @requires decorator to the function



By default flask-bouncer will inspect g for user or current_user. You can add your custom loader by decorating a function with @bouncer.user_loader

Other Features


  • This library focusing only on Authorization, we leave Authentication to other libraries such as flask-login.

Thank You!

  • Ryan Bates, and his excellent CanCan ruby library which this the inspiration for this library

Questions / Issues

Feel free to ping me on twitter: @tushman or add issues or PRs at https://github.com/jtushman/flask-bouncer