python-3.xflaskflask-jwt

Combining Flask Blueprints with Flask-JWT


I am developing a Flask 0.12 app with Blueprints and I am trying to use Flask-JWT (0.3.2) for authentication.

None of the tutorials that I can see for Flask-JWT use Blueprints.

There is a usually a block of code in each example, that does something like this:

app = Flask(__name__)
jwt = JWT(app, authenticate, identity)

In a blueprinted flask app the structure tends to be more like this:

__init__.py:

from swarm.controllers.main import main
from swarm.controllers.grid import grid
from swarm.controllers.address import address

def create_app(object_name):
    app = Flask(__name__)
    ...
    app.register_blueprint(main)
    app.register_blueprint(grid)
    app.register_blueprint(address)

controllers/main.py:

main = Blueprint('main', __name__)

controllers/grid.py:

grid = Blueprint('grid', __name__)

controllers/address.py:

address = Blueprint('address', __name__)

How would I reference Flask-JWT and use its decorators in the controllers?

It might prove easier to answer this question by showing how to add JWT decorators to a standard example such as blueprintexample in the flask source code o Michał Karzyński's REST API demo.


Solution

  • I've built a simple example that enables use of Flask-JWT decorators.

    The file structure:

    server
    ├── app
    |   ├── admin # blueprint
    |   |   ├── __init__.py
    |   |   ├── views.py
    |   ├── __init__.py
    ├── config.py
    └── run.py
    

    First, create a blueprint called admin and import its views

    # file: server/app/admin/init.py
    from flask import Blueprint
    
    admin = Blueprint('admin', __name__)
    
    from . import views
    

    The admin blueprint has one view. Here, we import the admin blueprint and some flask_jwt stuff so we can properly access their decorators:

    from flask_jwt import jwt_required, current_identity
    from . import admin
    
    # file: server/app/admin/views.py
    @admin.route('/protected')
    @jwt_required()
    def protected():
        return '%s' % current_identity
    

    Now create the flask app, create the JWT instance, and register the admin blueprint to the flask application:

    # file: server/app/__init__.py
    from flask import Flask
    from flask_jwt import JWT
    from werkzeug.security import safe_str_cmp
    
    from .admin import admin
    
    # skipping over jwt authenticate() and identity() creation
    # https://pythonhosted.org/Flask-JWT/
    # ...
    
    app = Flask(__name__)
    
    app.config.from_object('config')
    
    jwt = JWT(app, authenticate, identity)
    
    app.register_blueprint(admin, url_prefix='/admin')
    

    And finally, set up your script manager:

    from flask_script import Manager, Server
    
    from server.app import app
    
    manager = Manager(app)
    
    # Turn on debugger by default and reloader
    manager.add_command("runserver", Server(
        use_debugger = True,
        use_reloader = True,
        host = '0.0.0.0',
        port = 5000)
    )
    
    if __name__ == "__main__":
        manager.run()
    

    Now, if we go to our /admin/protected url, we will see that JWT is up and running:

    {
      "description": "Request does not contain an access token",
      "error": "Authorization Required",
      "status_code": 401
    }
    

    I hope this helps!