Skip to content

Commit 974ea74

Browse files
committed
Merge branch 'master' of git://github.com/vimalloc/flask-jwt-extended into vimalloc-master
# Conflicts: # README.md # app.py
2 parents 8188188 + f97b5f5 commit 974ea74

21 files changed

+2238
-142
lines changed

README.md

Lines changed: 504 additions & 6 deletions
Large diffs are not rendered by default.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
from flask import Flask, jsonify, request
2+
from flask_jwt_extended import JWTManager, jwt_required, create_access_token, \
3+
get_jwt_claims
4+
5+
app = Flask(__name__)
6+
app.secret_key = 'super-secret' # Change this!
7+
jwt = JWTManager(app)
8+
9+
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
14+
@jwt.user_claims_loader
15+
def add_claims_to_access_token(identity):
16+
return {
17+
'hello': identity,
18+
'foo': ['bar', 'baz']
19+
}
20+
21+
22+
@app.route('/login', methods=['POST'])
23+
def login():
24+
username = request.json.get('username', None)
25+
password = request.json.get('password', None)
26+
if username != 'test' and password != 'test':
27+
return jsonify({"msg": "Bad username or password"}), 401
28+
29+
ret = {'access_token': create_access_token(username)}
30+
return jsonify(ret), 200
31+
32+
33+
# In a protected view, get the claims you added to the jwt with the
34+
# get_jwt_claims() method
35+
@app.route('/protected', methods=['GET'])
36+
@jwt_required
37+
def protected():
38+
claims = get_jwt_claims()
39+
return jsonify({
40+
'hello_is': claims['hello'],
41+
'foo_is': claims['foo']
42+
}), 200
43+
44+
if __name__ == '__main__':
45+
app.run()

examples/blacklist.py

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
from datetime import timedelta
2+
3+
import simplekv
4+
import simplekv.memory
5+
from flask import Flask, request, jsonify
6+
7+
from flask_jwt_extended import JWTManager, jwt_required, \
8+
get_jwt_identity, revoke_token, unrevoke_token, \
9+
get_stored_tokens, get_all_stored_tokens, create_access_token, \
10+
create_refresh_token, jwt_refresh_token_required, get_stored_token
11+
12+
# Setup flask
13+
app = Flask(__name__)
14+
app.secret_key = 'super-secret'
15+
16+
# Configure access token expires time
17+
app.config['JWT_ACCESS_TOKEN_EXPIRES'] = timedelta(minutes=5)
18+
19+
# Enable and configure the JWT blacklist / token revoke. We are using an in
20+
# memory store for this example. In production, you should use something
21+
# persistant (such as redis, memcached, sqlalchemy). See here for options:
22+
# http://pythonhosted.org/simplekv/
23+
app.config['JWT_BLACKLIST_ENABLED'] = True
24+
app.config['JWT_BLACKLIST_STORE'] = simplekv.memory.DictStore()
25+
app.config['JWT_BLACKLIST_TOKEN_CHECKS'] = 'refresh'
26+
27+
jwt = JWTManager(app)
28+
29+
30+
@app.route('/login', methods=['POST'])
31+
def login():
32+
username = request.json.get('username', None)
33+
password = request.json.get('password', None)
34+
if username != 'test' and password != 'test':
35+
return jsonify({"msg": "Bad username or password"}), 401
36+
37+
ret = {
38+
'access_token': create_access_token(identity=username),
39+
'refresh_token': create_refresh_token(identity=username)
40+
}
41+
return jsonify(ret), 200
42+
43+
44+
@app.route('/refresh', methods=['POST'])
45+
@jwt_refresh_token_required
46+
def refresh():
47+
current_user = get_jwt_identity()
48+
ret = {
49+
'access_token': create_access_token(identity=current_user)
50+
}
51+
return jsonify(ret), 200
52+
53+
54+
# Endpoint for listing tokens that have the same identity as you
55+
@app.route('/auth/tokens', methods=['GET'])
56+
@jwt_required
57+
def list_identity_tokens():
58+
username = get_jwt_identity()
59+
return jsonify(get_stored_tokens(username)), 200
60+
61+
62+
# Endpoint for listing all tokens. In your app, you should either not expose
63+
# this endpoint, or put some addition security on top of it so only trusted users,
64+
# (administrators, etc) can access it
65+
@app.route('/auth/all-tokens')
66+
def list_all_tokens():
67+
return jsonify(get_all_stored_tokens()), 200
68+
69+
70+
# Endpoint for allowing users to revoke their tokens
71+
@app.route('/auth/tokens/revoke/<string:jti>', methods=['PUT'])
72+
@jwt_required
73+
def change_jwt_revoke_state(jti):
74+
username = get_jwt_identity()
75+
try:
76+
token_data = get_stored_token(jti)
77+
if token_data['token']['identity'] != username:
78+
raise KeyError
79+
revoke_token(jti)
80+
return jsonify({"msg": "Token successfully revoked"}), 200
81+
except KeyError:
82+
return jsonify({'msg': 'Token not found'}), 404
83+
84+
85+
@app.route('/auth/tokens/unrevoke/<string:jti>', methods=['PUT'])
86+
@jwt_required
87+
def change_jwt_unrevoke_state(jti):
88+
username = get_jwt_identity()
89+
try:
90+
token_data = get_stored_token(jti)
91+
if token_data['token']['identity'] != username:
92+
raise KeyError
93+
unrevoke_token(jti)
94+
return jsonify({"msg": "Token successfully unrevoked"}), 200
95+
except KeyError:
96+
return jsonify({'msg': 'Token not found'}), 404
97+
98+
99+
@app.route('/protected', methods=['GET'])
100+
@jwt_required
101+
def protected():
102+
return jsonify({'hello': 'world'})
103+
104+
if __name__ == '__main__':
105+
app.run()

