Skip to content

Commit d294f64

Browse files
committed
Update examples and README.md
1 parent 4d44ff8 commit d294f64

File tree

10 files changed

+142
-263
lines changed

10 files changed

+142
-263
lines changed

README.md

Lines changed: 80 additions & 54 deletions
Large diffs are not rendered by default.

examples/additional_data_in_access_token.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@
77
jwt = JWTManager(app)
88

99

10+
# Using the user_claims_loader, we can specify a method that will be called
11+
# when creating access tokens, and add these claims to the said token. This
12+
# method is passed the identity of who the token is being created for, and
13+
# must return data that is json serializable
1014
@jwt.user_claims_loader
1115
def add_claims_to_access_token(identity):
12-
# These must be json serializable
1316
return {
1417
'hello': identity,
1518
'foo': ['bar', 'baz']
@@ -27,6 +30,8 @@ def login():
2730
return jsonify(ret), 200
2831

2932

33+
# In a protected view, get the claims you added to the jwt with the
34+
# get_jwt_claims() method
3035
@app.route('/protected', methods=['GET'])
3136
@jwt_required
3237
def protected():

examples/app.py

Lines changed: 0 additions & 185 deletions
This file was deleted.

examples/blacklist.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from flask_jwt_extended import JWTManager, jwt_required, \
88
get_jwt_identity, revoke_token, unrevoke_token, \
99
get_stored_tokens, get_all_stored_tokens, create_access_token, \
10-
create_refresh_token, jwt_refresh_token_required
10+
create_refresh_token, jwt_refresh_token_required, get_stored_token
1111

1212
# Setup flask
1313
app = Flask(__name__)
@@ -18,7 +18,7 @@
1818

1919
# Enable and configure the JWT blacklist / token revoke. We are using an in
2020
# memory store for this example. In production, you should use something
21-
# else (csuch as redis, memcached, sqlalchemy). See here for options:
21+
# persistant (such as redis, memcached, sqlalchemy). See here for options:
2222
# http://pythonhosted.org/simplekv/
2323
app.config['JWT_BLACKLIST_ENABLED'] = True
2424
app.config['JWT_BLACKLIST_STORE'] = simplekv.memory.DictStore()
@@ -60,33 +60,40 @@ def list_identity_tokens():
6060

6161

6262
# Endpoint for listing all tokens. In your app, you should either not expose
63-
# this, or put some addition security on top of it so only trusted users,
63+
# this endpoint, or put some addition security on top of it so only trusted users,
6464
# (administrators, etc) can access it
6565
@app.route('/auth/all-tokens')
6666
def list_all_tokens():
6767
return jsonify(get_all_stored_tokens()), 200
6868

6969

70-
# Endpoint for revoking a token
70+
# Endpoint for allowing users to revoke their tokens
7171
@app.route('/auth/tokens/revoke/<string:jti>', methods=['PUT'])
7272
@jwt_required
7373
def change_jwt_revoke_state(jti):
74+
username = get_jwt_identity()
7475
try:
76+
token_data = get_stored_token(jti)
77+
if token_data['token']['identity'] != username:
78+
raise KeyError
7579
revoke_token(jti)
7680
return jsonify({"msg": "Token successfully revoked"}), 200
7781
except KeyError:
78-
return jsonify({'msg': 'Token not foun'}), 404
82+
return jsonify({'msg': 'Token not found'}), 404
7983

8084

81-
# Endpoint for un-revoking a token
8285
@app.route('/auth/tokens/unrevoke/<string:jti>', methods=['PUT'])
8386
@jwt_required
84-
def change_jwt_revoke_state(jti):
87+
def change_jwt_unrevoke_state(jti):
88+
username = get_jwt_identity()
8589
try:
90+
token_data = get_stored_token(jti)
91+
if token_data['token']['identity'] != username:
92+
raise KeyError
8693
unrevoke_token(jti)
8794
return jsonify({"msg": "Token successfully unrevoked"}), 200
8895
except KeyError:
89-
return jsonify({'msg': 'Token not foun'}), 404
96+
return jsonify({'msg': 'Token not found'}), 404
9097

9198

9299
@app.route('/protected', methods=['GET'])

examples/loaders.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
jwt = JWTManager(app)
77

88

9-
@jwt.expired_token_callback
9+
# Use the expired_token_loader to call this function whenever an expired but
10+
# otherwise valid access token tries to access an endpoint
11+
@jwt.expired_token_loader
1012
def my_expired_token_callback():
1113
return jsonify({
1214
'status': 401,

examples/refresh_tokens.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,20 @@ def login():
1414
if username != 'test' and password != 'test':
1515
return jsonify({"msg": "Bad username or password"}), 401
1616

17+
# Use create_access_token() and create_refresh_token() to create our
18+
# access and refresh tokens
1719
ret = {
1820
'access_token': create_access_token(identity=username),
1921
'refresh_token': create_refresh_token(identity=username)
2022
}
2123
return jsonify(ret), 200
2224

2325

26+
# The jwt_refresh_token_required decorator insures a valid refresh token is
27+
# present in the request before calling this endpoint. We can use the
28+
# get_jwt_identity() function to get the identity of the refresh toke, and use
29+
# the create_access_token() function again to make a new access token for this
30+
# identity.
2431
@app.route('/refresh', methods=['POST'])
2532
@jwt_refresh_token_required
2633
def refresh():

examples/simple.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,13 @@
33

44
app = Flask(__name__)
55
app.secret_key = 'super-secret' # Change this!
6+
7+
# Setup the Flask-JWT-Extended extension
68
jwt = JWTManager(app)
79

810

11+
# Provide a method to create access tokens. The create_access_token() function
12+
# is used to actually generate the token
913
@app.route('/login', methods=['POST'])
1014
def login():
1115
username = request.json.get('username', None)
@@ -17,6 +21,8 @@ def login():
1721
return jsonify(ret), 200
1822

1923

24+
# Protect a view with jwt_required, which requires a valid access token in the
25+
# request to access.
2026
@app.route('/protected', methods=['GET'])
2127
@jwt_required
2228
def protected():

examples/token_freshness.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,30 @@
88
jwt = JWTManager(app)
99

1010

11+
# Standard login endpoint. Will return a fresh access token and a refresh token
1112
@app.route('/login', methods=['POST'])
1213
def login():
1314
username = request.json.get('username', None)
1415
password = request.json.get('password', None)
1516
if username != 'test' and password != 'test':
1617
return jsonify({"msg": "Bad username or password"}), 401
1718

19+
# create_access_token supports an optional 'fresh' argument, which marks the
20+
# token as fresh or non-fresh accordingly. As we just verified their username
21+
# and password, we are going to mark the token as fresh here.
1822
ret = {
1923
'access_token': create_access_token(identity=username, fresh=True),
2024
'refresh_token': create_refresh_token(identity=username)
2125
}
2226
return jsonify(ret), 200
2327

2428

25-
@app.route('/login', methods=['POST'])
26-
def login():
29+
# Fresh login endpoint. This is designed to be used if we need to make a fresh
30+
# token for a user (by verifying they have the correct username and password).
31+
# Unlike the standard login endpoint, this will only return a new access token
32+
# (so that we don't keep generating new refresh tokens, which defeats their point)
33+
@app.route('/fresh-login', methods=['POST'])
34+
def fresh_login():
2735
username = request.json.get('username', None)
2836
password = request.json.get('password', None)
2937
if username != 'test' and password != 'test':
@@ -33,6 +41,9 @@ def login():
3341
return jsonify(ret), 200
3442

3543

44+
# Refresh token endpoint. This will generate a new access token from the refresh
45+
# token, but will mark that access token as non-fresh (so that it cannot access
46+
# any endpoint protected via the fresh_jwt_required decorator)
3647
@app.route('/refresh', methods=['POST'])
3748
@jwt_refresh_token_required
3849
def refresh():
@@ -43,13 +54,15 @@ def refresh():
4354
return jsonify(ret), 200
4455

4556

57+
# Any valid jwt can access this endpoint
4658
@app.route('/protected', methods=['GET'])
4759
@jwt_required
4860
def protected():
4961
username = get_jwt_identity()
5062
return jsonify({'hello': 'from {}'.format(username)}), 200
5163

5264

65+
# Only fresh jwts can access this endpoint
5366
@app.route('/protected-fresh', methods=['GET'])
5467
@fresh_jwt_required
5568
def protected_fresh():

flask_jwt_extended/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
create_refresh_token, create_access_token, get_jwt_identity,
44
get_jwt_claims)
55
from .blacklist import (revoke_token, unrevoke_token, get_stored_tokens,
6-
get_all_stored_tokens)
6+
get_all_stored_tokens, get_stored_token)

0 commit comments

Comments
 (0)