{ "info": { "author": "Alexander Potts", "author_email": "alexander@jakkso.com", "bugtrack_url": null, "classifiers": [ "Framework :: Flask", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3" ], "description": "## \ud83d\udd25Flask_Blacklist\ud83d\udd25\n\n### What\nIt's a Flask extension designed to work with `flask_sqlalchemy` and `flask_pratorian` to blacklist tokens!\n\nIt stores blacklisted JWT's jti value in an in-memory store, allowing blacklist checks without\ndatabase calls. However, when a token is blacklisted, it is also persisted to the database.\n\n### Why\n\n* Emulate a redis store without actually using redis! \ud83d\udc4d\n * This is almost certainly slower than redis (It's python, after all).\n* Why not, it's an excuse to get to know flask and associated libraries a little bit better. \ud83d\udc4d\n\n### How\nYou *are* using a [virtualenv](https://virtualenv.pypa.io/en/latest/), right?\n\n`pip install flask-blacklist` \n\n\nThen in your app factory function, initialize `Blacklist` *after* you've initialized your ORM.\n\n # In global scope\n from flask_blacklist import Blacklist, is_blacklisted\n db = SQLAlchemy()\n guard = Praetorian()\n bl = Blacklist()\n\n # In the app factory function\n app = Flask(__name__)\n db.init_app(app)\n\n from app.models import Token, User\n bl.init_app(app, Token) # Initialize after your ORM\n\n # is_blacklisted is a helper function that Praetorian uses to determine if a token has been blacklisted\n guard.init_app(app, User, is_blacklisted) \n\nThe Token database model needs to have two different class methods:\n\n* `Token.blacklist_jti` \n * Takes a single parameter, which is the `jti` string extracted from a JWT\n * This method calll persist the blacklisted `jti` string to your database.\n* `Token.get_blacklisted` \n * Should return a list of already blacklisted tokens from the database\n * The tokens returns should have a `jti` attribute containing string extracted from the token you want to blacklist\n\nThen, in the route that needs to invalidate the token:\n\n @auth_blueprint.route(\"/v1/auth/token\", methods=[\"DELETE\"])\n @auth_required\n def invalidate_token():\n token = guard.read_token_from_header()\n jti = guard.extract_jwt_token(token)[\"jti\"]\n bl.blacklist_jti(jti)\n rv, code = {\"success\": True, \"message\": \"token invalidated\"}, 200\n return jsonify(rv), code\n\n