examples/loaders.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
from flask import Flask, jsonify, request
2+
from flask_jwt_extended import JWTManager, jwt_required, create_access_token
3+
4+
app = Flask(__name__)
5+
app.secret_key = 'super-secret' # Change this!
6+
jwt = JWTManager(app)
7+
8+
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
12+
def my_expired_token_callback():
13+
return jsonify({
14+
'status': 401,
15+
'sub_status': 101,
16+
'msg': 'The token has expired'
17+
}), 200
18+
19+
20+
@app.route('/login', methods=['POST'])
21+
def login():
22+
username = request.json.get('username', None)
23+
password = request.json.get('password', None)
24+
if username != 'test' and password != 'test':
25+
return jsonify({"msg": "Bad username or password"}), 401
26+
27+
ret = {'access_token': create_access_token(username)}
28+
return jsonify(ret), 200
29+
30+
31+
@app.route('/protected', methods=['GET'])
32+
@jwt_required
33+
def protected():
34+
return jsonify({'hello': 'world'}), 200
35+
36+
if __name__ == '__main__':
37+
app.run()

examples/refresh_tokens.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
from flask import Flask, jsonify, request
2+
from flask_jwt_extended import JWTManager, jwt_required, create_access_token, \
3+
jwt_refresh_token_required, create_refresh_token, get_jwt_identity
4+
5+
app = Flask(__name__)
6+
app.secret_key = 'super-secret' # Change this!
7+
jwt = JWTManager(app)
8+
9+
10+
@app.route('/login', methods=['POST'])
11+
def login():
12+
username = request.json.get('username', None)
13+
password = request.json.get('password', None)
14+
if username != 'test' and password != 'test':
15+
return jsonify({"msg": "Bad username or password"}), 401
16+
17+
# Use create_access_token() and create_refresh_token() to create our
18+
# access and refresh tokens
19+
ret = {
20+
'access_token': create_access_token(identity=username),
21+
'refresh_token': create_refresh_token(identity=username)
22+
}
23+
return jsonify(ret), 200
24+
25+
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.
31+
@app.route('/refresh', methods=['POST'])
32+
@jwt_refresh_token_required
33+
def refresh():
34+
current_user = get_jwt_identity()
35+
ret = {
36+
'access_token': create_access_token(identity=current_user)
37+
}
38+
return jsonify(ret), 200
39+
40+
41+
@app.route('/protected', methods=['GET'])
42+
@jwt_required
43+
def protected():
44+
username = get_jwt_identity()
45+
return jsonify({'hello': 'from {}'.format(username)}), 200
46+
47+
if __name__ == '__main__':
48+
app.run()

