Navigation

This extension supports optional token revoking out of the box. This will
allow you to revoke a specific token so that it can no longer access your endpoints.

You will have to choose what tokens you want to check against the blacklist. In
most cases, you will probably want to check both refresh and access tokens, which
is the default behavior. However, if the extra overhead of checking tokens is a
concern you could instead only check the refresh tokens, and set the access
tokens to have a short expires time so any damage a compromised token could
cause is minimal.

Blacklisting works by is providing a callback function to this extension, using the
token_in_blacklist_loader() decorator.
This method will be called whenever the specified tokens (access and/or refresh)
are used to access a protected endpoint. If the callback function says that the
token is revoked, we will not allow the call to continue, otherwise we will
allow the call to access the endpoint as normal.

Here is a basic example of this in action.

fromflaskimportFlask,request,jsonifyfromflask_jwt_extendedimport(JWTManager,jwt_required,get_jwt_identity,create_access_token,create_refresh_token,jwt_refresh_token_required,get_raw_jwt)# Setup flaskapp=Flask(__name__)# Enable blacklisting and specify what kind of tokens to check# against the blacklistapp.config['JWT_SECRET_KEY']='super-secret'# Change this!app.config['JWT_BLACKLIST_ENABLED']=Trueapp.config['JWT_BLACKLIST_TOKEN_CHECKS']=['access','refresh']jwt=JWTManager(app)# A storage engine to save revoked tokens. In production if# speed is the primary concern, redis is a good bet. If data# persistence is more important for you, postgres is another# great option. In this example, we will be using an in memory# store, just to show you how this might work. For more# complete examples, check out these:# https://github.com/vimalloc/flask-jwt-extended/blob/master/examples/redis_blacklist.py# https://github.com/vimalloc/flask-jwt-extended/tree/master/examples/database_blacklistblacklist=set()# For this example, we are just checking if the tokens jti# (unique identifier) is in the blacklist set. This could# be made more complex, for example storing all tokens# into the blacklist with a revoked status when created,# and returning the revoked status in this call. This# would allow you to have a list of all created tokens,# and to consider tokens that aren't in the blacklist# (aka tokens you didn't create) as revoked. These are# just two options, and this can be tailored to whatever# your application needs.@jwt.token_in_blacklist_loaderdefcheck_if_token_in_blacklist(decrypted_token):jti=decrypted_token['jti']returnjtiinblacklist# Standard login endpoint@app.route('/login',methods=['POST'])deflogin():username=request.json.get('username',None)password=request.json.get('password',None)ifusername!='test'orpassword!='test':returnjsonify({"msg":"Bad username or password"}),401ret={'access_token':create_access_token(identity=username),'refresh_token':create_refresh_token(identity=username)}returnjsonify(ret),200# Standard refresh endpoint. A blacklisted refresh token# will not be able to access this endpoint@app.route('/refresh',methods=['POST'])@jwt_refresh_token_requireddefrefresh():current_user=get_jwt_identity()ret={'access_token':create_access_token(identity=current_user)}returnjsonify(ret),200# Endpoint for revoking the current users access token@app.route('/logout',methods=['DELETE'])@jwt_requireddeflogout():jti=get_raw_jwt()['jti']blacklist.add(jti)returnjsonify({"msg":"Successfully logged out"}),200# Endpoint for revoking the current users refresh token@app.route('/logout2',methods=['DELETE'])@jwt_refresh_token_requireddeflogout2():jti=get_raw_jwt()['jti']blacklist.add(jti)returnjsonify({"msg":"Successfully logged out"}),200# This will now prevent users with blacklisted tokens from# accessing this endpoint@app.route('/protected',methods=['GET'])@jwt_requireddefprotected():returnjsonify({'hello':'world'})if__name__=='__main__':app.run()

In production, you will likely want to use either a database or in memory store
(such as redis) to store your tokens. In memory stores are great if you are wanting
to revoke a token when the users logs out, as they are blazing fast. A downside
to using redis is that in the case of a power outage or other such event, it’s
possible that you might ‘forget’ that some tokens have been revoked, depending
on if the redis data was synced to disk.

In contrast to that, databases are great if the data persistance is of the highest
importance (for example, if you have very long lived tokens that other developers
use to access your api), or if you want to add some addition features like showing
users all of their active tokens, and letting them revoke and unrevoke those tokens.