-
-
Notifications
You must be signed in to change notification settings - Fork 247
Added example and docs for revoking both tokens #187
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,6 +26,16 @@ Here is a basic example of this in action. | |
|
|
||
| .. literalinclude:: ../examples/blacklist.py | ||
|
|
||
| Sometimes there will be situations where we would want to backlist both the access token and the refresh token in the logout call. It could be done by | ||
| embedding the reference to the refresh token in the access token. For that | ||
| we could write the login, logout and refresh functions as: | ||
|
|
||
|
|
||
| .. literalinclude:: ../examples/backlist_both_tokens.py | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. blacklist_both_tokens.py |
||
|
|
||
|
|
||
| Using databases for Blacklisting | ||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 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 | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| from flask import Flask, request, jsonify | ||
|
|
||
tecoholic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| from flask_jwt_extended import ( | ||
| jwt_refresh_token_required, jwt_required, create_access_token, get_jti, | ||
| create_refresh_token, get_jwt_identity, get_raw_jwt, JWTManager | ||
| ) | ||
|
|
||
|
|
||
| app = Flask(__name__) | ||
|
|
||
| # Enable blacklisting and specify what kind of tokens to check | ||
| # against the blacklist | ||
| app.config['JWT_SECRET_KEY'] = 'super-secret' # Change this! | ||
| app.config['JWT_BLACKLIST_ENABLED'] = True | ||
| app.config['JWT_BLACKLIST_TOKEN_CHECKS'] = ['access', 'refresh'] | ||
| jwt = JWTManager(app) | ||
|
|
||
| blacklist = set() | ||
|
|
||
|
|
||
| @jwt.token_in_blacklist_loader | ||
| def check_if_token_in_blacklist(decrypted_token): | ||
| jti = decrypted_token['jti'] | ||
| return jti in blacklist | ||
|
|
||
|
|
||
| # Endpoint for logging in | ||
| @app.route('/login', methods=['POST']) | ||
| def login(): | ||
| username = request.json.get('username', None) | ||
| password = request.json.get('password', None) | ||
| if username != 'test' or password != 'test': | ||
| return jsonify({"msg": "Bad username or password"}), 401 | ||
|
|
||
| # use a dict for identity, so that we can link the access token with | ||
| # the refresh token as a user claim | ||
| user = {"username": username} | ||
| refresh_token = create_refresh_token(identity=user) | ||
|
|
||
| # Embed the refresh token's jti in the access_token | ||
| user["refresh_jti"] = get_jti(refresh_token) | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't really like having having this data stored in what will become the |
||
| access_token = create_access_token(identity=user) | ||
|
|
||
| ret = { | ||
| 'access_token': access_token, | ||
| 'refresh_token': refresh_token | ||
| } | ||
| return jsonify(ret), 200 | ||
|
|
||
|
|
||
| # Endpoint for generating a new access token using refresh token | ||
| @app.route('/refresh', methods=['POST']) | ||
| @jwt_refresh_token_required | ||
| def refresh(): | ||
| current_user = get_jwt_identity() | ||
| refresh_jti = get_raw_jwt()['jti'] | ||
| current_user['refresh_jti'] = refresh_jti | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same thing here regarding the user_claims_loader |
||
| ret = { | ||
| 'access_token': create_access_token(identity=current_user) | ||
| } | ||
| return jsonify(ret), 200 | ||
|
|
||
|
|
||
| # Endpoint which blacklists both the refresh token and the access token with a | ||
| # single call | ||
| @app.route('/logout', methods=['DELETE']) | ||
| @jwt_required | ||
| def logout(): | ||
| access_jti = get_raw_jwt()["jti"] | ||
| refresh_jti = get_jwt_identity()["refresh_jti"] | ||
| blacklist.add(access_jti) | ||
| blacklist.add(refresh_jti) | ||
| return jsonify({"msg": "Successfully logged out"}), 200 | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| app.run() | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... to blacklist both ...