examples/simple.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from flask import Flask, jsonify, request
2+
from flask_jwt_extended import JWTManager, jwt_required, create_access_token
3+
4+
app = Flask(__name__)
5+
app.secret_key = 'super-secret' # Change this!
6+
7+
# Setup the Flask-JWT-Extended extension
8+
jwt = JWTManager(app)
9+
10+
11+
# Provide a method to create access tokens. The create_access_token() function
12+
# is used to actually generate the token
13+
@app.route('/login', methods=['POST'])
14+
def login():
15+
username = request.json.get('username', None)
16+
password = request.json.get('password', None)
17+
if username != 'test' and password != 'test':
18+
return jsonify({"msg": "Bad username or password"}), 401
19+
20+
ret = {'access_token': create_access_token(username)}
21+
return jsonify(ret), 200
22+
23+
24+
# Protect a view with jwt_required, which requires a valid access token in the
25+
# request to access.
26+
@app.route('/protected', methods=['GET'])
27+
@jwt_required
28+
def protected():
29+
return jsonify({'hello': 'world'}), 200
30+
31+
if __name__ == '__main__':
32+
app.run()

examples/token_freshness.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
from flask import Flask, jsonify, request
2+
from flask_jwt_extended import JWTManager, jwt_required, create_access_token, \
3+
jwt_refresh_token_required, create_refresh_token, get_jwt_identity, \
4+
fresh_jwt_required
5+
6+
app = Flask(__name__)
7+
app.secret_key = 'super-secret' # Change this!
8+
jwt = JWTManager(app)
9+
10+
11+
# Standard login endpoint. Will return a fresh access token and a refresh token
12+
@app.route('/login', methods=['POST'])
13+
def login():
14+
username = request.json.get('username', None)
15+
password = request.json.get('password', None)
16+
if username != 'test' and password != 'test':
17+
return jsonify({"msg": "Bad username or password"}), 401
18+
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.
22+
ret = {
23+
'access_token': create_access_token(identity=username, fresh=True),
24+
'refresh_token': create_refresh_token(identity=username)
25+
}
26+
return jsonify(ret), 200
27+
28+
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():
35+
username = request.json.get('username', None)
36+
password = request.json.get('password', None)
37+
if username != 'test' and password != 'test':
38+
return jsonify({"msg": "Bad username or password"}), 401
39+
40+
ret = {'access_token': create_access_token(identity=username, fresh=True)}
41+
return jsonify(ret), 200
42+
43+
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)
47+
@app.route('/refresh', methods=['POST'])
48+
@jwt_refresh_token_required
49+
def refresh():
50+
current_user = get_jwt_identity()
51+
ret = {
52+
'access_token': create_access_token(identity=current_user, fresh=False)
53+
}
54+
return jsonify(ret), 200
55+
56+
57+
# Any valid jwt can access this endpoint
58+
@app.route('/protected', methods=['GET'])
59+
@jwt_required
60+
def protected():
61+
username = get_jwt_identity()
62+
return jsonify({'hello': 'from {}'.format(username)}), 200
63+
64+
65+
# Only fresh jwts can access this endpoint
66+
@app.route('/protected-fresh', methods=['GET'])
67+
@fresh_jwt_required
68+
def protected_fresh():
69+
username = get_jwt_identity()
70+
return jsonify({'hello': 'from {}'.format(username)}), 200
71+
72+
if __name__ == '__main__':
73+
app.run()

flask_jwt_extended/__init__.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from .jwt_manager import JWTManager
2-
from .utils import (jwt_identity, jwt_claims, jwt_required, fresh_jwt_required,
3-
create_refresh_access_tokens, refresh_access_token,
4-
create_fresh_access_token)
2+
from .utils import (jwt_required, fresh_jwt_required, jwt_refresh_token_required,
3+
create_refresh_token, create_access_token, get_jwt_identity,
4+
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)